Setting Up CI/CD for EC2 Deployment GitHub Actions for Node.js
Learn how to set up a CI/CD pipeline with GitHub Actions to automatically build, test, and deploy your Node.js application to AWS EC2 on every git push.
Setting Up CI/CD for EC2 Deployment
Continuous Integration and Continuous Deployment (CI/CD) automates the process of building, testing, and deploying your Node.js app to EC2. This guide uses GitHub Actions.
What Is CI/CD?
- Continuous Integration (CI) Automatically build and test on every push
- Continuous Deployment (CD) Automatically deploy to production after tests pass
Benefits
- Consistency Same deployment process every time
- Speed Deploy in minutes, not hours
- Safety Tests run before deployment
- Rollback Easy to revert to a previous version
- No manual errors Everything is automated
Step 1: Create the GitHub Actions Workflow
Create a file at .github/workflows/deploy.yml in your repository:
name: Deploy to EC2 on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm install - name: Run tests run: npm test - name: Deploy to EC2 uses: appleboy/[email protected] with: host: ${{ secrets.EC2_HOST }} username: ubuntu key: ${{ secrets.EC2_SSH_KEY }} script: | cd /home/ubuntu/devtinder-backend git pull origin main npm install pm2 restart devtinder-api pm2 save
Step 2: Add GitHub Secrets
Go to your GitHub repository → Settings → Secrets and variables → Actions → New repository secret:
- EC2_HOST Your EC2 public IP or domain (e.g.,
12.34.56.78) - EC2_SSH_KEY The contents of your .pem key file (open it in a text editor and copy everything)
To get the SSH key content:
cat your-key.pem # Copy everything including BEGIN and END lines
Step 3: How the Workflow Works
- Trigger On every push to the
mainbranch - Checkout Gets the latest code
- Setup Node.js Installs Node.js 20 on the GitHub runner
- Install dependencies Runs
npm install - Run tests Runs
npm test(add tests to your project) - Deploy SSHs into EC2, pulls the latest code, installs dependencies, and restarts PM2
Step 4: Advanced Workflow with Build Step
If you have a build step (e.g., TypeScript compilation):
- name: Build run: npm run build - name: Deploy to EC2 uses: appleboy/[email protected] with: host: ${{ secrets.EC2_HOST }} username: ubuntu key: ${{ secrets.EC2_SSH_KEY }} script: | cd /home/ubuntu/devtinder-backend git pull origin main npm install npm run build pm2 restart devtinder-api pm2 save
Step 5: Add Environment Variables to EC2
If your app needs new environment variables, SSH into EC2 and update .env manually:
ssh -i your-key.pem ubuntu@your-ip cd devtinder-backend nano .env # Add new variables pm2 restart devtinder-api
For automated env updates, use GitHub Secrets and write them during deployment:
- name: Deploy to EC2 uses: appleboy/[email protected] with: host: ${{ secrets.EC2_HOST }} username: ubuntu key: ${{ secrets.EC2_SSH_KEY }} envs: MONGODB_URI, JWT_SECRET script: | cd /home/ubuntu/devtinder-backend git pull origin main npm install echo "MONGODB_URI=$MONGODB_URI" > .env echo "JWT_SECRET=$JWT_SECRET" >> .env pm2 restart devtinder-api
Step 6: Test the Pipeline
- Make a change to your code
- Commit and push to main:
git add . git commit -m "feat: update something" git push origin main - Go to GitHub → Actions tab
- Watch the workflow run
- Verify the deployment on your EC2 instance
Step 7: Add Slack Notifications (Optional)
- name: Notify Slack if: always() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} channel: '#deployments' env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
The Takeaway
CI/CD with GitHub Actions automates deployment to EC2. Create a workflow that triggers on push to main, runs tests, SSHs into EC2, pulls the latest code, installs dependencies, and restarts PM2. Store EC2 host and SSH key as GitHub Secrets. This ensures consistent, fast, and safe deployments with no manual SSH needed.
Create a .github/workflows/deploy.yml file that triggers on push to main. Steps: checkout code, setup Node.js, npm install, npm test, then SSH into EC2 to git pull, npm install, and pm2 restart. Store EC2 host IP and SSH key as GitHub Secrets.
Add EC2_HOST (your EC2 public IP or domain) and EC2_SSH_KEY (the contents of your .pem key file, including BEGIN and END lines). Go to repository Settings → Secrets and variables → Actions → New repository secret.
On push to main, GitHub runs the workflow on a runner. It checks out the code, installs dependencies, runs tests, then uses appleboy/ssh-action to SSH into EC2. On EC2, it runs git pull, npm install, and pm2 restart to deploy the new code.
For manual setup, SSH into EC2 and update .env. For automated setup, store env values as GitHub Secrets and use the envs parameter in the SSH action to write them to .env during deployment.
Add a step using 8398a7/action-slack@v3 with status: ${{ job.status }} and your Slack webhook URL stored as a GitHub Secret. Set if: always() to get notified on both success and failure.
Ready to master Node.js completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master Node.js
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

