In this tutorial, we will go through:

  • Install and configure NGINX,
  • Install and configure SSL/TLS,
  • Configure 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 using your web browser and note that is labeled as an insecure connection.


SSL/TLS

Install the Cerbot and execute it against your :

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

Only on the first time it will ass that many questions.

Alternatively, the domain could be specified to skip one step.

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

Reload the server and refresh the browser to verify that it was automatically redirected to a secure connection.

nginx -s reload

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

Create a cron job using the root user to automatically renew the certificate that will expire every 90 days:

sudo su
crontab -e

Append:

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

REVERSE PROXY

To prevent CPU overload with multiple encrypted sessions it is recommended to use regular HTTP connection internally when possible (restricted VLAN for example).

Edit the virtual server configuration:

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

Applying the reverse proxy to the root of the website.

Edit the virtual server configuration:

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

Look for the location { … } block.

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 will forward the traffic to the host and port defined. The example above will forward to localhost under port 5000, which could be a docker application listening on this port.

All the lines in orange are optional and will provide metadata to the hidden application if necessary.

Applying the reverse proxy to a directory of the website.

Create a location block to the desired directory.

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

In the example above the reverse proxy is applied only to the directory proxied_page to another host (192.168.1.7) in the private network on the default HTTP port.


BONUS: Reverse Proxy with Apache

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

Include the following lines accordingly to your need in the site configuration file:

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

Additionally, 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 nodes of the members of the cluster:

<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>

Moreover, on the host side (where the web application is running) if it is running Apache too:

  • The logs will contain the Remore Address IP of the reverse proxy server for all clients.
  • To fix this issue the module mod_remoteip must be enabled and configured as follows.
sudo a2enmod remoteip
sudo nano /etc/apache2/apache2.conf

Append the line:

RemoteIPHeader X-Forwarded-For

Change 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