Quick Tip: Configuring NGINX and SSL with Node.js

Share this article

Quick Tip: Configuring NGINX and SSL with Node.js

NGINX is a high-performance HTTP server as well as a reverse proxy. Unlike traditional servers, NGINX follows an event-driven, asynchronous architecture. As a result, the memory footprint is low and performance is high. If you’re running a Node.js-based web app, you should seriously consider using NGINX as a reverse proxy.

NGINX can be very efficient in serving static assets. For all other requests, it will talk to your Node.js back end and send the response to the client. In this tutorial, we’ll discuss how to configure NGINX to work with Node.js. We’ll also see how to setup SSL in the NGINX server.

Note: Node also has a built-in HTTPS module and can be configured to read the necessary certificate files without the need for a reverse proxy. You can find out more about this in our article How to Use SSL/TLS with Node.js.

Installing NGINX

Assuming you already have Node.js installed on your machine (if not, check here), let’s see how to install NGINX.

Installation on Linux

If you’re running Ubuntu, you can use the following command to install NGINX:

sudo apt-get update
sudo apt-get install nginx

If you’re running a Linux distro other than Ubuntu, check out the NGINX installation docs for more information.

NGINX will start automatically once it’s installed.

Installation on macOS

If you’re on macOS, you can use Homebrew to install NGINX easily. The steps are as following:

  • Homebrew needs the directory /usr/local to be chown’d to your username. So, run the following command in terminal first:

    sudo chown -R 'username here' /usr/local
    
  • Now the following two commands will install NGINX on your system:

    brew link pcre
    brew install nginx
    
  • Once the installation is complete, you can type the following command to start NGINX:

    sudo nginx
    
  • The NGINX config file can be found here: /usr/local/etc/nginx/nginx.conf.

Installation on Windows

For Windows, head over to the NGINX downloads page and get the zip. The next step is unzipping the archive and moving to the directory in the command prompt as follows:

unzip nginx-1.3.13.zip
cd nginx-1.3.13
start nginx

As you can see, the command start nginx will start NGINX.

Now that the installation is done, let’s see how you can configure a simple server.

Setting Up a Node.js Server

First, let’s create a simple Node.js server. We’ll start by initiating a project and installing the Express package:

mkdir node-demo && cd node-demo
npm init -y
npm i express

Create a file called server.js, with the following contents:

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

You can start the server by running node server.js.

Configuring NGINX

Now let’s open up the NGINX default site config file:

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

If you want, you can go directly to the directory and open up the config file with your favorite text editor.

As you scroll down, you’ll find a server block. It looks something like this:

server {
  listen       80;
  server_name  localhost;

  ....
  more config goes here
}

Next, we’ll configure the server block to suit our needs. We want to configure NGINX to pass all requests through to our Node.js server. Replace the above server block with a new block as shown below:

