Programming, robotics, traveling

16 Apr 2020

Nginx Reverse Proxy

Nginx reverse proxy needs where we want to get access to few resources by one external IP address and port.

I used that for several http web services (debian repository, my website and phpmyadmin). The following config is pairing server_name and proxy_pass as target location. Pleese look at last section with default_server atribute. It needs to set default site (in this case page with 501 Internal Error).

Quickstart

  1. Create webproxy.conf with your data:

    cat << EOF | sudo tee webproxy.conf > /dev/null
    # Don't show server's version
    server_tokens off;
    
    server {
        listen          80 default_server;
        server_name     _;
        location / {
            return 501;
        }
    }
    
    server {
        listen          80;
        server_name     hostname1 hostname2;
        location / {
            proxy_pass  http://hostname3:1080/;
        }
    }
    
    server {
        listen          80;
        server_name     hostname4;
        location / {
            proxy_pass  http://8.8.4.4:80/;
        }
    }
    
    server {
        listen          80;
        server_name     hostname5;
        location / {
            proxy_pass  http://8.8.8.8:3080/;
        }
    }
    EOF
    

    If you wanna use SSL wrapper for HTTP host you can set next options:

    server {
        listen       443 default_server ssl;
        listen  [::]:443 default_server ssl;
    
        server_name     hostname4;
    
        ssl_certificate     /path_to_cred.crt;
        ssl_certificate_key /path_to_cred.key;
    
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
    
        location / {
            proxy_pass  http://8.8.4.4:80/;
        }
    }
    

    Permanent redirect HTTP to HTTPS (source):

    server {
        listen  80;
        server_name hostname4;
        return 301 https://$server_name$request_uri; # enforce https
        # rewrite ^(.*) https://www.example.com$uri permanent;
    }
    

    Also you may need to throw or set some HTTP headers:

    proxy_http_version    1.1;
    proxy_set_header      Upgrade $http_upgrade;
    proxy_set_header      Connection "upgrade";
    proxy_set_header      Host $host;
    proxy_cache_bypass    $http_upgrade;
    
  2. Download preparing nginx image from DockerHub and run webproxy in the container:

    docker run \
        --detach=true \
        --log-driver=syslog \
        --restart=always \
        --name=webproxy \
        --publish 80:80 \
        --volume ./webproxy.conf:/etc/nginx/conf.d/default.conf \
        nginx:1.17.8-alpine /usr/sbin/nginx -g "daemon off;"
    

Also you can download docker-webproxy.service file.

Scratches

In an ideal situation I want to set name of container, a local port (inside that container), external domain names and owner email.

I woudn’t want to throw in a container to any networks or set any env variables.

docker inspect -f "{{ .NetworkSettings.GlobalIPv6Address }}" webproxy
docker inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" webproxy