Deploy Node.js App on Ubuntu with PM2, NGINX and Let’s Encrypt

Updated: December 28, 2023 By: Khue Post a comment

Deploying a Node.js application on an Ubuntu server may seem daunting, but it doesn’t have to be. In this guide, we’ll walk you through the process of deploying your app with process management via PM2, setting up NGINX as a reverse proxy, and securing your app with a free SSL certificate (https) from Let’s Encrypt.

Step 1: Getting Your Code on the Server

First off, let’s move your precious code safely to its new home. There are a couple of ways to do this:

The Git Way (Highly Recommended!)

If you’ve got Git in your toolbox (it’s very likely), clone your repo right onto your server. It’s like sending your code on a first-class flight directly to its destination.

1. Install Git (if it’s not already partying on your server):

sudo apt update
sudo apt install git

2. Clone your repo and step into your project:

cd /var/www/
git clone
cd your-awesome-app

3. Get the latest version and check out your branch:

git checkout master
git pull origin master

The SCP or Rsync Way (Old School Cool)

Use scp or rsync if you prefer the hands-on approach. It’s like packing up your code in a moving van and driving it to the server yourself.

scp -r /path/to/your/app username@your_server_ip:/var/www/your-awesome-app

Step 2: Set Up and Run Your Node.js App

Alrighty, let’s get Node.js and npm cozy on your server:

1. Welcome Node.js and npm to Ubuntu:

sudo apt install nodejs npm

2. Jump into your app’s directory and hug all those dependencies (in your package.json file):

cd /path/to/your-awesome-app
npm install

3. Give your app a quick run to make sure it’s feeling fine:

node app.js

If you use index.js or main.js as your entry point, don’t forget to adjust the command above.

Step 3: Let PM2 Take the Wheel

PM2 is a production process manager for Node.js applications that allows you to keep your app running in the background and start automatically upon system reboots. In other words, it is like a reliable friend who makes sure your app keeps running even when you’re away.

1. Invite PM2 over with a global install:

npm install pm2@latest -g

2. Start your app with PM2:

pm2 start app.js

3. Tell PM2 to revive your app after a nap (i.e., server reboot):

pm2 startup ubuntu

Step 4: Let NGINX Be Your Traffic Cop

NGINX is a fast and efficient reverse proxy that can manage incoming traffic and route it to your Node.js app, handling many simultaneous connections efficiently. It’ll make sure your app doesn’t get lost in the web’s hustle and bustle.

1. Get NGINX set up:

sudo apt install nginx

2. Craft a server block to let NGINX know where to send your visitors:

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

Insert the following configuration, which sets up Nginx to act as a reverse proxy:

server {
    listen 80;

    location / {
        proxy_pass http://localhost:3000; # Replace with your app's port
        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;

Don’t forget to replace and with your own domain. Save and exit the file (press Ctrl + X then hit Y).

3. Flip the switch to enable your site.

Link the file to the sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/

Test the configuration for syntax errors:

sudo nginx -t

eload Nginx to apply the changes:

sudo systemctl reload nginx

Step 5: Securing Your App with Let’s Encrypt

Securing your app with HTTPS is crucial, and Let’s Encrypt provides free SSL certificates.

1. Suit up with Certbot and its NGINX sidekick:

sudo apt install certbot python3-certbot-nginx

2. Obtain an SSL certificate

Run Certbot with the Nginx plugin and follow the prompts. It will automatically update your Nginx configuration to use the SSL certificate.

sudo certbot --nginx -d -d

Replace with your domain name (don’t get mad at me for repeating this too many times).

3. Automatic renewal

Let’s Encrypt certificates are valid for 90 days. Certbot will set up a cron job or systemd timer to auto-renew the certificates. You can test the renewal process manually.

sudo certbot renew --dry-run

After you’ve secured your Node.js app with SSL, all the data transmitted to and from your server will be encrypted, providing privacy and security for you and your users.

Now, open a new tab on your favorite web browser and enter https://your_domain to enjoy the result.


And that’s it! 🎉 Your Node.js app is now living it up on your Ubuntu server, with PM2 making sure it never takes an unplanned snooze, NGINX handling the traffic like a pro, and Let’s Encrypt keeping everything locked up tighter than your diary. Now go forth and share your app with the world!