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.


START

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
IF UBUNTU INSTALLS A NODE VERSION THAT IS NOT LATEST (6.* or higher) FOLLOW THIS GUIDE.
  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 https://deb.nodesource.com/node_6.x xenial main
deb-src https://deb.nodesource.com/node_6.x 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 https://deb.nodesource.com/gpgkey/nodesource.gpg.key | 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.

CONTINUE.

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.
http://pm2.keymetrics.io/

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/id_rsa.pub
pbcopy < ~/.ssh/id_rsa.pub

Paste key into repo host Deploy Keys.

Clone the Production!

git clone GIT@GITLAB.COM:GROUP/PROJECT.GIT

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.

ls

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://keyserver.ubuntu.com:80 --recv EA312927

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

echo “deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu 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.

top

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

asdf



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).
top

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

sudo mkdir -p /data/db/

START MONGODB

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

NOW STOP MONGODB — “Ctrl-C”

PROCESS MANAGER

PM2 — (link: https://github.com/Unitech/pm2)
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).

touch mongod.sh

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

#!/bin/bash
mongod
  • Hit “Ctrl-X”
  • Hit “y”
  • Hit “Enter” Make sure the 2 lines are saved in the file
cat mongod.sh

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

START THE SERVER

FIRST START THE DATABASE…

sudo pm2 start mongod.sh

THEN….
Start the server.

sudo pm2 start server.js

./END


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.