server {
  listen       80;
  server_name  localhost;

  location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

As you can see, the web server will listen on http://localhost port 80. The location / block tells NGINX what to do with any incoming request. We use proxy_pass to point to our Node.js application, which is running at http://localhost:3000 in our case.

At this point, you should save the file and type the following to restart NGINX, depending on your operating system.

Ubuntu:

sudo service nginx restart

Or:

sudo /etc/init.d/nginx restart

macOS:

sudo nginx -s stop && sudo nginx

Windows:

nginx -s reload

Once this is done, you can go to http://localhost to see our proxy in action. Although you’re accessing the NGINX web server, you’ll get the actual response from the Node.js server.

Note: you’ll need to make sure there isn’t anything else (such as Apache) running on port 80.

Setting Up SSL

In order to create a secure connection with a user’s browser, we’ll need to obtain a digital certificate. Normally, you get one of these from a certificate authority such as Let’s Encrypt. If you go the Let’s Encrypt route, be sure to install the certificate using Certbot, which will take care of reconfiguring NGINX for you.

For local development (and for following along with this tutorial) you can also create a self-signed certificate. The only problem is that browsers will show a warning that the “Certificate is not Trusted” when someone visits your website. But for testing on your local machine that’s perfectly fine.

Once you have a certificate and a private key, you can set up SSL in NGINX. You need to modify our previous server block to the following:

server {
  listen       80;
  listen       443 ssl;
  server_name  localhost;

  ssl_certificate  /etc/nginx/ssl/server.crt;
  ssl_certificate_key /etc/nginx/ssl/server.key;

  location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}

That’s it!

Now, if you access https://localhost, your connection will be secure. The configuration above assumes that the certificate and private key are located at /etc/nginx/ssl/server.crt and /etc/nginx/ssl/server.key respectively, but you can change these locations if you wish.

Bonus: Serving Static Assets

An additional benefit of having NGINX set up in front of our Node.js server is that we can easily configure it to serve up any static assets our app requires. This will save the overhead of passing through these requests for Node to handle.

To do this, we need to add a new location block to the server configuration:

server {
  listen       80;
  server_name  localhost;

  location / {
    ...
  }

  location /public {
    root /usr/local/var/www;
  }
}

Inside this location block we set the root to /usr/local/var/www, but you can choose a different directory if you like. As a result, whenever there’s a request to something like http://localhost/public/somepath/file.html, NGINX will serve the file from /usr/local/var/www/public/somepath/file.html directly.

Conclusion

In this brief tutorial, we’ve seen how to use NGINX as a reverse proxy for our Node.js app and configure SSL. By using NGINX to handle the static resources, you can also take some load off your Node application.

Frequently Asked Questions (FAQs) on Configuring Nginx SSL with Node.js

What is the role of Nginx in SSL configuration with Node.js?

Nginx is a powerful web server and reverse proxy server. When configuring SSL with Node.js, Nginx plays a crucial role as it acts as a reverse proxy for your Node.js application. This means that it accepts all incoming connections and forwards them to your Node.js application. This setup provides an additional layer of security as your Node.js application is not directly exposed to the internet. Furthermore, Nginx can handle SSL termination, which offloads the computational burden of encrypting and decrypting SSL traffic from your Node.js application, thereby improving its performance.

How do I generate an SSL certificate for use with Nginx and Node.js?

To generate an SSL certificate, you can use a Certificate Authority (CA) like Let’s Encrypt. Let’s Encrypt provides free SSL certificates and has an automated process for certificate issuance. You can use the Certbot tool from Let’s Encrypt to automate the process of obtaining and renewing certificates. Once you have obtained your SSL certificate, you can configure Nginx to use this certificate for SSL termination.

How do I configure Nginx to use the SSL certificate?

Once you have your SSL certificate, you need to configure Nginx to use it. This involves editing the Nginx configuration file, typically located at /etc/nginx/nginx.conf or /etc/nginx/sites-available/default. In this file, you need to specify the location of your SSL certificate and private key, and set up a server block to listen on port 443 (the default port for HTTPS) and forward requests to your Node.js application.

What is SSL termination and why is it important?

SSL termination refers to the process of decrypting SSL traffic at the Nginx level before forwarding it to your Node.js application. This is important because it offloads the computational burden of encrypting and decrypting SSL traffic from your Node.js application, thereby improving its performance. Furthermore, it simplifies your Node.js application as it doesn’t need to handle SSL traffic directly.

How do I redirect HTTP traffic to HTTPS in Nginx?

To redirect HTTP traffic to HTTPS, you need to set up a server block in your Nginx configuration file that listens on port 80 (the default port for HTTP) and redirects all requests to HTTPS. This ensures that all traffic to your site is encrypted, providing better security for your users.

How do I troubleshoot issues with Nginx and SSL?

If you’re having issues with Nginx and SSL, there are several steps you can take to troubleshoot. First, check the Nginx error logs, typically located at /var/log/nginx/error.log. These logs can provide valuable information about any issues. Second, verify your Nginx configuration using the command “nginx -t”. This will check your configuration for syntax errors. Finally, ensure that your SSL certificate is valid and correctly installed.

How do I renew my SSL certificate?

If you’re using Let’s Encrypt and Certbot, you can automate the renewal process with a cron job or systemd timer. Certbot includes a renew command that checks all certificates installed on the system and renews them if they’re close to expiring. By default, Let’s Encrypt certificates are valid for 90 days.

How do I secure my Nginx configuration?

There are several steps you can take to secure your Nginx configuration. First, ensure that all traffic is redirected to HTTPS. Second, disable any weak SSL protocols and ciphers. Third, enable HTTP Strict Transport Security (HSTS) to ensure that browsers always connect to your site over HTTPS. Finally, regularly update Nginx to the latest version to benefit from the latest security patches.

Can I use Nginx with multiple Node.js applications?

Yes, you can use Nginx as a reverse proxy for multiple Node.js applications. Each application would have its own server block in the Nginx configuration file, with a unique server name and port number. This allows you to host multiple Node.js applications on the same server, each accessible via a different domain or subdomain.

How do I test my Nginx SSL configuration?

You can test your Nginx SSL configuration using the SSL Labs Server Test. This free online tool performs a deep analysis of your SSL configuration and provides a detailed report, including a grade for your configuration. It checks for issues like weak ciphers, SSL protocol support, and certificate validity.

Nilson JacquesNilson Jacques
View Author

Nilson is a full-stack web developer who has been working with computers and the web for over a decade. A former hardware technician, and network administrator. Nilson is now currently co-founder and developer of a company developing web applications for the construction industry. You can also find Nilson on the SitePoint Forums as a mentor.

ColinILearn-Node-JSnginxssl
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week