How to deploy an Node.js application to a server with Nginx

In this guide, we’ll look at how to deploy an Node.js application on a VPS server and how to configure a reverse proxy for that application.

Cloud technology offers many options for deploying applications. You can use services such as Microsoft Azure, Google Cloud or AWS to host web applications. You can also use PaaS services, such as Heroku, for easy and fast deployment.

However, deploying a Node.js application to a bare-metal Linux server in the cloud can be challenging. Finding the right configuration and technology stack that meets your expectations can be time-consuming.

Preparing

Before you start, you need a server with a Linux operating system installed and an account with administrator privileges.

There are many Virtual Private Servers (VPS) available on various reliable platforms. You can choose any VPS hosting service that meets your requirements.

In our example we will use Ubuntu 20.04.

To deploy Node.Js application on a bare-metal server you need to do the following steps:

  • Install and configure Nginx.
  • Install Node.js and NPM.
  • Install PM2 process manager.
  • Place the Node.js application on the server.
  • Set up a reverse proxy and run the local server.

Let’s start by connecting to the server via ssh.

ssh username@server_ip_address

The server address and password should be in your personal account of the hosting provider.

Installing and configuring Nginx

Nginx is a web server used to serve static resources and as a reverse proxy that redirects client requests to other servers. It can be used as a server for web applications written in different languages, including Node.js.

Nginx is available in the package repository for most Linux distributions, making it easy to install.

If apache2 is installed on the server, it should be disabled, as it is fully configured to run on port 80 as an HTTP server. To do this, run the command:

sudo apt remove apache2*

After using this command, all apache2 packages will be unavailable.

Installing Nginx

Run the following commands to install Nginx:

sudo apt update
sudo apt install nginx

Once the installation is complete, check the status of the Nginx service and make sure it is running:

sudo systemctl status nginx

If the service is running, you will see a message like this:

● nginx.service - A high performance web server and a reverse proxy server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
    Active: active (running) since Fri 2023-02-19 12:00:00 PST; 1h ago

An important point! A firewall should be installed to protect our server. For example a UFW (Uncomplicated Firewall or “simple firewall”). However, I will not take this topic into account in this context.

Configuring Nginx

After installing Nginx, we need to configure it to handle client requests. First, we will create a configuration file for our domain.

sudo nano /etc/nginx/sites-available/servername.com

Replace servername.com with your real domain. You can also specify the ip address of the server in server_name. Then add the following text to the file:

server {
    server_name servername.com www.servername.com;
    listen 80;
    listen [::]:80;
    root /var/www/servername.com;
    index index.html;
  
    location / {
        try_files $uri $uri/ =404;
    }
}

In this example we have created a simple configuration file for Nginx that is configured to serve static files such as HTML, CSS, and JavaScript.

Then we need to create a symbolic link for our configuration file in the sites-enabled folder so that Nginx can use it:

sudo ln -s /etc/nginx/sites-available/servername.com /etc/nginx/sites-enabled/

After that, you need to check that the Nginx configuration is correct:

sudo nginx -t

If the output of the nginx -t command shows that the configuration is correct, you can restart Nginx with the command:

sudo systemctl restart nginx

Now, if you open a web browser and type in your server address, the default Nginx page should appear.

How to deploy an Node.js application to a server with Nginx

Installing Node.js

First we need to install Node.js on the server. To do this we will use NVM (Node Version Manager), which allows you to manage multiple versions of Node.js on one server. NVM can be downloaded from GitHub.

Let’s install NVM:

sudo apt install wget

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
After installation, restart the terminal to apply the changes.

If you don’t apply the changes and the error Command ‘nvm’ not found appears you need to create a .bash_profile

touch .bash_profile

And add there line

source ~/.nvm/nvm.sh

After that you need to restart the terminal again.

Then install the version of Node.js we want to use. In this example we will use version 18.7.0:

nvm install 18.7.0

Once installed, the Node and NPM commands will be available on the command line. Make sure that the Node.js version is correct by running the command:

node -v

Installing PM2

Next we will install PM2, a Node.js process management tool that allows you to run and monitor multiple Node.js applications on the same server. It automatically restarts applications if they crash and allows you to easily scale applications based on load.

PM2 also provides additional features such as clustering, logging, and monitoring that make it easy to manage and debug Node.js applications.

Let’s install PM2:

npm install pm2 -g

Deploying Node.js application to a server

Now you need to place the Node.js application code on the server. You can use Git or copy the files to the server via SSH.

Suppose our app.js application is based on a simple Node.js or Express server. We need to use PM2 to start the process. Let’s add our application to PM2 and name it “node_server” to easily identify it:

pm2 start dev/node_server/app.js --name="node_server"

After successfully starting the application, you will get a table with data about the running and stopped applications and CPU usage.

How to deploy an Node.js application to a server with Nginx

To save the current processes and synchronize them with the saved list, run the command:

pm2 save

This is needed so that you don’t lose all your settings during a server reboot.

Configuring the reverse proxy server

Now our Node.js application is up and running. However, for it to be accessible externally, we need to configure the reverse proxy server using Nginx.

To do this, edit the server configuration file /etc/nginx/sites-available/servername.com:

server {
    server_name servername.com www.servername.com;
    listen 80;
    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/; 
    }
}


After updating the configuration file and restarting Nginx, all requests sent to the server will be redirected to the application running on http://localhost:3000.

The proxied requests will send user headers – $remote_addr and $host – to the Node.js server which contain the user’s real IP address and the hostname the server is running on.

The reverse proxy configuration is now complete and your Node.js application is accessible from the outside.