Deploy an Express Web Server with Pm2 and Nginx on Ubuntu 20.04

Updated on May 11, 2021
Deploy an Express Web Server with Pm2 and Nginx on Ubuntu 20.04 header image


This guide explains how to create a Node.js app with Express, deploy it with the pm2 process manager, and publish it with an Nginx reverse proxy.


Before you begin:

  • Deploy a fully-updated Vultr cloud server running Ubuntu 20.04.

1. Install the Dependencies

  1. SSH to the server, or connect with the Vultr web console.

  2. Update all your dependencies.

     $ sudo apt update
  3. Install Node.js

     $ sudo curl -sL | sudo -E bash -
     $ sudo apt install -y nodejs nano nginx
  4. Confirm Node.js was installed properly.

     $ node -v

    This command should say something like v14.x.x

  5. Install pm2.

     $ sudo npm i -g pm2

2. Project Setup

  1. Initialize a new project.

     $ mkdir express-website
     $ cd express-website
     $ npm init -y
  2. Install Express.js

     $ npm i express

3. Add Demo Source Code

  1. Create your project's main file.

     $ nano index.js
  2. Paste the following into your editor.

     const express = require("express"); // Acquire the express package and assign it to a variable called "express"
     const app = express(); // Calls the method "express()" and assigns it's output to "app". "express()" will create an express app for you.
     app.get("/", (req, res) => { // Creates sort of a listener for when there are "GET" requests to the "/" (root) path. Takes in req (request) and res (response)
         res.send("Hello world!"); // For the response, send a string "Hello World!"
     app.listen(3000, () => { // Tells the app to start on port 3000. This function below is run when
         console.log("Server listening on port 3000!"); // Say in the console "Server listening on port 3000!"
  3. Save and exit the file.

4. Test the App

Run your app:

$ node index.js

If it works, it reports "Server listening on port 3000!". Type Ctrl + C to exit.

5. Daemonize the App

Daemonize the app with pm2.

$ pm2 start index.js

To verify it has daemonized, run pm2 list.

6. Nginx Reverse Proxy

  1. Create your server block in Nginx.

     $ nano /etc/nginx/sites-enabled/express.conf
  2. Paste the following in your nano editor:

     server {
         listen 80; # Listen on port 80
         listen [::]:80; # Listen on port 80 for ipv6
         server_name _;
         location / {
  3. Save and exit the file.

  4. Remove the default Nginx site.

     $ sudo rm /etc/nginx/sites-enabled/default
  5. Restart nginx

     $ systemctl restart nginx
  6. Open port 80 in the UFW firewall. See our firewall quickstart guide for more information.

     $ sudo ufw allow 80/tcp
  7. Verify it works by entering your server's IP in your browser.