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.

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.

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.