DEV Community

Cover image for Node.js Application with CI/CD GitLab Pipeline on AWS EC2

Node.js Application with CI/CD GitLab Pipeline on AWS EC2

“Automation is the key to speed and reliability in modern software development.”

Table of Contents

  1. Introduction
  2. Architecture Overview
  3. Prerequisites
  4. CI/CD Workflow (Step-by-Step)
  5. GitLab Pipeline Configuration
  6. Deployment Process on AWS EC2
  7. Security Best Practices
  8. Interesting Facts & Statistics
  9. FAQs
  10. Key Takeaways
  11. Conclusion

1. Introduction

Continuous Integration and Continuous Deployment (CI/CD) is a modern development practice that automates the process of building, testing, and deploying applications. This document explains how to set up a CI/CD pipeline for a Node.js application using GitLab CI/CD and deploy it automatically to an AWS EC2 instance.
The goal is to:

  • Automate deployment
  • Reduce manual errors
  • Improve development speed
  • Ensure reliable releases

2. Architecture Overview

  • Backend: Node.js
  • Version Control: GitLab
  • CI/CD Tool: GitLab Pipeline
  • Server: AWS EC2 (Ubuntu)
  • Process Manager: PM2
  • SSH Authentication: Secure Key-based login

High-level Flow:

  1. Developer pushes code to GitLab repository.
  2. GitLab pipeline triggers automatically.
  3. Pipeline installs dependencies and builds project.
  4. GitLab connects to EC2 via SSH.
  5. Code is pulled on EC2 server.
  6. Application restarts using PM2.
  7. Nginx routes HTTP traffic to the Node.js app

3. Prerequisites

Before setting up CI/CD, ensure the following:

GitLab Setup

  • GitLab repository created
  • Branches (dev/stage/prod) configured
  • GitLab Runner enabled (shared runner works)

AWS EC2 Setup

  • Ubuntu EC2 instance running
  • Node.js & npm installed
  • Git installed on server
  • SSH access configured PM2 installed globally
npm install pm2 -g
Enter fullscreen mode Exit fullscreen mode

SSH Key Setup

  • Generate SSH key on local system:
    ssh-keygen -t rsa -b 4096
Enter fullscreen mode Exit fullscreen mode
  • Add public key to EC2:
    ~/.ssh/authorized_keys
Enter fullscreen mode Exit fullscreen mode

- Add private key in GitLab:

    **GitLab → Settings → CI/CD → Variables**
Enter fullscreen mode Exit fullscreen mode
  • SSH_PRIVATE_KEY
  • SSH_HOST
  • SSH_USER

4. CI/CD Workflow (Step-by-Step)

Step 1: Developer Pushes Code
Developer pushes code to the GitLab branch (e.g., staging or production).

Step 2: Pipeline Triggered
GitLab detects changes and starts pipeline.

Step 3: Install Dependencies
Pipeline installs Node.js packages.

Step 4: SSH Connection
GitLab pipeline connects to AWS EC2 via SSH.

Step 5: Deployment
On EC2 server:
Pull latest code
Install dependencies
Restart Node app with PM2

Step 6: Live Deployment
Application updated automatically without manual login.

“CI/CD turns deployment from a risky event into a routine process.”

5. GitLab Pipeline Configuration

Create .gitlab-ci.yml in project root:
stages:

  • production deploy_to_ec2: stage: production image: alpine:latest only:
    • prd before_script:
    • apk add --no-cache openssh
    • mkdir -p ~/.ssh
    • cp "$SSH_PRIVATE_KEY" ~/.ssh/id_rsa
    • chmod 600 ~/.ssh/id_rsa
    • ssh-keyscan -H "$SSH_HOST" >> ~/.ssh/known_hosts
script:
   - |
     ssh "$SSH_USER@$SSH_HOST" << 'EOF'
       set -e


       echo "---------- Checking Directory ---------------"
       cd "$PATH_DIR"


       echo "---------------- Load NVM ----------------"
       export NVM_DIR="$HOME/.nvm"
       [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
       [ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"


       echo "--------Node Version:-----------"
       node -v || echo "Node not found"


       echo "----------NPM Version:--------------"
       npm -v || echo "npm not found"


       echo "----------------- Git Pull ------------------"
       git pull origin "$PRD_BRANCH"


       echo "----------------- npm install ----------------"
       npm install


       echo "----------------- Restart PM2 ----------------"
       pm2 restart all


       echo "---------------- Deployment Completed ----------------"
     EOF
Enter fullscreen mode Exit fullscreen mode

6. Deployment Process on AWS EC2

On EC2 server:

  • Clone project first time:
  • git clone
  • cd project
  • npm install
  • pm2 start app.js --name node-app

After CI/CD setup:
Deployment becomes automatic on every push.

Practical Demonstration (Images Explained)

Step 1. BEFORE: Original Login Page

Step 2. Making Changes & Pushing Code

  • This terminal screenshot shows the developer workflow.

  • The code was reflected in the GitLab repository 6 minutes ago.

Step 3. GitLab Pipelines Dashboard

  • This shows the Pipelines page in GitLab with successful deployments:

The highlighted row #2330658746 is the most recent deployment that was triggered automatically when code was pushed to the prd branch.

The pipeline deployment was successful. See the image below.

Step 4. AFTER: Updated Login Page

This shows the application after successful deployment. The title has changed from "Login Page" to "Addweb Login Page" - confirming the CI/CD pipeline worked correctly!

GitLab Pipeline Failure Scenario

Step 1. Intentionally Introduce an Error
To test pipeline failure behavior, we intentionally modified the package.json file by adding an invalid dependency:

Example change in package.json:

- "package-does-not-exist-3232": "2.1.0"

This package does not exist in the npm registry. the purpose was to simulate a real-world mistake such as:

  • Typo in package name
  • Incorrect dependency version
  • Invalid module added by mistake

Step 2. Commit and Push the Wrong Code
After modifying package.json, the changes were committed and pushed to the prd branch:

  • git commit -m "We mentioned the wrong package name in package.json."
  • git push origin prd

Since our GitLab Pipeline is configured to run automatically on the prd branch, this push immediately triggered a new pipeline execution.

Step 3. GitLab Pipeline Triggered Automatically
As expected, GitLab Pipelines started running automatically as soon as the code was pushed.
In the Pipelines dashboard we can see:

  • New pipeline execution created #2330702561
  • Status initially shown as “Failed”

This confirms that the CI/CD automation is working correctly.

Step 4. Pipeline Execution Failed
During pipeline execution, the following command was executed on the server:

- npm install **
Because we added a non-existent package, the installation failed with this error:
npm error 404 Not Found - GET https://registry.npmjs.org/package-does-not-exist-3232 - Not found
npm error 404 The requested resource **'package-does-not-exist-3232@2.1.0'
could not be found or you do not have permission to access it.
npm error 404

As a result:

  • The pipeline step stopped
  • Deployment process was aborted
  • Application was NOT restarted
  • Previous working version remained intact

If any step in the CI/CD pipeline fails, the deployment automatically stops. This protects production from broken or unstable code.

“First automate, then optimize.”

7. Security Best Practices

  • Use SSH keys instead of passwords
  • Restrict EC2 security group (only required ports)
  • Store secrets in GitLab CI/CD variables
  • Disable root login on EC2
  • Use environment variables for API keys
  • Enable firewall (UFW)

8. Interesting Facts & Statistics

  • Companies using CI/CD deploy 30x faster than manual deployment.
  • Automated pipelines reduce deployment failures by 40–60%.
  • GitLab CI/CD supports Auto DevOps for full automation.
  • AWS EC2 is used by millions of applications worldwide.
  • 90% of DevOps teams use CI/CD pipelines in production.

9. FAQs

Q1: Why use CI/CD for Node.js?
→ It automates testing and deployment, saving time and reducing errors.
Q2: Why GitLab CI/CD?
→ GitLab provides built-in CI/CD with repositories, making setup easier.
Q3: Why use PM2?
→ PM2 keeps Node.js apps running and supports auto restart.
Q4: Can we deploy multiple environments?
→ Yes, create separate branches:

  • dev
  • staging
  • production Q5: Is EC2 safe for production? → Yes, if proper security (SSH keys, firewall, updates) is applied.

10. Key Takeaways

  • CI/CD automates build and deployment.
  • GitLab pipeline integrates easily with AWS EC2.
  • SSH keys ensure secure deployment.
  • PM2 manages Node.js processes efficiently.
  • Automated deployment saves time and reduces downtime.

11. Conclusion

Implementing CI/CD for a Node.js application using GitLab and AWS EC2 significantly improves development workflow and deployment reliability.
With automated pipelines:

  • Developers can focus on coding
  • Deployments become faster
  • Errors are minimized
  • Applications stay updated continuously

CI/CD is no longer optional, it is a standard practice for modern scalable applications.

About the Author: Rajan is a DevOps Engineer at AddWebSolution, specializing in automation infrastructure, Optimize the CI/CD Pipelines and ensuring seamless deployments.

Top comments (0)