In this tutorial, we will go through:

  • Installing and configuring NGINX,
  • Installing and configuring SSL/TLS,
  • Configuring NGINX as a reverse proxy for:
    • A whole site,
    • A directory of a site.

Requirements:

sudo apt update && sudo apt upgrade -y
sudo apt install nginx -y
sudo nano /etc/nginx/sites-available/default

Change the following configuration with your domain:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/html;
    server_name example.com www.example.com;
}

Check the configuration and restart the server:

nginx -t && nginx -s reload

Access your website in a browser and note that it is labeled as an insecure connection.


SSL/TLS

Install Certbot and run it against your domain:

sudo apt-get install certbot python3-certbot-nginx -y
sudo certbot --nginx

Only on the first run will it ask that many questions.

Alternatively, you can specify the domain directly to skip a step:

sudo certbot --nginx -d example.com -d example2.com

Reload the server and refresh the browser to verify that it automatically redirects to a secure connection:

nginx -s reload

The browser will redirect from HTTP://example.com to HTTPS://example.com.

Create a cron job under the root user to automatically renew the certificate before it expires every 90 days:

sudo su
crontab -e

Append:

0 12 * * * /usr/bin/certbot renew --quiet

REVERSE PROXY

To avoid CPU overload from multiple encrypted sessions, it is recommended to use a regular HTTP connection internally when possible (e.g. within a restricted VLAN).

Edit the virtual server configuration:

sudo nano /etc/nginx/sites-available/default

Applying the reverse proxy to the root of the website.

Look for the location { … } block and update it as follows:

location / {
    proxy_pass http://127.0.0.1:5000;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

This configuration forwards traffic to the specified host and port. The example above forwards to localhost on port 5000, which could be a Docker application listening on that port.

The lines in orange are optional and pass metadata to the backend application if needed.

Applying the reverse proxy to a directory of the website.

Add a location block for the target directory:

location /proxied_page/ {
    proxy_pass http://192.168.1.7;
}

In this example, the reverse proxy applies only to the proxied_page directory and forwards requests to another host (192.168.1.7) on the private network over the default HTTP port.


BONUS: Reverse Proxy with Apache

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests

Add the following lines to your site configuration file as needed:

ProxyPreserveHost On
ProxyPass / http://10.1.1.1:8080/
ProxyPass /directory http://192.168.1.1/
ProxyPass /another_directory http://172.16.1.1/dir/

Restart the service:

sudo apachectl configtest
sudo systemctl restart apache2.service

The reverse proxy can also act as a load balancer:

<Proxy balancer://cluster>
    BalancerMember http://webserver1
    BalancerMember http://webserver2
</Proxy>

ProxyPreserveHost On
ProxyPass / balancer://cluster/
ProxyPassReverse / balancer://cluster/

You can also apply health checks to the cluster members:

<Proxy balancer://cluster>
    BalancerMember "http://webserver1" hcmethod=HEAD hcinterval=1 hcpasses=9 hcuri=/app/status
    BalancerMember "http://webserver2" hcmethod=HEAD hcinterval=1 hcpasses=9 hcuri=/app/status
</Proxy>

On the backend host (where the web application runs), if it is also running Apache:

  • Logs will show the remote IP address of the reverse proxy server for all clients.
  • To fix this, the mod_remoteip module must be enabled and configured as follows.
sudo a2enmod remoteip
sudo nano /etc/apache2/apache2.conf

Append the line:

RemoteIPHeader X-Forwarded-For

Update the following line.

From:

LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

To:

LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

Then check the configuration and apply the changes:

sudo apachectl configtest && sudo systemctl restart apache2