🚀 Set Up CI/CD for Your Node.js App Using GitHub Actions and PM2
In our previous guide, we manually deployed a Node.js app to a VPS using Nginx and PM2. In this follow-up, we’ll take it one step further and automate the deployment process using GitHub Actions and SSH.
🎯 Why CI/CD Is Important
CI/CD (Continuous Integration and Continuous Deployment) helps streamline your development workflow by automatically running builds, tests, and deployments. Here’s why it’s essential:
- ✅ Speed: Automatically deploy code with every push to main.
- ✅ Consistency: Reduces the chance of human error in deployments.
- ✅ Reliability: Integrates tests to catch issues before production.
- ✅ Productivity: Developers focus on code, not manual deployment steps.
- ✅ Scalability: Works seamlessly as your team or infrastructure grows.
🔐 Step 1: Set Up SSH Access to Your VPS
- Generate an SSH key (if you haven’t already):
- View and copy your public key:
- Log into your VPS:
- If
.ssh
doesn't exist, create it: - Edit the
authorized_keys
file and paste your public key: - Set correct permissions:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
cat ~/.ssh/id_rsa.pub
ssh your_user@your_server_ip
mkdir -p ~/.ssh
nano ~/.ssh/authorized_keys
Paste the copied key from your local ~/.ssh/id_rsa.pub
into this file and save.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
This ensures your GitHub Actions workflow can SSH into your server securely using the corresponding private key.
🔧 Step 2: Add Secrets to GitHub
Navigate to your GitHub repository → Settings → Secrets and variables → Actions and add the following secrets:
VPS_SSH_KEY
: Paste the content of your private key (~/.ssh/id_rsa
)VPS_HOST
: Your server IP (e.g.,123.123.123.123
)VPS_USER
: Your VPS user (e.g.,ubuntu
orroot
)
⚙️ Step 3: GitHub Actions Workflow File
Create a file at .github/workflows/deploy.yml
and paste the following content:
name: Deploy to VPS
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.VPS_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts
- name: Deploy with PM2
run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} << 'EOF'
echo "🔁 Connected to VPS"
# Load Node.js environment (optional)
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Navigate to project directory
cd your-project-directory
git pull origin main
npm install
npx tsc
pm2 start dist/index.js --name your-project-name || pm2 restart your-project-name
pm2 save
echo "✅ Deployment complete!"
EOF
🚀 Step 4: Trigger Your First CI/CD Deployment
Push any changes to the main
branch and watch GitHub Actions handle the rest. It will connect to your server, pull the latest code, rebuild it, and restart the app via PM2. All automated, all hands-off.
✅ Conclusion
You’ve now connected your GitHub repository to your live server using CI/CD. This setup ensures that your application is always up to date without needing to manually SSH every time you push code.
👉 If you missed the initial deployment steps, check out our full guide on How to Deploy an Express.js App on Ubuntu with PM2 and Nginx.
Stay tuned for future posts where we’ll take this CI/CD flow even further — with staging environments, zero-downtime deployments, and automated testing pipelines.
0 Comments