Easy Deployment of Nodejs Applications on EC2 with PM2 and NGINX

PulkitPulkit
6 min read

Deploying Node.js applications can be a daunting task, especially when aiming for a robust and scalable production environment. However, with the right tools and a clear process, it becomes much more manageable. In this guide, I will walk you through the easy deployment of Node.js applications on Amazon EC2 using PM2 and NGINX. By the end of this article, you'll have a solid understanding of how to set up your server, manage your application processes, and configure a reverse proxy to handle incoming traffic efficiently. Let's dive in!

Initializing the Node project

For this walkthrough, I will be deploying a simple Express hello-world application on EC2. Let's start by initialize a simple express app

npm init -y

Add express as a dependency

npm install express

Adding a simple / endpoint that returns a hello world object

const express= require("express");

const app= express();

app.get("/",(req,res)=>{
  res.json({ message: "Hello world" });
});

const PORT= 3000;
app.listen(PORT,()=>{
  console.log("app is listening on port " + PORT );
});

Start your express application

node index.js

and you see a / endpoint like this

Deploying the app on AWS EC2

Let's bootstrap an EC2 instance

You can directly head over to AWS EC2 create instance page

You can name the ec2 instance according to you, I am naming it demo-nodejs.

Select any image that suits you best, or you can learn more about these here. I have selected the basic Ubuntu image, as it is widely used and has good support.

Since I am using this instance for this walkthrough, I have selected a free-tier Instance type, you can choose the instance types according to your need, know more about this here

And finally launch the instance, I am going to access this instance from AWS connect, If you want to ssh into the instance you can create a key-pair and do that

Click on connect to access your instance and start setting up your environment.

Now you have access to you ec2 instance from your brower

Setting up the Environment in the instance

Update the package lists by running:

sudo apt-get update && sudo apt-get upgrade

Installing node using the NVM(Node Version Manager)

Reference: How To Install Node.js on Ubuntu 20.04

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash

This will install the nvm script to your user account. To use it, you must first source your .bashrc file:

source ~/.bashrc

Now let's install node using the nvm

nvm install node

To check if it is installed correctly:

node --version

Starting the server on EC2

You can either upload your code on GitHub and then clone it in Ec2 or use any other viable method to get your code on the instance.

If you are able to see this or whatever log you added in the app.listen() you are good to go.

Starting the server with pm2

Now we can do a node index.js and we're good to go, but this approach has its limitations. Running your application this way means it won't automatically restart if it crashes, and it won't start again if the server reboots. This is where PM2 comes in. PM2 is a production process manager for Node.js applications that ensures your application stays online, even in the face of unexpected issues. It provides features like process monitoring, automatic restarts, and load balancing, making it an essential tool for managing Node.js applications in a production environment. Let's explore how to set up and use PM2 to manage our Node.js application on EC2.

So let's install pm2

npm install -g pm2

Now we'll start the express app using pm2

pm2 start index.js

Now we have deployed the app, but it won't be accessible on the internet yet. To make it accessible, let's configure the necessary security groups and open the required ports. This will allow external traffic to reach our application.

Navigate to the Security tab on the Instance page. and click on the Security group which is sg-09f5337d4845d84fb (launch-wizard-1) here.

Click on Edit inbound rules

Add a new Inbound rue with Type of Custom TCP and PORT 3000. To make it accessible add 0.0.0.0/0 from the CIDR block.

Now get the Ip from the home page of your instance

My Instance's Ip is ec2-54-242-52-243.compute-1.amazonaws.com, Now the app is deployed on port 300, So to access the app navigate to

http://ec2-54-242-52-243.compute-1.amazonaws.com:3000

And voilà! Your application is now accessible on the internet.

But wait the url for the application is https://ec2-54-242-52-243.compute-1.amazonaws.com:3000, prettly ugly to add :3000 in the url. Have you ever seen we go to http://google.com:5173. No! right, So let's fix this next

Configuring Nginx

To make your application accessible without appending the port number to the URL, we will set up NGINX as a reverse proxy. This will allow NGINX to handle incoming traffic on the default HTTP port (80) and forward it to your Node.js application running on port 3000.

Steps to add and Install nginx

  1. Install NGINX

    First, install NGINX on your EC2 instance by running the following commands:

     sudo apt update
     sudo apt install nginx
    
  2. Start and Enable NGINX

    Ensure that NGINX is running and set to start on boot:

     sudo systemctl start nginx
     sudo systemctl enable nginx
    
  3. Configure NGINX as a Reverse Proxy

    Open the NGINX configuration file for editing:

     sudo vi /etc/nginx/sites-available/default
    

    Replace the contents of the file with the following configuration:

     server {
         listen 80;
         server_name ec2-54-242-52-243.compute-1.amazonaws.com;
    
         location / {
             proxy_pass http://localhost:3000;
             proxy_http_version 1.1;
             proxy_set_header Upgrade $http_upgrade;
             proxy_set_header Connection 'upgrade';
             proxy_set_header Host $host;
             proxy_cache_bypass $http_upgrade;
         }
     }
    
    1. Make sure to replace ec2-54-242-52-243.compute-1.amazonaws.com with your actual domain name or public IP address.

    2. Test the NGINX Configuration

      Test the NGINX configuration to ensure there are no syntax errors:

       sudo nginx -t
      

      If the test is successful, you should see a message indicating that the configuration file is okay.

    3. Restart NGINX

      Restart NGINX to apply the new configuration:

       sudo systemctl restart nginx
      
    4. Update Security Group to Allow HTTP Traffic

      Ensure that your EC2 instance's security group allows inbound traffic on port 80. Navigate to the Security Groups section in the AWS Management Console, select your instance's security group, and add a rule to allow HTTP traffic on port 80 from any IP address (0.0.0.0/0) and you may remove the 3000 port that's no more needed

    5. Access Your Application

      Now, you should be able to access your Node.js application using your domain name or public IP address without appending the port number. For example:

       http://your_domain_or_IP
      

      Your application should be accessible, and NGINX will forward the traffic to your Node.js application running on port 3000.

By following this guide, you have successfully deployed a Node.js application on an EC2 instance using PM2 and NGINX. This setup not only ensures that your application remains robust and scalable but also provides a clean and professional URL for your users. With PM2 managing your application processes and NGINX handling incoming traffic, you can focus on developing your application further, knowing that your deployment is in good hands. Happy coding!

1
Subscribe to my newsletter

Read articles from Pulkit directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Pulkit
Pulkit

Hi there! 👋 I'm Pulkit, a passionate web and app developer specializing in MERN and React Native technologies. With a keen interest in open-source contributions and competitive programming, I love building innovative solutions and sharing my knowledge with the community. Follow along for insights, tutorials, and updates on my coding journey!