Adding SSL/TLS (HTTPS) to Nginx Reverse Proxy with Node Application Server on Ubuntu 22.04

Prasad Beligalage
6 min readOct 28, 2022

--

In this tutorial let’s learn how to create a Nginx Reverse Proxy with SSL/TLS layer (HTTPS) for a Node Application Server.

Prerequisites

You need;

  • A latest Ubuntu server or desktop version where Nginx is installed.
  • A Node Application Server which is listening on your preferred port.
  • A valid domain name

The Node Application Server that I am using here, listens on port 3030 and it’s accessible via http://localhost:3030 address. You can run your app on your preferred port, but please make sure to use the correct port in the configuration file we are going to create later.

For all the examples in this tutorial, I use strawberry.gleeze.com as the domain name, so please make sure to replace strawberry.gleeze.com with your domain name. If you don’t have a domain name, you can get a free subdomain (as I have used in this tutorial) from a free subdomain provider such as dynu.

If you haven't setup Nginx reverse proxy for HTTP before, or you don’t have a Node Application ready, then read this article. It explains how to create a basic Node Application, Install Nginx and setup reverse proxy for HTTP.

Why should you make your application or website HTTPS?

With HTTP communication, the data is plain and therefore it can be read by anyone. When you use SSL or TLS along with HTTP, the data is always encrypted and cannot be read by any intermediate person. When you use HTTP with SSL or with TLS, we call it Secured HTTP or HTTPS in short. HTTPS communication is always encrypted and therefore it is a secured way to communicate with a server.

However, the Secure Socket Layer (SSL) protocol is considered to be obsolete now. Therefore, Transport Layer Security (TLS) is used more often today instead of SSL. When you use TLS to make your HTTP connection secured, a TLS handshake takes place before the actual communication begins. During this handshake, client and server negotiate and create a secret key which they will use later for encryption.

Ok, let’s begin the HTTPS setup;

We will do the setup in two steps;

  1. Create the certificates and keys
  2. Create the Nginx Reverse Proxy Server blocks.

Let’s start with the first step. When you get the SSL certificate from the Certificate Authority (CA), you should get three files, a private key file, SSL certificate file and a certificate bundle (intermediate certificate or chain certificate) file.

However, For HTTPS setup, we need only two files.

The first file we need is the private key that is issued by the Certificate Authority. This key can easily be found within your set of keys issued by CA. It usually has the naming convention xxxx.pivate.key. Find the file and rename it to your domain name, in my case it is strawberry.gleeze.com.private.key

The second file is the concatenated TLS certificate file which is a combination of the certificate file and the certificate bundle (intermediate or chain certificate) file. In order to create the concatenated certificate file, follow these steps.

  1. Create new file called strawberry.gleeze.com.certificate.cer and open it in a text editor.
  2. Open the SSL/TLS certificate file in a text editor and copy all content.
  3. Then paste it in the newly created file. The last line would look like `— END CERTIFICATE — `.
  4. Then open the certificate bundle file in a text editor (intermediate or chain certificate) and copy the content (without spaces).
  5. Now go to the end of the newly created file (strawberry.gleeze.com.certificate.cer), and press “enter” to go to the next line (immediate line after — END CERTIFICATE — ).
  6. Now paste the copied content right under the — END CERTIFICATE — line. (Make sure not to keep white spaces when copying and pasting)

As an alternative to the above six steps (or if you want to use just the command line), you can run the following command. Assume the SSL/TLS certificate is certificate.cer and certificate bundle or intermediate certificate file is certificate.bundle.cer and the concatenated certificate file is strawberry.gleeze.com.certificate.cer.

$ cat certificate.cer certificate.bundle.cer > strawberry.gleeze.com.certificate.cer

Now we have our second file ready, which is; strawberry.gleeze.com.certificate.cer

So, here are the two files;

  • The private key file 🡺 strawberry.gleeze.com.private.key
  • The certificate bundle file 🡺 strawberry.gleeze.com.certificate.cer

I have saved both these files in the /home/ssl/ directory and you can save them in your preferred location.

