Deploying Express.js website to VPS with Nginx, PM2 and Ubuntu 18.04

Lukáš Fuchs
Jun 17, 2018 · 3 min read
“Macro of Macbook computer screen displaying information from server” by Jacob Miller on Unsplash

0. Preparation

You will need:

  • VPS with Ubuntu 18.04 installed and root access
  • Putty or other SSH client
  • Dummy Node.js + Express.js server (I will use this)
  • Optional: domain with DNS records pointed to your VPS

1. Creating user

We want to create new user with “sudo” rights, because it’s bad practice to user default root user in production.

I will create user with name lukas.

# creating new user
adduser lukas
# providing superuser rights
usermod -aG sudo lukas

Log out and log in as your new user. Also it’s good idea to update.

sudo apt-get update
sudo apt-get upgrade

2. Node.js

There are many ways how to install Node.js, but i prefer NVM (Node.js Version Manager). We will install Node.js version 10.

We will download install script with curl (or we can alternatively use wget). This will create .nvm folder inside our user’s directory. Inside this folder will be stored your Node.js installations.

# this command will download install script with curl
curl -o- | bash
# or use wget
wget -qO- | bash

Now log out and log back in. After this, you should be able to use nvm commands.

# check if installed
nvm --version
==> 0.33.11
# list available Node.js versions
nvm ls-remote
# choose one version and install it
# example of v10.4.1 installation
nvm install v10.4.1
# check if installed properly
node --version
==> v10.4.1

NVM is powerfull tool, that allows you to have multiple Node versions installed and to switch between them as you like. You can use “help” command or check out their github page to learn more.

# check more nvm usage
nvm --help

Creating basic server with Express.js

# go to your user's directory
cd /home/lukas
# create folder simpleServer
mkdir simpleServer
# go inside
cd simpleServer
# create package.json
npm init -y
# install Express.js
npm install express

Create file with this text inside it and save it. You can use nano or any other tool.

# open nano
nano server.js
# to save, press Ctrl + X ==> Y ==> Enter
# start server
node server.js
==> Listening on http://localhost:3000

If you go to <YourVPSIpAddress>:3000, you should see “Hello World!” inside your browser widow.

3. PM2

If you now close your SSH client widow, your website will stop working. We need some tool that will keep our server “alive”. Say hello to PM2!

# globally install PM2
npm install pm2 -g
# check if installed properly
pm2 -V
==> 2.10.4

PM2 will make our server run in background and if it crashes, PM2 will restart it automatically.

# start our server with PM2
pm2 start server.js
# check <YourVPSIpAddress>:3000 if your server is running

Make PM2 to start at boot

If we now reboot VPS, our server won’t start up. We must enable it first. Relevant documentation here.

pm2 startup
# this will generate another command that you need to run
# We also need to save what processes
# should get started with pm2
pm2 save
# reboot VPS and check if your website is up
sudo reboot

Same as NVM, PM2 is very powerfull tool that can do much, much more than this. Check out official documentation and “help” command.

# get help!
pm2 help

4. Nginx

Install Nginx:

sudo apt-get install nginx# check if installed
sudo nginx -v
==> nginx version: nginx/1.14.0 (Ubuntu)

Create configuration file for your server.

cd /etc/nginx/sites-availablesudo nano simpleServer

Inside this file write this piece of code:

server {
listen 80;
server_name <YourVPSIpAddress>;
location / {
proxy_pass http://localhost:3000/;

If you have your domain set up, you can do this.

# ...
# ...

More information can be found in Nginx documentation.

Final steps

# check if your configuration is ok
sudo nginx -t
# enable your configuration
sudo ln -s /etc/nginx/sites-available/simpleServer /etc/nginx/sites-enabled
# restart nginx
sudo systemctl restart nginx

Your server should be now available on <YourVPSIpAddress>.

What to do next?

There is still work to do. This is just basic setup to get you running as soon as possible. For production it’s probably good idea to do some other things:

Lukáš Fuchs

Written by

I am freelance programmer from Pilsen, Czech Republic. You can learn about me here: and here:

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade