Skip to main content

Quick Tip: Configuring NGINX and SSL with Node.js

By Nilson Jacques

JavaScript

Share:

Free JavaScript Book!

Write powerful, clean and maintainable JavaScript.

RRP $11.95

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

Learn PHP for free!

Make the leap into server-side programming with a comprehensive cover of PHP & MySQL.

Normally RRP $11.95 Yours absolutely free

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.

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.

New books out now!

Learn valuable skills with a practical introduction to Python programming!


Give yourself more options and write higher quality CSS with CSS Optimization Basics.