The second step is to create the Nginx server blocks. First, create a new configuration file in the /etc/nginx/ssl-available directory.

cd /etc/nginx/ssl-available

Now create a new file with your domain name. Here, I am using the VIM editor, but you can use any text editor you wish.

vim strawberry.gleeze.com

Now, follow the instructions below carefully, to create the configuration file.

  • HTTPS port number is 443 and therefore the server has to listen on port 443 for client requests. So let’s start by adding the code below;
listen 443 ssl;listen [::]:443 ssl;
  • Thereafter you have to mention the location of the certificate bundle file and the private key that we have created before. Please make sure to change the file path and the file name to yours.
ssl_certificate /home/ssl/strawberry.gleeze.com.certificate.cer;ssl_certificate_key /home/ssl/ strawberry.gleeze.com.private.key;
  • Now create a location block. The proxy_pass directive is used to forward the traffic to the Node application server which is running on http://localhost:3030.
location / {
proxy_pass http://localhost:3030;
}
  • You can also add more configuration to the location block. Note that these are additional configuration and not required to create the reverse proxy.

Set the HTTP version; The default value is set to HTTP version 1.0, so it’s recommended to use the HTTP version 1.1.

proxy_http_version 1.1;

Overriding default header values can be done using proxy_set_header directive.

The Host value is by default set to $http_host which gives both the hostname and port number. You can replace this as below, so the Host will contain only the server name.

proxy_set_header Host $host;

If you check the remote client IP of the request header in the Node app, it will show 127.0.0.1. This is because our Node app doesn’t see the client directly, instead it see the Nginx reverse proxy which stays in between the client and the Node app. So, in order to forward the actual client IP address to the Node app (in the request header), use the code below;

proxy_set_header client-ip $remote_addr;

Refer to this article to learn how to add more optional configuration such as log files.

  • Now we are almost there, but we will have one more change. This is because our Server Block accepts both HTTPS requests and HTTP requests. Therefore, it’s a good practice to rewrite the URL of all HTTP requests to HTTPS. You can use the rewrite directive inside another new server block listening on port 80. This is our second server block and we will add this right after the SSL/TLS server block we created above.
server {    listen 80;    listen [::]:80;    server_name strawberry.gleeze.com www.strawberry.gleeze.com;    #Add the rewrite directive as below    return 301 https://$host$request_uri;}

Now let’s add everything we have done in step one and step two, into a single configuration file.

server{  listen 443 ssl;  listen [::]:443 ssl;  ssl_certificate /home/ssl/strawberry.gleeze.com.certificate.cer;  ssl_certificate_key /home/ssl/ strawberry.gleeze.com.private.key;  server_name strawberry.gleeze.com www.strawberry.gleeze.com;  location / {    proxy_pass http://localhost:3030;    #Optional configuration    proxy_http_version 1.1;    proxy_set_header Host $host;    proxy_set_header client-ip $remote_addr;  }}#Create a new server block to rewrite http to httpsserver {  listen 80;  listen [::]:80;  server_name strawberry.gleeze.com www.strawberry.gleeze.com;  #Add the rewrite directive as below  return 301 https://$host$request_uri;}

Next we have to create a symbolic link from the /etc/nginx/sites-enabled directory to the file we’ve just created. First you have to navigate to the sites-enabled directory before you create the symbolic link.

cd /etc/nginx/sites-enabledln -s /etc/nginx/sites-available/strawberry.gleeze.com /etc/nginx/sites-enabled/strawberry.gleeze.com

In order to test the changes, restart Nginx and enter the URL with https in the address bar and you should be able to see that your Node app responds to HTTPS.

systemctl restart nginx

https://strawberry.gleeze.com

Once SSL installation is done, you can use any SSL Checker such as digicert, geotrust etc. to validate your SSL installation. If everything looks good, the SSL checker will tell you with green colour as in the image below.

That’s it and now your Node application server is secured with SSL/TLS protocol. Thanks for reading this tutorial and if you have any questions, please feel free to comment below.

--

--