Running Node.js in Production

Want to run a Node.js application in production? The best way is to run it behind Nginx and use PM2 to keep it running after crashes and reboots.

First launch a EC2 instance on AWS, I used Ubuntu 16.04 but 14.04 should be mostly equivalent. I'm going to also assume that you've setup a static ip and pointed your domain to the ip address of the server.

On the instance install Nginx:

sudo apt-get update
sudo apt-get install nginx

Now visit and make sure you see the nginx test page. If you don't it's likely an issue with your security group (fancy word for firewall). It should allow HTTP, HTTPS, and SSH traffic through. See the below image.

Now install certbot to get a free TLS certificate from letsencrypt.

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot

Now request a certificate (assuming your domain is

certbot certonly --webroot -w /var/www/html -d

Now that you have a certificate setup Nginx to listen to TLS traffic. Edit the /etc/nginx/sites-available/default file and add the following:

# Redirects user to HTTPS page
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;

# Listens for HTTPS Connections
server {
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/;
    ssl_certificate_key /etc/letsencrypt/live/;

    # Passes those connections to Node running on on port 8080
    location / {
            proxy_pass http://localhost:8080;
            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;

    # Sets the HSTS flag in browser
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
Restart the Nginx service: sudo service nginx restart

Now we need to setup Node so that Nginx can serve traffic to it.

First install PM2

npm install pm2@latest -g

Now run your app with pm2. I assume app.js is what you'd run when serve traffic locally with node. I'm also assuming app.js is executable and can be run like ./app.js

pm2 start app.js

You can check on the status of your app with pm2 like so (notice the job name doesn't include .js):

pm2 start app.js

Assuming that your Node app is running on port 8080 you should now be able to go to

To make sure browsers always go to the https version first (they'll get redirected automatically), add your application to the HSTS preload list/.

Comments ()