Host Multiple Node Apps with nginx, pm2 with SSL certificate
Tags: node, pm2, nginx, linux
Published: 2024-07-08 10:29:17

---

Hey Developers,
If you're planning to host a Node.js application, or multiple Node.js applications, on a Linux server, consider this guide.
Before diving in, it's worth noting that there are various ways to set up a Node.js app with Nginx, and the abundance of documentation and YouTube videos can sometimes make the process confusing.
In my case, I launched an AWS EC2 instance with a Linux operating system. Let's assume the public IPv4 address of the EC2 instance, after attaching an Elastic IP address, is 11.111.111.111.

## Step -1 
Connect to your instance using SSH 
Install the Nodejs, npm and PM2 using the below commands in the terminal

```
 sudo apt update
 sudo apt install nodejs npm
 sudo npm install -g pm2
```

> _Max : What is PM2 for? _
> _PM2 is a renowned open-source process manager tailored for Node. js applications. It acts as a guardian, streamlining deployment, overseeing logs, monitoring resources, and ensuring minimal downtime for every application it manages.
> https://pm2.keymetrics.io/_

First, install the new Node.js applications or clone your existing Node.js repositories from your Git. Ensure both applications are running as per your requirements and are listening on different ports,
for example, ports "8000" and "8001".

## Step -2

Next, start the Node.js applications with PM2. Navigate to the respective folders of each application and use PM2 to run them in the background, ensuring they will restart automatically if the server restarts.

```
cd /path/to/your/first/app
pm2 start app.js --name "app1"

cd /path/to/your/second/app
pm2 start app.js --name "app2"

pm2 save     # saves the running processes
                  # if not saved, pm2 will forget the running apps on next boot
```
If you want pm2 to start on system boot

```
pm2 startup # starts pm2 on computer boot
```

## Step -3
Install Nginx and configure the Nginx file.
Command for installation

```
sudo apt install nginx
```
Open the configuration file using the nano editor or any other editor that you are comfortable with. 

> _Max : Could you provide more information about the Nano editor? Due to client-imposed restrictions, I am unable to use any other text editors. Your insights would be greatly appreciated_.

Nano is a nightmare for some Windows developers. However, GNU Nano is a text editor for Unix-like computing systems or operating environments using a command line interface. It emulates the Pico text editor, part of the Pine email client, and provides additional functionality. Unlike Pico, Nano is licensed under the GNU General Public License.
**Cheatsheet for Nano: https://www.nano-editor.org/dist/latest/cheatsheet.html**

> _Max : Can we use VSCode for this? _

If you're using Visual Studio Code (VS Code) for development, keep in mind that it doesn't have write permissions by default for folders outside the home directory on a Linux OS. You may need to install the appropriate VS Code extensions to manage these permissions effectively.
> **Extension name**: "Save as Root in Remote - SSH"
> **Externsion URL**: https://marketplace.visualstudio.com/items?itemName=yy0931.save-as-root


Devs who are using nano use the below command to open the file

```
sudo nano /etc/nginx/sites-available/default

```
Replace the content with the following configuration, adjusting the domain names and ports accordingly:

 - NODEJS APP 1 -
```

server {
    listen 80;
    server_name subdomain1.yourdomain.com;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```
- NODEJS APP 2 -

```
server {
    listen 80;
    server_name subdomain2.yourdomain.com;

    location / {
        proxy_pass http://localhost:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```
If you have only one node js application then, you can ignore "NODEJS APP2" in the above snippet and save it.
Check NGINX config:

```
sudo nginx -t

```
Restart the nginx:

```
sudo service nginx restart

```
Add your subdomain names (subdomain1.yourdomain.com & subdomain2.yourdomain.com) in Godaddy or Cloudflare etc as A record to your EC2 instance IP.

## Step -4
Obtain SSL Certificates with Certbot:

```
sudo apt install certbot python3-certbot-nginx

```
Run Certbot to obtain and install Free SSL certificates for your subdomains:

```
sudo certbot --nginx -d subdomain1.yourdomain.com -d subdomain2.yourdomain.com

```

>_ Max: If my case has only one domain, I will run the above command till sudo certbot - nginx -d subdomain1.yourdomain.com _
> _Yes, Perfecto! also, you don't have 2nd Server block in the below snippet._
Certbot should automatically update your Nginx configuration to include SSL settings. Ensure the new configuration looks like this:

```
server {
    listen 80;
    server_name subdomain1.yourdomain.com;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/subdomain1.yourdomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/subdomain1.yourdomain.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
    listen 80;
    server_name subdomain2.yourdomain.com;

    location / {
        proxy_pass http://localhost:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/subdomain2.yourdomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/subdomain2.yourdomain.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
```
Restart Nginx to apply the changes:

```
sudo systemctl restart nginx

```
Now, your two Node.js applications should be accessible via https://subdomain1.yourdomain.com and https://subdomain2.yourdomain.com with SSL encryption.

 Thank you !!!