Programster's Blog

Tutorials focusing on Linux, programming, and open-source

Debian 9 - Set Up Nginx Reverse Proxy

I use a reverse proxy so that I can host multiple sites on different servers within a NAT. I forward ports 80 and 443 on my router to my reverse proxy, which then takes care of redirecting the traffic to the relevant servers. However, they can also be useful as a gateway for monitoring/restricting traffic, or to have a single point to maintain all your SSL certificates.

The setup below assumes you wish to have SSL enabled, but will forward the traffic in the encrypted form so as to not cause confusion on the final server. This is because I have the servers redirect the user if they don't detect https.

Steps

Install nginx

sudo apt update && sudo apt install nginx -y

Run the following command to set up the proxy configuration.

sudo echo 'proxy_redirect          off;
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;' | sudo tee /etc/nginx/proxy.conf

Adding A Site

For each site that you wish to proxy, run the following command after having changed the variables at the top:

DOMAIN="www.mydomain.com"
CONTAINER_IP="192.168.16.100"

echo "
server {
        listen 80;

        server_name `echo $DOMAIN`;

        access_log  /var/log/nginx/access.log;

        location / {
                proxy_pass      http://`echo $CONTAINER_IP`/;
                include         /etc/nginx/proxy.conf;
        }
}

server {
    listen 443 default_server ssl;

    ssl on;

    server_name `echo $DOMAIN`;

    access_log  /var/log/nginx/access.log;

    ssl_certificate      ssl/`echo $DOMAIN`.crt;
    ssl_certificate_key  ssl/`echo $DOMAIN`.key;

    ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers RC4:HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    keepalive_timeout    60;
    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;

    location / {
        proxy_pass      https://`echo $CONTAINER_IP`/;
        include         /etc/nginx/proxy.conf;
    }
}" | sudo tee /etc/nginx/sites-enabled/$DOMAIN

Then add the relevant SSL certificate files at:

/etc/nginx/ssl/[www.mydomain.com].crt
/etc/nginx/ssl/[www.mydomain.com].key

Reload Nginx

For your changes to take effect, you need to gracefully reload the configuration using the following command:

sudo invoke-rc.d nginx reload

If nginx fails to start, then check the log at /var/log/nginx/error.log. If the last line states: could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32 then simply uncomment the server_names_hash_bucket_size line in /etc/nginx/nginx.conf on line 23.

References