Continuous Deployment of Node.js REST API with AWS EC2 and GitHub Actions

Continuous Deployment of Node.js REST API with AWS EC2 and GitHub Actions

Step 1: Create Your Node.js Server

The first step is to create a Node.js REST API that will act as the backbone of your application.we’ll create a simple Node.js server from scratch. Below is a basic structure of the project as this stucture,

Article content

  1. Initialize a new Node.js project <npm init -y>
  2. Install dependencies <npm install express mongoose dotenv cors>
  3. Create server.js file as below with controllers ,db connection and etc

Article content

4. Environment Setup

Create a .env file to store environment variables such as your MongoDB connection string


If you are using MongoDB, ensure it’s accessible from any IP address by updating your network access settings in MongoDB Atlas (or your chosen DB host).

Article content

Step 2: Launch an EC2 Instance & Push Code

To host your Node.js REST API, you first need an AWS EC2 server and a Git repository to manage your code.


Article content

2.1 Launch an EC2 Instance

  • Log in to the AWS Console and navigate to EC2 → Instances → Launch Instance.
  • Select an Amazon Machine Image (AMI): Choose Ubuntu 22.04 LTS (recommended for Node.js apps).

Configure Security Group

  • SSH (22) – For remote access.
  • HTTP (80) – To allow web traffic.
  • HTTPS (443) – For secure web traffic.
  • Custom TCP (5000) – For your Node.js API server (optional)

Create/Select an SSH Key Pair

  • Download the .pem file.
  • Keep it secure; you will need it to connect to the server.

2.2 Prepare Your Git Repository


Article content

Step 3: Connect to Your EC2 Instance

Once your instance is up, connect to it using your SSH key.

After creating the instance and pushing code to the repository, connect to the EC2 instance via SSH using the .pem file.


Article content

Step 4: Setting Up GitHub Actions

GitHub Actions will handle the CI/CD pipeline, automatically deploying your Node.js REST API whenever you push code to the repository.

4.1 Enable GitHub Actions

  1. Go to your GitHub repository.
  2. Navigate to Settings → Actions → General.
  3. Ensure that Actions permissions are set to allow workflows.

4.2 Add a Self-Hosted Runner

If you want the pipeline to run directly on your EC2 server:

  1. In your repository, go to Settings → Actions → Runners → New self-hosted runner.
  2. Select Linux as the OS.
  3. Copy the commands provided by GitHub and run them on your EC2 instance to register the runner.


Article content


Article content

Step 5: Environment Setup for GitHub Actions

To ensure your Node.js application works seamlessly during deployment, you need to manage environment variables securely.

In your local Node.js project, creates a .env file containing values want to add as github repo screat keys ;

5.2 Add GitHub Secrets

  1. Go to Repository Settings → Secrets and Variables → Actions.
  2. Click New repository secret.
  3. Add your environment variables as key-value pairs, for example:


Article content

6. CI/CD Workflows

Create GitHub Actions workflows for CI/CD. Below is an example of a Node.js CI workflow.

name: Node.js CI/CD

on:
  push:
    branches: [ "main" ]

jobs:
  build:
    runs-on: self-hosted
    strategy:
      matrix:
        node-version: [22.x]
        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    - run: npm ci
    - run: npm run build --if-present
    - run: |
        touch .env
        echo "${{ secrets.MONGO_DB_URL }}" > .env        

Step 7: Installing Node.js and Nginx on Ubuntu

Before deploying your application, ensure your Ubuntu EC2 instance has both Node.js (to run the backend server) and Nginx (to serve as a reverse proxy and web server).

Why Node.js: Node.js is the runtime environment that allows you to execute JavaScript on the server. Your REST API needs Node.js to run its backend logic, handle HTTP requests, and communicate with the database

How to Install Node.js:

Run the following commands on your EC2 instance

sudo apt update
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
        

Why Nginx?

Nginx is a powerful, high-performance web server that enhances your API deployment by:

  • Acting as a reverse proxy, directing client requests to your Node.js backend.
  • Serving static assets (e.g., HTML, CSS, JavaScript).
  • Handling load balancing for scalability.
  • Providing SSL/TLS termination for secure HTTPS connections.
  • Offering caching to improve response times.

How to Install Nginx?

Run this command on your Ubuntu instance

sudo apt-get install -y nginx        

Key Roles of Nginx in Your Setup

  • Web Server: Delivers static content directly to clients.
  • Reverse Proxy: Forwards yourdomain.com/api requests to Node.js (localhost:5000).
  • Load Balancer: Spreads traffic across multiple Node.js instances.
  • TLS/SSL Offloading: Handles HTTPS, freeing Node.js from heavy encryption tasks.
  • Microservices Routing: Routes requests based on paths or services in your architecture.


8. Setting Up Nginx as Reverse Proxy

To route incoming requests to your Node.js app running on port 5000, configure Nginx as a reverse proxy

  1. Open the default Nginx configuration file:

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

2. Add this block inside the server {} section

location /api {
  rewrite ^/api/(.*)$ /api/$1 break;
  proxy_pass http://localhost:5000;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}        

3. Save and exit the file.

4. Restart Nginx to apply the changes:

sudo systemctl restart nginx        

9. Running Node.js App with PM2

PM2 is a Node.js process manager that keeps your app running continuously, even after crashes or restarts.

  1. Install PM2 globally

sudo npm install -g pm2        

2. Start your server:

pm2 start server.js --name=apiServer        
PM2 ensures your app keeps running in the background and restarts if it crashes.

10. Automatic Deployment with GitHub Actions

Your CI/CD pipeline is now fully automated. Every new push to the main branch will:

1. Trigger the Workflow

GitHub Actions automatically detects new code pushed to the main branch and starts the workflow.

2. CI Process (Continuous Integration)

2.1. Checkout Code Fetches the latest code using actions/checkout.

2.2. Setup Node.js Ensures the correct Node.js version is installed using actions/setup-node.

2.3. Install Dependencies Runs npm ci to install all required dependencies cleanly.

2.4. Run Tests (Optional) If included, tests like npm test are run to validate the changes.

3. CD Process (Continuous Deployment)

3.1. Deploy If everything passes, the workflow continues by:

  • Updating .env from GitHub secrets.
  • Restarting the Node.js app using pm2.


By following these steps, you've successfully set up a full CI/CD pipeline for your Node.js application using GitHub Actions, EC2, Nginx, and PM2. This setup allows you to:

  • Deploy code automatically on every push to the main branch.
  • Keep your app running reliably with PM2.
  • Serve requests efficiently and securely using Nginx as a reverse proxy.
  • Manage your deployment like a pro with minimal manual effort.

With this automation in place, you can now focus more on developing features, while your infrastructure takes care of deployment and uptime.


To view or add a comment, sign in

More articles by Dinesh Priyantha

Others also viewed

Explore content categories