Deploying a Node App to Digital Ocean

Draft updated on Invalid Date

Chimezie Enyinnaya

Deploying a Node App to Digital Ocean

This tutorial is out of date and no longer maintained.

Warning: For the latest information, refer to the documentation for creating 1-Click NodeJS Droplets on DigitalOcean.


There are various platforms that help with deploying Node.js apps to production.

In this tutorial, we’ll be looking at how to deploy a Node.js app to DigitalOcean. DigitalOcean compared to these other platforms is cheaper and you also can log on 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.


This tutorial assumes the following:

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 a pretty simple app.

  1. // create a new directory
  2. mkdir sample-nodejs-app
  3. // change to new directory
  4. cd sample-nodejs-app
  5. // Initialize npm
  6. npm init -y
  7. // install express
  8. npm install express
  9. // create an index.js file
  10. touch index.js

Open index.js and paste the code below into it:

// index.js

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('Hey, I\'m a Node.js app!')

app.listen(3000, () => {
  console.log('Server is up on 3000')

You can start the app with:

  1. node index.js

And access it on http://localhost:3000.

You should get:

Hey, I'm a Node.js app!

The complete code is available on GitHub.

Now let’s take our awesome app to production.

Create a Droplet

Login to your DigitalOcean account and create a new droplet (server). We’ll be going to with One-click apps. Select Node.js 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 the existing ones that you have added. You can get your SSH key by running the command below on your local computer:

  1. 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 a 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.

Note: 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 log in to the server as root. We can do that using the server’s IP address:

  1. ssh root@SERVER_IP_ADDRESS

Once we are logged in to the server, we can move on to create a new user:

  1. adduser mezie

This will create a new user called mezie, you can name the user whatever you like. You will be asked a few questions, starting with the account password.

Having created the new user, we need to give it administrative privileges. That is, the user will be able to carry out administrative tasks by using sudo command.

  1. usermod -aG sudo mezie

The command above adds the user mezie to sudo group.

Now the user can run commands with superuser privileges.

Setup SSH Key For The New User

You need to copy your public key to your new server. Enter the command below on your local computer:

  1. cat ~/.ssh/id_rsa.pub

This will print your SSH key to the terminal, which you can then copy.

For the new user to log in to the server with SSH key, we must add the public key to a special file in the user’s home directory.

Still logged in as root on the server, enter the following command:

  1. su - mezie

This will temporarily switch to the new user. Now you’ll be in your new user’s home directory.

Next, we need to create a new directory called .ssh and restrict its permission:

  1. mkdir ~/.ssh
  2. chmod 700 ~/.ssh

Next, within the .ssh directory, create a new file called authorized_keys:

  1. touch ~/.ssh/authorized_keys

Next, open the file with vim:

  1. vim ~/.ssh/authorized_keys

Next, paste your public key (copied above) into the file. To save the file, hit ESC to stop editing, then :wq and press ENTER.

Next, restrict the permissions of the authorized_keys file with this command:

  1. chmod 600 ~/.ssh/authorized_keys

Type the command below to return to the root user:

  1. exit

Now your public key is installed, and you can use SSH keys to log in as your user.

To make sure you can log in as the new user with SSH. Enter the command below in a new terminal on your local computer:

  1. ssh mezie@SERVER_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):

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

Next, we install the dependencies:

  1. cd sample-nodejs-app
  2. 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:

  1. 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:

  1. curl http://localhost:3000

You should get an output as below:

  1. 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:

  1. sudo npm install -g pm2

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

  1. pm2 start index.js

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

To launch PM2 on system startup or reboot, enter the command below:

  1. pm2 startup systemd

You’ll get the following output:

  1. [PM2] Init System found: systemd
  2. [PM2] To setup the Startup Script, copy/paste the following command:
  3. sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u mezie --hp /home/mezie

Copy and run the last command from the output above:

  1. sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u mezie --hp /home/mezie

Now PM2 will start at boot up.

Install Nginx

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.

  1. sudo apt-get update
  2. sudo apt-get install nginx

Because we chose 1-Click Apps while creating our Droplet, ufw firewall is set up for us and running. Now, we need to open the firewall for only HTTP since we are not concerned with SSL in this tutorial:

  1. 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:

  1. 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:

// /etc/nginx/sites-available/default

location / {
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-NginX-Proxy true;
  proxy_pass http://localhost:3000;
  proxy_set_header Host $http_host;
  proxy_cache_bypass $http_upgrade;
  proxy_redirect off;

Save and exit vim.

Test to make sure there are no syntax errors in the configuration by running:

  1. sudo nginx -t

Then restart Nginx:

  1. sudo systemctl restart nginx

Now you should be able to access the app with your IP_ADDRESS. You should get something similar to the image below:


In this tutorial, we have seen how to deploy a Node.js app to DigitalOcean. We also saw how to setup a reverse proxy server with Nginx.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Chimezie Enyinnaya


Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
Leave a comment

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel