NginxProxyManager / nginx-proxy-manager

Docker container for managing Nginx proxy hosts with a simple, powerful interface
https://nginxproxymanager.com
MIT License
22.6k stars 2.62k forks source link

IPv6 not supported #149

Closed epelaez1 closed 4 years ago

epelaez1 commented 5 years ago

Describe the bug

To Reproduce Steps to reproduce the behavior:

  1. Enable IPv6 for docker:

    • Create a network at docker with the following command: $ docker network create --subnet 2a02::/80 --ipv6 network_name Replace 2a02:: with the IPv6 block given by your ISP, or, in case you don't have IPv6 support use a block reserved for NAT, (for example: fe80:10::/80). I will use 2a02:10::/80 in this example.
  2. Create the dockers:

    • Create the docker of mariadb inside that network: $ docker pull mariadb $ docker create --name=mariadb -e MYSQL_ROOT_PASSWORD=your_password -v ~/docker_data/mariadb:/var/lib/mysql --network network_name --ip6 2a02:10::10 mariadb $ docker start mariadb
    • Create a database called nginx: $ docker run -it --network network_name --rm mariadb mysql -hmariadb -uroot -p Enter your password MariaDB [(none)]> CREATE DATABASE nginx;
    • Edit the config.json file.
    • Create the nginx proxy manager docker: $ docker pull jc21/nginx-proxy-manager:latest $ docker create --name=reverse_proxy --restart unless-stopped -v ~/docker_data/proxy/config.json:/app/config/production.json -v ~/docker_data/proxy/data:/data -v ~/docker_data/proxy/letsencrypt:/etc/letsencrypt --network network_name --ip6 2a02:10::11 jc21/nginx-proxy-manager $ docker start reverse_proxy
  3. Everything should work until this point.

  4. Access the web ui with Google Chrome using the IPv6 address of the docker. http://[2a02:10::11]:81

  5. Try to login with admin@example.com and changeme as credentials. The web responds with an Internal Error. And if you check the logs of the docker you should see the following message: [Express ] › ⚠ warning data should match pattern "^[a-z\-]+:\/\/(?:[\w\-\.]+(:[0-9]+)?/?)?$"

  6. Now restart the docker: $ docker stop reverse_proxy $ docker start reverse_proxy And now the following error apears: [emerg] 320#320: invalid port in resolver "fe80::something%2" in /etc/nginx/conf.d/include/resolvers.conf:1 nginx: [emerg] invalid port in resolver "fe80::something%2" in /etc/nginx/conf.d/include/resolvers.conf:1 Beeing fe80::something the local IPv6 of the docker created before.

Operating System

Important comments about IPv6 In order to get access from outside the host you probably need to run the following commands:

(Replace eth0 with your network adapter name (see ifconfig)) (Replace 2a02:10::11 with the address used for the container) $ sysctl net.ipv6.conf.eth0.accept_ra=2 $ sysctl net.ipv6.conf.eth0.proxy_ndp=1 $ ip -6 neigh add proxy 2a02:10::11 dev eth0

If you are using a local IPv6 block (fe80::/80) you don't need this commands.

I know that IPv6 is not an easy thing to work with but I hope you can fix this bug.

jc21 commented 4 years ago

Resolved in v2.2.2

PKizzle commented 4 years ago

I still receive the mentioned Internal Error when trying to access the web ui using IPv6. However the IPv6 configuration is valid and works for other docker containers. Accessing the UI via IPv4 works without any issues.

The ajax request to /api/tokens seems to be the issue. It returns an error code 400.

jc21 commented 4 years ago

That's strange - if you can inspect the files inside your running docker container, specifcally /etc/nginx/conf.d/production.conf the configuration should mention listen [::]:81 default; without a preceding comment.

Are you accessing the admin interface directly on port 81 or do you have it behind a Proxy Host?

PKizzle commented 4 years ago

This is the content of the file you mentioned:

# Admin Interface
server {
    listen 81 default;
    listen [::]:81 default;

    server_name nginxproxymanager;
    root /app/frontend;
    access_log /dev/null;

    location /api {
        return 302 /api/;
    }

    location /api/ {
        add_header            X-Served-By $host;
        proxy_set_header Host $host;
        proxy_set_header      X-Forwarded-Scheme $scheme;
        proxy_set_header      X-Forwarded-Proto  $scheme;
        proxy_set_header      X-Forwarded-For    $remote_addr;
        proxy_pass            http://127.0.0.1:3000/;
    }

    location / {
        index index.html;
        if ($request_uri ~ ^/(.*)\.html$) {
            return 302 /$1;
        }
        try_files $uri $uri.html $uri/ /index.html;
    }
}

I am directly accesing the admin UI without any proxy http://[${IPV6_ADDR}]:81/login

This is the response from the ajax request to /api/tokens: {"error":{"code":400,"message":"Internal Error"}}

jc21 commented 4 years ago

So the docker logs for that container should have some more info about the internal error?

jc21 commented 4 years ago

Fix the login, it was a cors issue which wasn't expecting a ipv6 address in the referring url.

jc21 commented 4 years ago

Pull the latest or 2.2.2 or 2 images to get this fix.

PKizzle commented 4 years ago

Thank you very much. The issue is now fixed.

JonasVgt commented 3 years ago

I have a very similar Problem. but pulling latest, 2.2.2, 2 doesn't seem to help. When using only ipv4, there is no Problem but when creating a docker-network with sudo docker network create --ipv6 --subnet fd12:3456:789a:1::/64 --subnet 172.23.0.0/16 nginx_default --attachable and then running docker-compose with the following file:


version: '3'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    ports:
      - '80:80' #http traffic
      - '81:81' #dashboard
      - 443:443 #https traffic
    environment:
      DB_MYSQL_HOST: "db"
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "<USER>"
      DB_MYSQL_PASSWORD: "<PASS>"
      DB_MYSQL_NAME: "nginx"
      DISABLE_IPV6: 'false'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    restart: always
  db:
    image: 'yobasystems/alpine-mariadb:latest'
    environment:
      MYSQL_ROOT_PASSWORD: '<ROOT_PASS>'
      MYSQL_DATABASE: 'nginx'
      MYSQL_USER: '<USER>'
      MYSQL_PASSWORD: '<PASS>'
    volumes:
      - /srv/dev-disk-by-uuid-3fc1b3a4-7cc8-4262-ab30-8611d1e40119/Databases/nginx:/var/lib/mysql
    restart: always

networks:
  default:
    ipam:
      driver: default
      config:
        - subnet: "fd12:3456:789a:1::/64"

the webinterface doesn't start, the app is marked as 'unhealthy' and it produces this Error in the log files:

nginx: [emerg] invalid IPv6 address in resolver "[fe80::abd:43ff:feca:7350%2]" in /etc/nginx/conf.d/include/resolvers.conf:1
finish: applet not found

The weird thing is, that this used to work without problems two days ago, but after restarting the server the error emerged. I am running Raspbian GNU/Linux 10 (buster) on a Raspberry Pi 4B. I have tried fixing the problem now for a few hours without luck.

JonasVgt commented 3 years ago

I did some a little bit more research. I don't really know what I am talking about but here is what I found. The Problem seems to be, that somehow /etc/resolv.conf inside the container looks like this:

search jonas.local
nameserver 127.0.0.11
nameserver fd00::3a10:d5ff:fe77:c05d
nameserver fe80::abd:43ff:feca:7350%2
options ndots:0

I Think this file is copied from the file /etc/resolv.conf from outside the container when creating the container and then converted to /etc/nginx/conf.d/include/resolvers.conf which looks like this: resolver 127.0.0.11 [fd00::3a10:d5ff:fe77:c05d] [fe80::abd:43ff:feca:7350%2] And that's where the problem lies, because nginx doesn't seem to like, that there is a %2at the end of one ip-address.

As I said before I don't really know, how that %2 came into the resolv.conf file in the first place, but I will try to figure that out.

This Problem might be fixed by changing the conversion from the resolv.conf to resolvers.conf. in the file nginx-proxy-manager/docker/rootfs/etc/services.d/nginx/run of this repository.