Home > Blog > How to run multiple Node.js servers using Nginx as a reverse proxy

How to run multiple Node.js servers using Nginx as a reverse proxy

Running multiple Node.js servers using the same port is not possible. My solution to this problem is by using a domain name and Nginx’s reverse proxy configuration to allow multiple Node.js servers to run in the same port.

My configuration looks like this:

Part 1: NodeJS servers

For testing purposes, I’m using this Hello World code and I’ll run this code in 3 instances using ports 3001, 3002, and 3003. Using pm2, I’ll make sure that these 3 apps will autostart. I modified every listening port in the server.js file in every folder of these 3 apps.

server.js

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

app.set('view-engine', 'ejs')

app.get('/', (req, res) => {
	res.render('index.ejs')
});

app.listen(3001) // the listening port, 3001 for app1, 3002 for app2, 3003 for app 3

And for testing purposes, I modified every index.ejs title to something like “App 1”, “App 2”, and “App3” just for identification.

index.ejs

<!DOCTYPE html>
<html>
<head>
	<title>App 1</title>
</head>
<body>
	<h1>NodeJS App 1</h1>
</body>
</html>

And the folder structure looks like this :

NodeJS servers list:

pm2 table

To test that every NodeJS server runs perfectly, use cURL to port 3001, 3002, and 3003.

curl localhost:3001
curl localhost:3002
curl localhost:3003

Output:

Port 3001

<!DOCTYPE html>
<html>
<head>
        <title>App 1</title>
</head>
<body>
        <h1>NodeJS App 1</h1>
</body>

Port 3002

<!DOCTYPE html>
<html>
<head>
        <title>App 2</title>
</head>
<body>
        <h1>NodeJS App 2</h1>
</body>

Port 3003

<!DOCTYPE html>
<html>
<head>
        <title>App 3</title>
</head>
<body>
        <h1>NodeJS App 3</h1>
</body>

Part 2: Nginx reverse proxy server

After testing every server using cURL, I configured the Nginx server blocks using nano

sudo nano /etc/nginx/sites-available/testapp1.gabrielkheisa.xyz
sudo nano /etc/nginx/sites-available/testapp2.gabrielkheisa.xyz
sudo nano /etc/nginx/sites-available/testapp3.gabrielkheisa.xyz

testapp1.gabrielkheisa.xyz

server{
    listen 80;
    server_name testapp1.gabrielkheisa.xyz ;
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

testapp2.gabrielkheisa.xyz

server{
    listen 80;
    server_name testapp2.gabrielkheisa.xyz ;
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:3002;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

testapp3.gabrielkheisa.xyz

server{
    listen 80;
    server_name testapp3.gabrielkheisa.xyz ;
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:3003;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Link these files to the sites-enabled directory

sudo ln -s /etc/nginx/sites-available/testapp1.gabrielkheisa.xyz  /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/testapp2.gabrielkheisa.xyz  /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/testapp3.gabrielkheisa.xyz /etc/nginx/sites-enabled/

Test the configurations using sudo nginx -t , if there’s no error, continue to restart the Nginx server using sudo systemctl restart nginx.

Part 3: Configure your domain name in your DNS record

Lastly, make sure you already configure your domain name to your A record with the value of the Nginx’s public IP or CNAME domain name.

These are my NodeJS test apps running behind the Nginx reverse proxy:

Reference:

Leave a Reply

Your email address will not be published. Required fields are marked *