Monday, 9 October, 2017 UTC

Summary

There are various platforms that help with deploying NodeJS apps to production. Zeit Now is one such platform.

While those platforms can help, in this tutorial, we’ll be looking at how to deploy a NodeJS app to Digital Ocean. Digital Ocean compared to these other platforms is cheaper and you also can logon to your server and configure it however you like.

You get more control over your deployment and also it's a great experiment to see exactly how Node apps are deployed to production.

Prerequisites

This tutorial assumes the following:

Digital Ocean account (obviously).

SSH setup on your local computer, you might want to follow https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets for a walk through.

What We’ll Be Deploying

Let’s quickly build a sample app that we’ll use for the purpose of this tutorial. It going to be pretty simple app.

And access it on http://localhost:3000. You should get Hey, I'm a Node.js app! outputted. The complete code is available on GitHub.

Now let’s take this our awesome app to production.

Create a Droplet

Login to your Digital Ocean account and create a new droplet (server). We’ll be going to with One-click apps. Select NodeJS as shown below:

Next, we’ll choose the $10 plan. Though the task list app will work perfectly on the $5 plan, but we won’t be able to install the NPM dependencies because the NPM requires at least 1GB RAM for installing dependencies. Though there is a way around this by creating swap memory which is beyond the scope of this tutorial.

Next, select a datacenter region, we’ll go with the default:

Next, add a new SSH key or choose from existing ones that you have added. You can get your SSH key by running the command below on your local computer:

cat ~/.ssh/id_rsa.pub

The command above will print your SSH key on the terminal, which you can then copy and paste in the SSH Key Content field. Also, give your SSH key a name.

Finally, choose a hostname for the droplet and click the Create button.

After some couple of seconds, you’ll have your new server up and running on Ubuntu 16.04 and NodeJS version 6.11.2. Note the IP address of the server as we’ll be using it to access the server.

Create Non-root User

Before we start configuring the server for the task app, let’s quickly create a non-root user which we’ll use henceforth for the rest of the tutorial.

Tip: As a security measure, it is recommended to carry out tasks on your server as a non-root user with administrative privileges.

First, we need to login to the server as root. We can do that using the server’s IP address:

If all went well, you’ll be logged in to the server as the new user with SSH.

The rest of the tutorial assumes you are logged in to the server with the new user created (mezie in my case).

Clone The App on The Server

We are going to clone the app unto the server directly in the user's home directory (that is, /home/mezie in my case):

git clone https://github.com/ammezie/sample-nodejs-app.git

Next, we install the dependencies:

cd sample-nodejs-app
npm install

Once the dependencies are installed we can test the app to make sure everything is working as expected. We’ll do so with:

node index.js

The app is listening on port 3000 and can be accessed at http://localhost:3000. To test the app is actually working, open a new terminal (still on the server) and enter the command below:

curl http://localhost:3000

You should get an output as below:

Hey, I'm a Node.js app!

Good! The app is up and running fine. But whenever the app crashes we’ll need to manually start the app again which is not a recommended approach. So, we need a process manager to help us with starting the app and restarting it whenever it crashes. We’ll use PM2 for this.

Install PM2

We’ll install it globally through NPM:

sudo npm install -g pm2

With PM2 installed, we can start the app with it:

pm2 start index.js

Once the app is started you will get an output from PM2 indicating the app has started.

Next, we’ll install Nginx as the webserver to be used for reverse proxy which will allow us to access the app directly with an IP address or domain instead of tacking port to the IP address. Eg. 102.123.83.29:5000.

sudo apt-get update
sudo apt-get install nginx

Because we chose One-click apps while creating our droplet, ufw firewall is setup for us and running. Now, we need to open firewall for only HTTP since we are not concerned with SSL in this tutorial:

sudo ufw allow 'Nginx HTTP'

Set Up Nginx as a Reverse Proxy Server

Finally, we set up Nginx as a reverse proxy server. To this, run:

sudo vim /etc/nginx/sites-available/default

Within the server block you should have an existing location / block. Replace the contents of that block with the following configuration: