Reverse proxy with NGINX and letsencrypt tutorial

If you want to expose a web application, a backend interface, or just secure your website you should always use a reverse proxy. A reverse proxy will listen for client web requests and forwards them directly to your app or website. In this tutorial, I will explain how you can easily set up a reverse proxy with NGINX. And I will show you how you can easily secure any app or website with trusted HTTPS certificates from letsencrypt.


Install NGINX reverse proxy on Linux

First, we will install NGINX on Linux. I’m using Ubuntu 20.04 LTS in this example, but you can find installation instructions for other distributions in the official documentation. On Ubuntu, you simply need to update your package sources and install the package “nginx”.

sudo apt update
sudo apt install nginx

After you have installed NGINX, you can find the configuration files in the /etc/nginx folder.


Expose a sample web app in NGINX reverse proxy

I’ve prepared a sample web application, which will just print “Hello World”. It’s an unsecured web application that will run on port 5000 and is only listening for internal connections. This is a perfect example when you want to secure any web application with trusted HTTPS certificates to securely expose it to the public internet.

Note, you should never allow direct access to your app, otherwise, users could possibly just bypass the reverse proxy. I’ve changed the listening address from 0.0.0.0 to 127.0.0.1, that our app is only accepting connections from localhost.  Or you can simply add a firewall rule, that prevents access from outside to your web application. This is important because we want to force all users to use the reverse proxy instead of accessing our web application directly!

To enable the reverse proxy feature in NGINX, we will create a new “default” configuration file in the /etc/nginx/sites-enabled directory.

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name research.the-digital-life.com;

        location / {
                proxy_pass http://127.0.0.1:5000;
        }
}

The proxy_pass argument will forward all incoming client requests to this server to our app. You can easily change the protocol, IP, or port to whatever your app or website is listening to.

If you want to specify further arguments, you can do this within the server {} section or directly in the location / {} section. For example, I will add the proxy_set_header directive to pass the Host-Header which may be required by some apps or websites exposed by the proxy.

        location / {
                proxy_pass http://127.0.0.1:5000;
		proxy_set_header Host $host
        }

Expose the app in NGINX reverse proxy with trusted HTTPS certificates from letsencrypt

Now, let’s obtain trusted HTTPS certificates for our application. It’s also best practice to redirect all unencrypted HTTP connections to HTTPS. This is relatively easy with certbot and letsencrypt certificates. The certbot will obtain free certificates and also handle the renewal process automatically. To do that we will install certbot and also a plugin for our NGINX server.

sudo apt install certbot python3-certbot-nginx

Once we have installed those packages, we can obtain our certificates.

sudo certbot --nginx -d research.the-digital-life.com

It will ask you if you want to redirect all traffic from HTTP to HTTPS. Select yes (2). This automatically makes some changes to our NGINX default configuration.

server {

  server_name research.the-digital-life.com;
 
  location / {
    proxy_pass http://127.0.0.1:5000;
  }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/research.the-digital-life.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/research.the-digital-life.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = research.the-digital-life.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

  listen 80 default_server;
  listen [::]:80 default_server;

  server_name research.the-digital-life.com;
    return 404; # managed by Certbot
}

Let’s also check the auto-renewal.

certbot renew --dry-run

Learn how to set up a webserver with docker in just 15 minutes

9 thoughts on “Reverse proxy with NGINX and letsencrypt tutorial”

  1. Christian

    Re your reverse proxy with ngnx and letsencrypt tutorial -thank you. I have a slightly harder problem that I am hoping you have experience with to help me fix my issue.

    I have four raspberry pi’s – one acts as a reverse proxy running nginx and the remaining three are dedicated wordpress websites each running apache2. Each website is a different domain.

    I use letsencrypt to obtain SSL certificates for all three domains from the reverse proxy. No issue with the certbot certificates.

    Any idea how to configure each domain’s .conf file in /etc/nginx/sites-available? Nginx keeps responding with a 504 timeout communicating with the upstream server.
    Thanks

    Reply
  2. Hello,

    I am using mailcow dockirized and when I try to install NGINX at the end of the installation it says „Not attempting to start NGINX, port 80 is already in use.

    When checking with the command SYSTEMCTL STATUS NGINX indicates that „Active: inactive (dead)“…

    What could I do to correct since I want to use PORTAINER with letsencrypt?

    Reply
  3. Hello,

    I am using mailcow dockirized and when I try to install NGINX at the end of the installation it says „Not attempting to start NGINX, port 80 is already in use.

    When checking with the command SYSTEMCTL STATUS NGINX indicates that „Active: inactive (dead)“…

    What could I do to correct since I want to use PORTAINER with letsencrypt?

    Reply
  4. I have deleted “default” file in /sites-available and only “default” file is present in /sites-enabled but after first configuration, it is not possible to reload nginx, because “nginx -t” see this error “nginx: [emerg] a duplicate listen 0.0.0.0:80 in /etc/nginx/sites-enabled/default:2”. I have read this guide, but it is not possible to start nginx, can you help me? thank you, Carmine

    Reply

Leave a Comment

I accept the Privacy Policy