Configuring Nginx as a Front End to Your Node.js Application

Nginx ("engine-x") is a lightweight and high performance HTTP / proxy server. If you are planning to run your Node.js application on a production server, you should seriously consider using Nginx as a front-end proxy. Nginx can reduce the load on your application and improve performance, as it is very efficient at serving static resources. It can also provide an additional layer of defense against security attacks, by intercepting and acting upon all requests towards your application.

In this tutorial, you will learn how to configure Nginx as a reverse proxy server for a Node.js application. The steps below have been successfully tested on Ubuntu 14.04.

  1. Install Nginx:

    $ apt-get install nginx
    
  2. Edit /etc/nginx/nginx.conf:

    worker_processes auto;
    
    
    events {
        use epoll;
        worker_connections 1024;
        multi_accept on;
    }
    
    
    http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        server_tokens off;
        gzip on;
        gzip_disable "MSIE [1-6]\.";
        gzip_min_length 800;
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_http_version 1.1;
        gzip_types text/plain text/xml text/css application/javascript application/x-javascript text/javascript application/json image/svg+xml application/x-font-ttf;
     }
    
  3. Edit /etc/nginx/mime.types, and insert in the types section:

    application/x-font-ttf ttf;
    
  4. Edit /etc/nginx/proxy.conf:

    proxy_http_version 1.1;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-NginX-Proxy true;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_cache_bypass $http_upgrade;
    proxy_buffering off;
    
  5. Restart Nginx for changes to take effect:

    service nginx restart
    

For each of your Node.js applications you will have to create a separate server configuration file. An example configuration is provided below, which assumes:

  • You are setting up your site at MYDOMAIN.TLD
  • Your SSL certificate is stored in /etc/ssl/certs/MYDOMAIN.TLD.crt, and SSL key in /etc/ssl/private/MYDOMAIN.TLD.key
  • Your Node.js application listens on port 8080

Start by creating the server configuration file.

  1. Edit /etc/nginx/sites-available/MYDOMAIN.TLD:

    server {
        listen 80;
        server_name MYDOMAIN.TLD www.MYDOMAIN.TLD;
        access_log  /var/log/nginx/MYDOMAIN.TLD.log;
        error_log  /var/log/nginx/MYDOMAIN.TLD.err;
        return 301 https://MYDOMAIN.TLD$request_uri;
    }
    
    
    server {
        listen 443;
        server_name www.MYDOMAIN.TLD;
        ssl on;
        ssl_certificate /etc/ssl/certs/MYDOMAIN.TLD.crt;
        ssl_certificate_key /etc/ssl/private/MYDOMAIN.TLD.key;
        access_log  /var/log/nginx/MYDOMAIN.TLD.log;
        error_log  /var/log/nginx/MYDOMAIN.TLD.err;
        return 301 https://MYDOMAIN.TLD$request_uri;
    }
    
    
    server {
        listen 443;
        server_name MYDOMAIN.TLD;
        access_log  /var/log/nginx/MYDOMAIN.TLD.log;
        error_log  /var/log/nginx/MYDOMAIN.TLD.err;
        ssl on;
        ssl_certificate /etc/ssl/certs/MYDOMAIN.TLD.crt;
        ssl_certificate_key /etc/ssl/private/MYDOMAIN.TLD.key;
        location / {
            include /etc/nginx/proxy.conf;
            proxy_pass http://127.0.0.1:8080/;
        }
    }
    
  2. Enable the configuration:

    ln -s /etc/nginx/sites-available/MYDOMAIN.TLD /etc/nginx/sites-enabled/MYDOMAIN.TLD
    
  3. Restart Nginx for changes to take effect:

    service nginx restart
    

Since the only client that your Node.js application ever sees is the Nginx proxy, if you are using the popular express framework and want to be able to read the IP address of the remote client in the usual way, which is through req.ip, make sure you add app.enable('trust proxy') just before your routes.

If you want to learn more about Nginx, you can have a look at the official documentation here.