Skip to content

engabelal/simple-nodejs-ec2-cicd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 Node.js CI/CD Pipeline to AWS EC2

Production-ready CI/CD pipeline deploying Node.js applications to AWS EC2 with 13-second in-place updates. Built with GitHub Actions, Terraform, and AWS Systems Manager.

Node.js Terraform GitHub Actions AWS Bash


⚡ Quick Start

# 1. Clone repository
git clone https://github.com/engabelal/simple-nodejs-ec2-cicd.git
cd simple-nodejs-ec2-cicd

# 2. Configure AWS credentials in GitHub Secrets
# 3. Deploy: Actions → Run workflow → deploy

# 4. Push updates (automatic 13s deployment!)
git add .
git commit -m "Update app"
git push origin main

🎯 Key Features

Feature Description
13-Second Updates In-place deployment without infrastructure recreation
🤖 Fully Automated Push to main → automatic build & deploy
🏗️ Infrastructure as Code Complete Terraform setup with remote state
🔒 Production-Ready Security best practices & IAM roles
💰 Cost-Effective ~$10/month on AWS (t3.micro)

📊 Performance Metrics

Stage Duration Trigger
Build 30s Every push/deploy
Plan 40s Manual deploy only
Deploy (first time) 3m 30s Manual deploy
Update (in-place) 13s Auto on push
Destroy 1m 30s Manual destroy

📸 Screenshots

CI/CD Pipeline

Deploy Stage Full deployment with Terraform

In-Place Update

Update Stage 13-second automatic update

Application UI

Web App ABCloudOps Quote Generator

App Features

App Features Quote display with stats


🛠️ Tech Stack

CI/CD GitHub Actions
IaC Terraform 1.10.4
Cloud AWS (EC2, S3, IAM, SSM, CloudWatch)
Runtime Node.js 20.x
Framework Express.js 4.x
Scripting Bash (user-data.sh, deploy-update.sh)
Application ABCloudOps Quote Generator (API integration, stats tracking)

📁 Project Structure

simple-nodejs-ec2-cicd/
├── .github/workflows/
│   └── deploy.yml              # 4-stage CI/CD pipeline
├── app/
│   ├── server.js               # Express.js REST API
│   ├── package.json            # Dependencies
│   └── public/                 # Frontend
│       ├── index.html          # Quote Generator UI
│       ├── style.css           # Glassmorphism design
│       └── app.js              # Frontend logic
├── iac/
│   ├── main.tf                 # EC2, IAM, Security Groups
│   ├── variables.tf            # Input variables
│   ├── terraform.tfvars        # Configuration values
│   ├── outputs.tf              # Outputs (IP, URL)
│   ├── backend.tf              # S3 remote state
│   ├── providers.tf            # AWS provider
│   └── scripts/
│       ├── user-data.sh        # EC2 initialization
│       └── deploy-update.sh    # In-place update via SSM
└── images/                     # Screenshots

🏗️ Architecture

┌─────────────────────────────────────────────────────────┐
│                    GitHub Actions                       │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  │
│  │  Build  │→ │  Plan   │→ │ Deploy  │  │ Update  │  │
│  │  (30s)  │  │  (40s)  │  │ (2m20s) │  │  (13s)  │  │
│  └─────────┘  └─────────┘  └─────────┘  └─────────┘  │
└─────────────────────────────────────────────────────────┘
                         ↓
              ┌──────────────────────┐
              │     Amazon S3        │
              │ • Artifacts (app.zip)│
              │ • Terraform State    │
              └──────────────────────┘
                         ↓
              ┌──────────────────────┐
              │      Terraform       │
              │   (IaC Engine)       │
              └──────────────────────┘
                         ↓
    ┌────────────────────────────────────────┐
    │        AWS Infrastructure              │
    │  ┌──────────┐  ┌──────┐  ┌──────────┐ │
    │  │   EC2    │  │ IAM  │  │ Security │ │
    │  │ Instance │  │ Role │  │  Group   │ │
    │  └──────────┘  └──────┘  └──────────┘ │
    └────────────────────────────────────────┘
                         ↓
              ┌──────────────────────┐
              │   Node.js App        │
              │   Port: 3000         │
              │   (Quote Generator)  │
              └──────────────────────┘

🔄 How It Works

First Deployment (3m 30s)

1. Build (30s)    → Test, package, upload to S3
2. Plan (40s)     → Terraform validate & plan
3. Deploy (2m20s) → Create EC2, IAM, SG, deploy app

Subsequent Updates (13s)

1. Build (30s)  → Test, package, upload to S3
2. Update (13s) → SSM sends commands to EC2
                → Download new app.zip
                → Restart application

Key Difference: Updates skip infrastructure provisioning!


⚙️ Setup Guide

Prerequisites

  • ✅ AWS Account
  • ✅ GitHub Account
  • ✅ Terraform ≥ 1.10.4 (optional, for local testing)

Step 1: Create S3 Bucket

aws s3 mb s3://my-terraform-state-bucket --region eu-north-1
aws s3api put-bucket-versioning \
  --bucket my-terraform-state-bucket \
  --versioning-configuration Status=Enabled

Step 2: Create EC2 Key Pair

aws ec2 create-key-pair --key-name my-ec2-key \
  --query 'KeyMaterial' --output text > ~/.ssh/my-ec2-key.pem
chmod 400 ~/.ssh/my-ec2-key.pem

Step 3: Configure GitHub Secrets

Settings → Secrets and variables → Actions → New repository secret

Secret Name Example Value Description
AWS_ACCESS_KEY_ID AKIA... AWS access key
AWS_SECRET_ACCESS_KEY wJalr... AWS secret key
AWS_KEY_PAIR_NAME my-ec2-key EC2 key pair name

Step 4: Update Configuration

Edit iac/terraform.tfvars:

aws_region       = "eu-north-1"
artifacts_bucket = "my-terraform-state-bucket"
instance_type    = "t3.micro"
app_port         = 3000
project_name     = "nodejs-cicd"

🚀 Deployment Scenarios

Scenario 1: First Deployment

# Push code to GitHub
git add .
git commit -m "Initial deployment"
git push origin main

# Deploy via GitHub Actions UI
# Actions → Run workflow → Select "deploy" → Run

Result: Infrastructure created + app deployed (3m 30s)


Scenario 2: Update Application (Automatic)

# Modify app code
vim app/server.js

# Push changes
git add app/
git commit -m "Update feature"
git push origin main

Result: Automatic 13-second update! No manual action needed.


Scenario 3: Manual Update

# GitHub Actions → Run workflow → Select "update" → Run

Use case: Force update without code changes


Scenario 4: Destroy Infrastructure

# GitHub Actions → Run workflow → Select "destroy" → Run

Result: All AWS resources removed (1m 30s)

⚠️ Note: Manually delete CloudWatch logs:

aws logs delete-log-group --log-group-name "/aws/lambda/nodejs-cicd"

🔧 Troubleshooting

Issue Solution
Build fails • Check Node.js version (20.x required)
• Verify npm test passes locally
Terraform state locked cd iac && terraform force-unlock <LOCK_ID>
EC2 not accessible • Check security group allows port 3000
• Verify instance is running
App not responding • SSH: ssh -i ~/.ssh/my-ec2-key.pem ec2-user@<ip>
• Check: ps aux | grep node
Update fails • Ensure instance exists (deploy first)
• Check SSM agent is running

📚 Advanced Topics

🔍 CI/CD Pipeline Details

Workflow Triggers

Event Trigger Jobs Use Case
Push to main Automatic Build → Update Daily development
Manual: deploy workflow_dispatch Build → Plan → Deploy First deployment
Manual: update workflow_dispatch Build → Update Force update
Manual: destroy workflow_dispatch Destroy Cleanup

Pipeline Stages

  1. Build - Test, package, upload artifact
  2. Plan - Terraform validate & plan (deploy only)
  3. Deploy - Provision infrastructure (first time)
  4. Update - In-place deployment (subsequent)
  5. Destroy - Remove all resources (manual)
⚡ In-Place Deployment Explained

How It Works

  1. GitHub Actions builds app.zip and uploads to S3
  2. Workflow finds EC2 instance by tag: project-name-server
  3. SSM sends commands to EC2:
    pkill -f "node server.js"              # Stop app
    aws s3 cp s3://bucket/artifacts/app.zip /tmp/  # Download
    unzip -o /tmp/app.zip -d /home/ec2-user/app/   # Extract
    nohup node server.js &                 # Restart
  4. Wait 30s for app to restart

Benefits

  • ✅ No infrastructure recreation
  • ✅ Preserves IP address
  • ✅ 13-second deployment
  • ✅ Zero additional cost
  • ✅ No downtime (quick restart)
🏗️ Infrastructure Components

AWS Resources Created

  • EC2 Instance - t3.micro, Amazon Linux 2023
  • Security Group - Ports 22 (SSH), 3000 (App)
  • IAM Role - S3 read, SSM managed instance
  • Instance Profile - Attached to EC2
  • S3 Bucket - Artifacts + Terraform state

Terraform Files

  • main.tf - Resource definitions
  • variables.tf - Input variables
  • terraform.tfvars - Configuration values
  • outputs.tf - Outputs (IP, URL)
  • backend.tf - S3 remote state
  • providers.tf - AWS provider config
🔒 Security Best Practices

Implemented

  • ✅ IAM roles (no hardcoded credentials on EC2)
  • ✅ Least privilege permissions
  • ✅ Security group rules (specific ports only)
  • ✅ GitHub Secrets for AWS credentials
  • ✅ S3 bucket versioning
  • ✅ Terraform remote state locking

Recommended Additions

  • 🔄 Enable AWS CloudTrail
  • 🔄 Add CloudWatch alarms
  • 🔄 Implement HTTPS (ALB + ACM)
  • 🔄 Use AWS Secrets Manager
  • 🔄 Enable VPC Flow Logs
  • 🔄 Implement backup strategy

🎓 Learning Outcomes

After completing this project, you'll understand:

CI/CD Design - Multi-stage pipeline architecture
Infrastructure as Code - Terraform best practices
AWS Services - EC2, IAM, S3, SSM, CloudWatch
GitHub Actions - Workflows, secrets, artifacts
Deployment Strategies - In-place vs blue-green
State Management - Remote state with S3
Security - IAM roles, least privilege
Automation - End-to-end DevOps workflow


📝 License

MIT License - Free to use for learning and production!


👨‍💻 Author

Ahmed Belal - DevOps & Cloud Engineer

🔗 GitHubLinkedInEmail


🌟 Support

Star this repo if you found it helpful!

🐛 Found a bug? Open an issue
💡 Have suggestions? Create a pull request
📧 Questions? Reach out via email


Built with ❤️ by Ahmed Belal | ABCloudOps

About

Production-ready CI/CD pipeline deploying Node.js apps to AWS EC2 with 13-second updates. Built with GitHub Actions, Terraform, and AWS (EC2, S3, IAM, SSM). Features automated testing, in-place deployments, and Infrastructure as Code. Includes ABCloudOps Quote Generator demo app.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors