Deploying Nodejs Application to Server [Full Guide]

Video Tutorial

Getting Started

Deploying a Node.js Application to bare Linux Server on Cloud can be tricky and hard to find the right configuration and the right stack of technologies that fit your needs.

You can get a VPS (Virtual Private Server) from many different reliable platforms, we will use Hostigner since it is very affordable and easy to setup with different add-ons.

I prefer to use Ubuntu 18.04 which is the latest version as the time of making this tutorial since it is very easy to setup and install all required dependencies.

Usually, for deploying a Nodejs Application to a bare server required steps we need to follow.

  • Setup your DBMS: in our case, we will use MySQL (It depends on what your application works with).

  • Setup a Reverse Proxy: we will use Nginx for re-versing HTTP Requests to our internal Nodejs Server.

  • Install Node & NPM.

  • Install PM2 Nodejs Process Manager.

  • Push/Clone your code from version control.

  • run a local server and configure reverse proxy.

Those are the minimal steps you should consider for making your Nodejs application available to access on your server’s IP address or domain name on port 80 which the default port for serving HTTP.

First, make sure to grab a VPS Hosting I would advise you to use Hostinger with my COUPON CODE: **IPENYWIS** made especially for you guys.

Next, you need to SSH to your server, in case of using Hostigner you should be able to see your server’s IP address from the right-hand side so you can ssh as root.

ssh root@

You can change the SSH password from Hostinger cpanel.

Installing MySQL Database

Installing MySQL is like installing any other Debian (Ubuntu) package throughout apt.

sudo apt update
sudo apt install mysql-server

Make sure to accept all required permissions then we need to run the configuration script which will allow us to configure the MySQL Deamon server and secure it to work on a production ready environment.

sudo mysql_secure_installation

This will take you through a series of prompts where you can make some changes to your MySQL installation’s security options. The first prompt will ask whether you’d like to set up the Validate Password Plugin, which can be used to test the strength of your MySQL password. Regardless of your choice, the next prompt will be to set a password for the MySQL root user. Enter and then confirm a secure password of your choice.

From there, you can press Y and then ENTER to accept the defaults for all the subsequent questions. This will remove some anonymous users and the test database, disable remote root logins, and load these new rules so that MySQL immediately respects the changes you have made.

Make sure to check if MySQL server is running.

systemctl status mysql

You should see the status as (Active) running which means the server has been successfully started without no issues.

Try to connect the server throughout the MySQL client.

mysql -u root

If everything is okay, then we have successfully set up the Database Server.

mysql> quit

Nginx Reverse Proxy

A reverse proxy is used to receive one or multiple resources from clients and serve it to a different server in our case it will be our Nodejs server.

Nginx is a pretty awesome and reliable HTTP Server widely used for serving static HTML Files and for reverse proxying.

The main benefit behind using a reverse proxy is for providing internal access to a server or a resource behind a firewall so in our case we will be running Nodejs application on port 3000 behind a firewall which means it can only be accessed through the localhost and we bind Nginx reverse proxy to port 80 which is publicly available afterwards it can serve the localhost Nodejs server.

Install Nginx.

sudo apt update
sudo apt install nginx

By default Hostinger, VPS has apache2 installed and fully configured to serve HTTP on PORT 80 so we need to fully disable/uninstall apache2 from our server.

sudo apt-get remove apache2*

This will remove all apache2 packages and sub-packages.

Let’s try to configure a simple Test webpage for Nginx.

Before going any further with Nginx configuration we need first to install a firewall that will only allow a specific port which is very important to secure our server.

Let’s install ufw (uncomplicated firewall).

sudo apt install ufw

Make sure to allow SSH Connections to pass through the firewall otherwise you won’t be able to access your server the next time you try.

ufw allow ssh

To check which network application is available and which can be allowed/denied through the firewall.

ufw app list
>  Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  • Nginx Full: This profile opens both port 80 (normal, unencrypted web traffic) and port 443 (TLS/SSL encrypted traffic)

  • Nginx HTTP: This profile opens only port 80 (normal, unencrypted web traffic)

  • Nginx HTTPS: This profile opens only port 443 (TLS/SSL encrypted traffic)

Now let’s allow Nginx Http since we only need HTTP through ufw.

If you need SSL aka HTTPS make sure to enable the Nginx Https or the Nginx Full.

sudo ufw allow 'Nginx HTTP'
> Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx HTTP                 ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

If you got the output as Nginx HTTP and OpenSSH are allow then everything is fine.

As you can clearly see it also supports IPV6 Protocol in case you needed it.

Let’s check the status of Nginx.

sudo systemctl status nginx

Make sure to get Nginx is active (running) if not then start it manually:

sudo systemctl start nginx

Now we need to setup Nginx Server Block which allows us to serve subdomains from our server or multiple domains completely independent from each other.

  • Nginx Configuration resides at: /etc/nginx/

  • Nginx Main Serving Root at: /var/www/

Create your main domain/ip address serving page root.

sudo mkdir -p /var/www/

The permissions of your web roots should be correct if you haven’t modified your umask value, but you can make sure by typing:

sudo chmod -R 755 /var/www/

Using -R (recursive) will assign all sub-directories with the same permission as the parent directory.

Next, assign the directory ownership with the current $USER environment variable:

sudo chown -R $USER:$USER /var/www/

Now, let’s create a simple index.html webpage only for testing purposes because later we will bind the Nginx proxy to our localhost running Nodejs app.

nano /var/www/

Inside, put the following HTML code.

        <title>Welcome to!</title>
        <h1>Success!  The server block is working!</h1>
        <b>Meow Meow!</b>

Save and close Nano text editor.

In order for Nginx to serve this content, we should add configuration at /etc/nginx/sites-available.

sudo nano /etc/nginx/sites-available/

The convention of naming your config file the same as your domain name is pretty great when it comes to maintaining and your server.

Here is a simple Nginx configuration:

server {
        listen 80;
        listen [::]:80;

        root /var/www/;
        index index.html index.htm index.nginx-debian.html;
        #You can put your domain name here for ex:

        location / {
                try_files $uri $uri/ =404;

/etc/nginx/sites-available is only for storing your configuration, to make it active make sure to create a shortcut (link) the config to the sites-enabled directory for it to take effect on the server.

sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

To check if the newly add config has no errors run:

nginx -t

The last thing is to restart Nginx for the new config to take changes.

sudo systemctl restart nginx

Try to browse to your server’s IP address or domain name you should see the sample webpage served back to you, this means the Nginx server is fully running behind the ufw firewall.

Installing Node

You can install Node throughout apt package manager but it will only allow you to install the latest stable version not the latest one though so, therefore, we will use NVM instead.

sudo apt install wget

wget -qO- | bash

This will fetch the script and run it with bash to install nvm.

Depending on your configuration then you simply need to run the .profile or .bashrc from your home folder for applying environment changes.

source ~/.bashrc
source ~/.profile

You can run nvm command and it should work like a charm.

nvm -v

Let’s install Node and NPM using NVM:

nvm install 11.0

Afterwards, Node and NPM commands should be available through the command line.

node -v 

Installing PM2 and Cloning Repo

PM2 is a Nodejs process manager that keeps track of your running Node processes with a lot of cool features that makes it easier to debug and view running apps logs.

Let’s install it Globally.

npm install pm2 -g

it is as simple as that to install pm2.

Now, we need to get our Nodejs application code on the server, therefore, we will use a Git Version Control to push and then clone the repository, Github is a pretty great place for this job.

git add .
git commit -m "Initial Commit"
git remote add origin ""
git push origin master

Then simply clone the repository.

mkdir repos
cd repos
git clone [](

It depends on the framework you are using, let suppose it is based on a simple Nodejs/Express server with app.js as the main entry point of your application.

So we need to start the process using PM2.

cd /repos/your_repo

And use PM2

pm2 start server app.js

Here, we started app.js instance using PM2 and we gave it name as “server” so later we can identify our application by name.

You will get a table of statuses showing running/stopped apps and their Memory/CPU usage with so many other useful information for debugging.

Configuring Reverse Proxy

We have already added an Nginx configuration for the main server IP address or your domain name with simple index.html page.

Now, we need to bind it to a localhost address which represents the address of the currently running Nodejs application on the background.

This where an Nginx would truly work as a reverse proxy.

Let’s open up config again and edit it to act as a reverse proxy.

server {
        listen   80;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://localhost:3000/;
                proxy_redirect http://localhost:3000/ https://$server_name/;

This will make every request that comes through Nginx will be proxied (redirected) to http://localhost:3000 and there where our Nodejs server is running.

Make sure to change the host and port of your running Nodejs Application

If you can notice, we also provided custom headers that will be sent alongside the proxied request to our Nodejs server like the $host and $remote_addr which represent the real IP address of the user who issued the initial request.

Now we got everything setup and fully working.

You can try to access your server’s IP address or domain name on the browser you should see you Nodejs server is handling the request, pretty cool ahh!!

It is even cooler because we are using a reverse proxy and port 3000 (Nodejs server port) is not publicly available this helps a lot securing your Web Server aka Web Application.

No Comments Yet