π Deploy Node.js to AWS EC2 Using .pem Key and GitHub Actions (CI/CD)
If you're a developer or DevOps beginner looking to automate your Node.js app deployment from GitHub to an AWS EC2 instance, this guide is for you. We'll cover everything from launching an EC2 instance to deploying via GitHub Actions using a .pem file.
π¦ Prerequisites
AWS Account (Free tier is fine)
GitHub account with your Node.js app repo
Basic terminal skills
Node.js installed in your project
π§± Step 1: Launch EC2 Instance
β 1.1 Go to EC2 Console
Navigate to EC2 Dashboard
Click "Launch Instance"
β 1.2 Configure Instance
Name:
GitHub-CI-CD-ServerOS Image:
Ubuntu 24.04 LTSInstance Type:
t2.micro(Free Tier eligible)Key Pair: Click "Create Key Pair"
Name:
GitHub-CI-CD-Server-keyType: RSA
File format:
.pemDownload the
.pemand store it safely
π Step 2: Set Inbound Security Rules
During instance setup β Network settings:
β Inbound rules:
| Type | Port | Source |
| SSH | 22 | Anywhere |
| HTTP | 80 | Anywhere |
| Custom TCP | 3000 | Anywhere |
β
Now click Launch Instance
π Important: Later, restrict SSH access to My IP for security.
π» Step 3: Connect to EC2 with .pem
Open terminal or WSL and navigate to the folder where .pem is stored:
chmod 400 GitHub-CI-CD-Server-key.pem
ssh -i GitHub-CI-CD-Server-key.pem ubuntu@<your-ec2-ip>
Youβre now inside your EC2 machine π
βοΈ Step 4: Set Up Node.js on EC2
sudo apt update
sudo apt install nodejs npm -y
You can test with:
node -v
npm -v
π Step 5: Set Up GitHub Repository
Make sure your project includes:
index.jsorapp.jspackage.json
π‘οΈ Step 6: Add .pem to GitHub Secrets (Encrypted)
GitHub doesnβt allow file uploads, but we can convert .pem to a string:
β
6.1 Convert .pem to base64 string
base64 GitHub-CI-CD-Server-key.pem
Copy the long string inside .pem
A .pem (Privacy Enhanced Mail) file is a Base64-encoded file format commonly used to store private keys, certificates, and public keys in the context of secure communication, especially SSH access.
π‘ Example .pem File Structure
When you download a .pem file from AWS (like GitHub-CI-CD-Server-key.pem), it looks like this:
vbnetCopyEdit-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAx8+JhBdLqGRX...
...many lines of characters...
...never share this file...
...this is your private key...
-----END RSA PRIVATE KEY-----
BEGIN/END lines are delimiters
Contents between are the private RSA key, used to authenticate SSH sessions
Do not share this file publicly; it gives full access to your server
β 6.2 Add GitHub Secrets
Go to your GitHub repo β Settings β Secrets β Actions
Add these secrets:
| Name | Value |
PEM_KEY | (Paste the base64 encoded key) |
EC2_HOST | <your-ec2-public-ip> |
EC2_USER | ubuntu |
βοΈ Step 7: Create GitHub Actions Workflow
In your project repo:
mkdir -p .github/workflows
touch .github/workflows/deploy.yml
Paste the following:
name: Deploy to EC2 using PEM
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Decode PEM file
run: |
echo "${{ secrets.PEM_KEY }}" | base64 -d > key.pem
chmod 400 key.pem
- name: Deploy to EC2
run: |
ssh -o StrictHostKeyChecking=no -i key.pem ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} << 'EOF'
pkill node || true
rm -rf ~/app
mkdir ~/app
cd ~/app
echo "const http = require('http'); const PORT = 3000; http.createServer((req, res) => res.end('Hello from GitHub Actions!')).listen(PORT);" > index.js
nohup node index.js > out.log 2>&1 &
EOF
π Step 8: Test Deployment
Push your code to main:
git add .
git commit -m "Deploy via GitHub Actions"
git push origin main
After a minute, visit:
http://<your-ec2-ip>:3000
You should see:
Hello from GitHub Actions!
π‘οΈ Best Practices
Never expose
.pemdirectlyβuse GitHub secretsUse
pm2for production process managementAdd a reverse proxy (e.g. Nginx)
Restrict SSH port access to your IP only
β Summary
| Step | Done β |
| Launched EC2 instance | β |
Connected with .pem | β |
| Installed Node.js | β |
| Created GitHub Actions | β |
| Auto-deployed Node app | β |
π§Ύ Conclusion
Congratulations! Youβve successfully deployed your Node.js application to AWS EC2 using GitHub Actions and a .pem file. This setup enables continuous deployment with every code push, making your delivery process smooth, scalable, and hands-free.
For production-ready deployments, consider adding:
pm2for process managementReverse proxy with Nginx
HTTPS using Letβs Encrypt
Environment variable management with
.envor AWS Systems Manager
π Reference
You can find the complete working example and code in this GitHub repository: