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.


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;

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.


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

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:// to HTTPS://

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

sudo su
crontab -e


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


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_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/ {

In the example above the reverse proxy is applied only to the directory proxied_page to another host ( 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 /
ProxyPass /directory
ProxyPass /another_directory

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

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

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.


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


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