Debian - 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 TLSv1.2 TLSv1.3;
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
TLSv1.3
, which only works when you are using OpenSSL version 1.1.1 or higher. You can check this by running the command openssl version
.
If you are running an older version, just remove this protocol from the list.
Then add the relevant SSL certificate files at:
/etc/nginx/ssl/[www.mydomain.com].crt
/etc/nginx/ssl/[www.mydomain.com].key
Optional - Redirect HTTP Traffic Instead
If you want to redirect HTTP traffic to HTTPS, then change the first server directive to:
server {
listen 80;
server_name $DOMAIN;
access_log /var/log/nginx/access.log;
location / {
return 301 https://$DOMAIN$request_uri;
}
}
$DOMAIN
variable, but not the $request_uri
variable, which is actually for NGINX to dynamically input the request URI.
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
/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.
Allowing EventSource / Server-sent Events
For my WebRTC project, I make use of a permanent stream connection between the server and the client. This requires that the messages go straight through, without any kind of buffering/chunking, which the proxy could interfere with. In order to get that to still work, add the following lines to the configuration of that specific site:
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
References
- Programster - Ubuntu - Reverse Proxy Dockerized Websites
- Stack Overflow - EventSource / Server-Sent Events through Nginx
First published: 5th December 2018