Set up a new Node.js Production Server on Ubuntu

This is a tricky process; it never seems to go right the first time.

This is my attempt to detail every step in setting up a new Production Server running Node.js using Express with MongoDB on Ubuntu.

*This was tested and worked on a AWS EC2 server.


Always start with an update:

sudo apt update

Create folder for project:

mkdir ~/production
cd ~/production

Install GIT

sudo apt-add-repository ppa:git-core/ppa # [ENTER]
sudo apt-get update
sudo apt-get install git
# Check GIT version
git --version
# Should be
2.14.1 or higher

Install Node

*NOTE: Because of a conflict with another package, the executable from the Ubuntu repositories is called nodejs instead of node. Keep this in mind as you are running software.

sudo apt install nodejs
nodejs -v
# Should be v6.* or higher
  1. Create a new file: /etc/apt/sources.list.d/nodesource.list
sudo touch /etc/apt/sources.list.d/nodesource.list
sudo nano /etc/apt/sources.list.d/nodesource.list
# Paste these lines

deb xenial main
deb-src xenial main
# Ctrl+X, Y, Enter

2) Download the GPG Signing Key from Nodesource for the repository. Otherwise, you may get NO_PUBKEY errors with apt-get update.

curl -s | sudo apt-key add -
# OK

3) Update APT

sudo apt-get update

This refreshes the data from the nodesource repo so apt knows a newer version exists.
If you get a NO_PUBKEY GPG error, then go back to Step 2.

4) Check if APT has updated nodejs policy.

apt-cache policy nodejs

This is not done by the script, but you want to make sure you see an entry that says something like this in the output:

Version table:
6.11.3-1nodesource1 500

If you do not see entries like this, and only see 4.2.6, START OVER.

5) Install the nodejs binary.

sudo apt-get install nodejs

6) Check Node Version

nodejs --version

Should show v6.2.1 or higher on output.


Because Node has been installed with the name nodejs we have to add a new path map because other programs (like PM2) will look for the package named node and not find anything.

sudo ln -s /usr/bin/nodejs /usr/bin/node

Install NPM

npm is the package manager for JavaScript and the world’s largest software registry. Discover packages of reusable code — and assemble them in powerful new ways.
sudo apt install npm
sudo npm install npm@latest -g
# Check version.
npm -v
# Should be 3.5.2 or higher.

Install PM2

PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.

This is the Process Manager you should use. There are others (nodemon), this one is for production.

npm install pm2@latest -g
# Check version.
pm2 -v
# Should be 2.6.1 or higher.

Generating a new SSH key

ssh-keygen -t rsa -b 4096 -C "YOUR@EMAIL.COM"

Hit enter through the prompts.

Get SSH Public Key.

cat ~/.ssh/
pbcopy < ~/.ssh/

Paste key into repo host Deploy Keys.

Clone the Production!


You may need to run the command twice.

cd into the cloned repo.

Install all Project dependencies

sudo npm install

See if the folder node_modules has been created.


Make sure Express is installed.

npm ls | grep express

Install MongoDB

IF YOU GET GPG error NO_PUBKEY FOR Mongodb-org AFTER sudo apt update.

Adding the MongoDB Repository.

sudo apt-key adv --keyserver hkp:// --recv EA312927

Then add MongoDB repository details so apt will know where to download the packages.

echo “deb [ arch=amd64,arm64 ] xenial/mongodb-org/3.4 multiverse” | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list

Update Apt

sudo apt-get update

Installing MongoDB

sudo apt install -y mongodb-org

Start MongoDB

See if mongod is running.


If it is, find PID for mongod from top.

sudo kill -9 PID

Create required folder for MongoDB — (where the database is stored).

sudo mkdir -p /data/db

Start MongoDB so it can set up.

sudo mongod

Might be worth starting and stopping it a few times.

Start MongoD.

sudo service mongod start

Check output from Mongo log file.

cat /var/log/mongodb/mongod.log

If you get error:

Failed to unlink socket file /tmp/mongodb-27017.sock errno:1 Operation not permitted

Solve this by removing the sock file:

sudo rm /tmp/mongodb-27017.sock

Run MongoDB

sudo service mongod start
# To stop Mongod
sudo service mongod stop

PM2 Set Up

Start Server

sudo pm2 start ecosystem.json --env production


Give the Bash Script file “mongod” execution permissions.

chmod a+x mongod

Install mongodb (not with npm because npm is weird about mongodb).

sudo apt-get install -y mongodb
mongod --shutdown

Check to see if proccess “mongodb” is running — (press “q” to quit).
$ top
If it is, KILL it with the following command: $ sudo killall mongod
Make sure proccess “mongodb” is NO LONGER running — (press “q” to quit).

Create required folder for MongoDB — (where the database is stored).

sudo mkdir -p /data/db/


$ sudo mongod
# WAIT FOR MONGODB TO PRINT 'waiting for connections on port 27017'



PM2 — (link:
This is the Process Manager you should use. There are others, this one is for production.

sudo npm install pm2 -g

Make PM2 Persistent

$ pm2 startup ubuntu
# This next line will be provided by PM2: LOOKFOR IT (should be printed after executing the previous command)
$ sudo su -c "env PATH=$PATH:/opt/node/bin pm2 startup ubuntu -u bloombus --hp /home/bloombus"
$ pm2 save

Let PM2 run MongoDB:
Need to make a Shell Script that starts ‘mongod’ 
(a bash file that PM2 can run).


Paste these lines in the nano IDE
(All 2 lines, THE WHOLE THING):

  • Hit “Ctrl-X”
  • Hit “y”
  • Hit “Enter” Make sure the 2 lines are saved in the file

Port Opening and Accepting

sudo iptables -I INPUT 1 -p tcp — dport 8080 -j ACCEPT
sudo iptables -I INPUT 1 -p tcp --dport 8443 -j ACCEPT

Port Forwarding

This is important because port 80 is a “reserved” port. This script forwards port 80 to port 8080. You can make it port 8080.

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

Forward 443 for HTTPS.

sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443



sudo pm2 start

Start the server.

sudo pm2 start server.js


This next part is a reminder for myself.
I use a different port and IP address on development vs production server.
So I pass the command line argument “real” to set port to 3000 and IP to be requested by the server.

You pass command line arguments with --

sudo pm2 start server.js -- real
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.