JavaScript
Article

Configuring Nginx and SSL with Node.js

By Sandeep Panda

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 are 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 backend and send the response to the client. In this tutorial we will discuss how to configure Nginx to work with Node.js. We will also see how to setup SSL in the Nginx server.

Installing Nginx

Assuming you already have Node.js installed on your machine let’s see how to install Nginx.

Installation on Mac

If you are on Mac 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 Ubuntu

If you are running Ubuntu you can use the following command to install Nginx:

sudo apt-get update
sudo apt-get install nginx

Once Nginx is installed it will start automatically.

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 following:

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. If you want you can download a simple Express based app from here. Once you have the code, extract it and move to the demoApp directory in your terminal. Next, enter the following commands to start the server on port 3000.

npm install
node bin/www
[code]

<h2 id="configuring-nginx">Configuring Nginx</h2>
<p>Now let's open up Nginx config file. As I am on Mac, I can just use nano to start editing the file:</p>

[code]
nano /usr/local/etc/nginx/nginx.conf

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 will find a server block. It looks something like this:

server {
  listen       8080;
  server_name  localhost;
    
  ....
  more config goes here
}

Next, we will configure the server block to suit our needs. We want to serve static files from our website with the help of Nginx and pass all other requests to our Node.js backend. So, replace the above server block with a new block as shown below:

server {
  listen       8080;
  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;
  }

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

}

As you can see our Nginx server listens on http://localhost:8080. The location / block tells Nginx what to do when any request comes. Inside the location block we use proxy_pass to point to the Node.js backend which is http://localhost:3000 in our case.

Now we need another block location /public to tell Nginx how to serve static assets. Inside this location block we set the root to /usr/local/var/www. You can choose a different directory if you like. As a result whenever there is a request like http://localhost:8080/public/somepath/file.html Nginx will serve the file from /usr/local/var/www/public/somepath/file.html.

At this point you should save the file and type the following to restart Nginx:

Mac:

sudo nginx -s stop && sudo nginx

Ubuntu:

sudo service nginx restart

Or

sudo /etc/init.d/nginx restart

Windows:

nginx -s reload

Next, let’s serve our stylesheet from Nginx instead of Node.js. Our Node.js template uses a stylesheet with the URL /public/stylesheets/style.css. Create a file named style.css inside the directory /usr/local/var/www/public/stylesheets and Nginx will serve it correctly. For example, you can put the following CSS in style.css:

body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
  color: #00B7FF;
}

Once this is done you can go to http://localhost:8080 to see our app in action. Although you are accessing the Nginx server you will get the actual response from the Node.js backend while only the stylesheet will be served by Nginx.

Setting Up SSL

On a production website many times you will need to configure SSL to protect sensitive information. Usually you will go to a CA (Certificate Authority) and get a certificate issued. 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. Here is a nice tutorial that shows how to self sign your SSL certificate.

Once you have the certificate and a private key you can setup SSL in Nginx. You need to modify our previous server block to the following:

server {
  listen       8080;
  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;
  }

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

}

That’s it! Now if you access https://localhost:8080 your SSL set up will work. Here we assume that the certificate file and private key are located at /etc/nginx/ssl/server.crt and /etc/nginx/ssl/server.key respectively. You can change these locations if you want.

Conclusion

In this article, we saw how to use Nginx as a reverse proxy for our Node.js app and configure SSL. Letting Nginx work in the front and handle the static resources you can definitely take some load off your Node backend. Give it a try and do let us know your questions/suggestions through comments.

More:
  • ruffiem

    sudo nginx -s reload works on mac as well :) nice topic, nice post!

    • Guest

      This looks like it allows the server to be accessed over HTTP or HTTPS. How would I redirect the user to only use HTTP?

      • Guest

        Ooops. I attached this to the wrong person…

  • ambled

    nice and concise, however I don’t think you meant to include the port number 8080 in the reference to https://localhost

    startssl.com also issues free SSL certificates

  • Nisim Joseph

    you have an error on the config of “location” to static items.
    you need to use location /public
    {
    alias [folder location];
    }
    not “root”.

    inside a “server” -> “location” it only alias.
    in the server level it “root”.

  • http://www.i-visionblog.com s.shivasurya

    @sandeep doing this affects performance of app ? can u explain how to do vhost in Ngnix?

  • http://www.learningtitanium.com Sharry

    Can you use nginx to serve static content from a node site please?

  • cwoloszynski

    This looks like it proxies for both 8080 and 443 and routes them to the back end. I want to use nginx to redirect the 8080 to 443 and then only proxy the 443 to the node.js. Can you suggest how to do that?

    • Dominic Armstrong

      In case anyone else would like to know too.

      “`
      server {
      listen 80;
      server_name 127.0.0.1;
      return 301 https://$server_name$request_uri;
      }

      server {
      listen 443 ssl;
      server_name 127.0.0.1;

      … ssl cert, location etc
      }
      “`

  • Anthony DeFreitas

    Since node is not running ssl (only nginx is) If nginx and node are on different servers wouldn’t they be communicating insecurely?

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.