Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps

How to Configure Node.js and MongoDB for Production in Ubuntu

5.00/5 (6 votes)
23 Feb 2018CPOL5 min read 23.6K  
Setting up Node.js and MongoDB backend, and then getting an application up and running can be challenging. This tutorial helps you make the whole process easier.

One of the biggest challenges that a developer faces while working with the Node environment is the production phase. After spending days or even weeks on development, you’d expect the production and deployment to be as easy as running a few commands to get it up and running. But in real life, things are more difficult than that. In this tutorial, we will cover everything that you need to know to set up Node.js and MongoDB on Ubuntu. Some of the best practices for production are also discussed along the way.

Introduction

Over the years, JavaScript has evolved to be much more than a language that runs on browsers. It’s now actively used for running servers, rendering server-side code, powering databases and so on. JavaScript powered servers using Node.js and Express are popular options for getting started with a full-stack JavaScript solution. Some of the popular JavaScript stacks include MEAN that comprise MongoDB, Express.js, Angular and Node.js and the closely related MERN stack that replaces React in place of Angular.

Whatever your stack is, setting up Node.js/Express and MongoDB in a production-like environment can be challenging at first. So, we will try to configure Node.js and MongoDB on Ubuntu 16.04 LTS so that you can replicate the steps on your server running on AWS or DigitalOcean. However, before getting started, make sure that you have Ubuntu 16.04 installed, updated, and configured with a non-root sudo user.

Setting up Node.js

We should install the long-term supported version of Node.js and at the time of writing this tutorial, that’s v8.x.x. We’re going to download the node package archives and the setup script from NodeSource. Make sure that you’re in the home directory, and then download the script as follows:

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -

The PPA will be updated with the nodejs repository. You can now install nodejs by running:

sudo apt-get install -y nodejs

The nodejs package comprises both node.js and npm. However, you might need to install extra development tools for certain npm packages to work.

sudo apt-get install build-essential

Creating a MongoDB Backend

Although you could directly install MongoDB from the Ubuntu repository, the mongodb package provided there is not officially maintained by MongoDB team. Instead, you should use the following steps to install the community edition of mongodb-org.

Here are the steps that you need to follow to install MongoDB backend:

  1. Import MongoDB's GPG key used by Ubuntu’s package management system.
    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
    
  2. Create a /etc/apt/sources.list.d/mongodb.list file.
    echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
  3. Update the repository and then install the latest version of MongoDB.
    sudo apt-get update 
    sudo apt-get install mongodb-10gen

If you’re using AWS, EC2 instances can be configured with EBS for storage. For best performance, the official documentation recommends using a separate volume for the data, journal and the logs. Using EBS is recommended to maintain mongodb backup and you can then restore them whenever necessary.

Configuring MongoDB

I’ve listed the steps that you need to follow to use EBS volume.

# Create an EBS filesystem
sudo mkfs -t ext4 /dev/xvdb
# Create a directory for the mountpoint.
# mkdir <mount point>
mkdir /database
# To make the volume mount on boot, add a fstab entry
echo '/dev/xvdb /database ext4 defaults,auto,noatime,noexec 0 0' | sudo tee -a /etc/fstab
# Mount the database
sudo mount /dev/xvdb /database
# Create directories for data, journal and logs. 
# I am going to place them under a single volumen
cd /database
mkdir data journal log
# Set the ownership of these directories to mongodb
sudo chown -R mongodb:mongodb /database

Next, you need to configure MongoDB to use the dbpath and the logpath. For that, you need to edit the file /etc/mongodb.conf and the following content:

dbpath = /database/data
logpath = /database/log/mongodb.log

Start the mongod service by running:

sudo service mongod start

Creating a Node.js Application

To create a new application, first, create a new directory and then run npm init to create a package.json for your application.

mkdir demo_app && cd demo_app
npm init

Set the entry point as index.js.

You need to install Express.js for the server, and mongoose driver for the node. Use npm to install the dependencies.

npm install express mongoose --save

You can verify that the application works by setting it executable and then running it.

Now edit the index.js file as follows:

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

app.get('/', (req, res) => res.send('App is running successfully on port 3000'))

app.listen(3000, () => console.log('Example app listening on port 3000!'))

var db = Mongoose.connect('mongodb://localhost:27017/dbname', function(error){
    if(error) console.log(error);

        console.log("connection successful");
});

You can verify that the application works by setting it executable and then running it.

chmod +x ./index.js./index.js

You should get the output:

App is running successfully on port 3000.

Managing the Application using PM2

While you’re running the application in production, there are chances that the application may fail, or run into errors and then crash. Having a process manager helps you avoid such scenarios. Although there are many other process managers like foreverjs, systemd, and Strongloop, PM2 stands out from the rest. It offers additional insights about the runtime performance and resource consumption.

Install PM2 globally if you haven’t already.

sudo npm install -g pm2

The pm2 start index.js command should start the application and add it to PM2’s list of processes. You should see something like this in the command line:

Output:
┌──────────┬────┬──────┬──────┬────────┬───────────┬────────┬────────────┬──────────┐
│ App name │ id │ mode │ PID  │ status │ restarted │ uptime │     memory │ watching │
├──────────┼────┼──────┼──────┼────────┼───────────┼────────┼────────────┼──────────┤
│ index    │ 0  │ fork │ 5871 │ online │         0 │ 0s     │ 9.012 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴───────────┴────────┴────────────┴──────────┘

PM2 has assigned our application a name, an id, and a dedicated thread. If the app crashes at some stage, PM2 guarantees an application restart. However, to make things work on system startup, you need to follow additional steps.

You can use the startup command to generate a startup script for your PM2 application.

$ pm2 startup systemd

The terminal will return something that looks like this:

[PM2] Init System found: systemd
[PM2] You have to run this command as root. Execute the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u mjm --hp /home/mjm

Replace all instances of mjm with your username in the last line and run the command.

sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 
startup systemd -u <username> --hp /home/<username>

The command will create a systemd profile that executes pm2 on boot. You can check the status of the pm2 profile your user by running:

systemctl status pm2-mjm

Using NGINX as Reverse Proxy Server

We’re currently running on localhost. To make the application accessible to the outside world, we will need to use a server to act as a reverse proxy. Nginx, being one of the most popular web server applications is definitely suited for this purpose. I am going to assume that you’ve already installed nginx. If not, head over to the nginx documentation for guidance.

Once you’ve done that, open your nginx configuration file. The file could be located at /usr/local/nginx/conf, /etc/nginx, or /usr/local/etc/nginx based on your setup.

Open the file and within the server block, look for a location block. Replace its content with the following code:

JavaScript
location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

If you’ve already configured the domain with the nginx server, everything should work straight out.

Verify that the configuration file is syntactically correct.

sudo nginx -t

Now, restart nginx.

sudo systemctl restart nginx

Adding Encryption to nginx

You can encrypt your website for free using Let’s Encrypt which provides free SSL/TLS certificates. This has already been covered in another tutorial by James Johnes in How to Install Let's Encrypt and Automate Renewal in Nginx.

If you’ve followed the steps precisely, then our sample node.js application should be up and running.

Conclusion

In this tutorial, we’ve covered the steps for deploying a Node and MongoDB backend using Ubuntu. We created an Express server and then reverse proxied it using Nginx. We’ve also covered some of the best-practices to avoid common pitfalls.

If you have any thoughts about setting up Node.js for production, let us know through the comments.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)