DevOps
Complete AWS EC2 Ubuntu Deployment Guide (Node.js + PM2 + Nginx)
Published
Aug 11, 2026
Reading Time
15 min read
Admin
Author
Deploy a Node.js/Express backend on AWS EC2 Ubuntu: install Node, clone the repo, configure .env, run with PM2, and put Nginx in front with a firewall checklist.
Overview
Deploy a Node.js / Express backend on an AWS EC2 Ubuntu instance using PM2 and Nginx as a reverse proxy. Follow the sections in order the first time; later use the command reference when something breaks.
1. Connect to EC2
ssh -i your-key.pem ubuntu@YOUR_SERVER_IP
Example:
ssh -i myserver.pem ubuntu@13.126.xxx.xxx
- Exit server:
exit - Switch to root (optional):
sudo su - Current user:
whoami - Current directory:
pwd
2. Update Ubuntu
sudo apt update
sudo apt upgrade -y
sudo apt autoremove -y
sudo apt clean
3. Install Git
sudo apt install git -y
git --version
git config --global user.name "Your Name"
git config --global user.email "your-email@example.com"
git config --list
which git
4. Install Node.js (LTS)
sudo apt install curl -y
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install nodejs -y
node -v
npm -v
which node
which npm
5. Clone the repository
# HTTPS
git clone https://github.com/username/project.git
# SSH
git clone git@github.com:username/project.git
cd project
git branch
git pull origin main
6. Environment variables
nano .env
Example .env:
PORT=5000
DATABASE_URL=
JWT_SECRET=
REDIS_URL=
AWS_ACCESS_KEY=
AWS_SECRET_KEY=
In nano: Ctrl+O, Enter, Ctrl+X. Verify with cat .env and ls -la.
7. Install dependencies
npm install
# Clean install if needed
rm -rf node_modules package-lock.json
npm install
8. Build the project
# TypeScript
npm run build
# Prisma (if used)
npx prisma generate
npx prisma migrate deploy
npm run seed
9. Test the app
npm run dev # development
npm start # production (often node dist/server.js)
9.1 Install Redis (optional)
sudo apt install redis-server -y
9.2 Install MongoDB (optional)
Server packages
curl -fsSL https://pgp.mongodb.com/server-8.0.asc | \\
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | \\
sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
sudo apt update
sudo apt install -y mongodb-org
mongod --version
Start and enable
sudo systemctl start mongod
sudo systemctl enable mongod
sudo systemctl status mongod
Expected: Active: active (running).
Kernel compatibility override (if needed)
sudo systemctl edit mongod
Add:
[Service]
Environment="MONGODB_DISABLE_KERNEL_VERSION_CHECK=true"
sudo systemctl daemon-reload
sudo systemctl restart mongod
sudo systemctl status mongod
Logs and shell
sudo journalctl -u mongod -n 50 --no-pager
sudo tail -50 /var/log/mongodb/mongod.log
sudo apt install mongodb-mongosh
mongosh
MongoDB Compass is a GUI — it needs a desktop display. On a headless EC2 box, use mongosh instead of Compass.
10. Install and run with PM2
sudo npm install -g pm2
pm2 -v
pm2 start npm --name backend -- start
# or
pm2 start dist/server.js --name backend
11. Essential PM2 commands
pm2 list
pm2 logs
pm2 logs backend
pm2 restart backend
pm2 reload backend
pm2 stop backend
pm2 delete backend
pm2 monit
pm2 save
pm2 startup
# run the command PM2 prints, then:
pm2 save
12. Install Nginx
sudo apt install nginx -y
sudo systemctl status nginx
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl restart nginx
sudo systemctl reload nginx
13. Nginx reverse proxy
sudo nano /etc/nginx/sites-available/backend
server {
listen 80;
server_name YOUR_SERVER_IP;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
sudo ln -s /etc/nginx/sites-available/backend /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
14. Firewall (UFW)
sudo apt install ufw -y
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo ufw status
15. Useful Ubuntu commands
pwd
ls
ls -la
cd foldername
cd ..
cd ~
cd /
mkdir folder
rm -rf folder
rm file.txt
mv old new
cp file file2
16. Disk, memory, and CPU
df -h
du -sh *
free -h
lscpu
17. Processes and ports
ps aux
ps aux | grep node
kill PID
kill -9 PID
sudo ss -tulpn
sudo lsof -i :5000
sudo kill -9 PID
18. Logs
pm2 logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
journalctl -xe
19. Git on the server
git status
git pull
git fetch
git branch
git checkout main
git log --oneline
20. Node / npm helpers
node -v
npm -v
npm list -g --depth=0
npm cache clean --force
21. Service status
systemctl status nginx
systemctl status ssh
systemctl status docker
sudo systemctl restart nginx
22. Common errors and fixes
Port already in use
sudo lsof -i :5000
sudo kill -9 PID
Node not found
which node
node -v
sudo apt install nodejs -y
Git permission denied
ssh-keygen -t ed25519 -C "your@email.com"
cat ~/.ssh/id_ed25519.pub
Add the public key to GitHub, then clone over SSH again.
PM2 not found
sudo npm install -g pm2
Nginx config test
sudo nginx -t
Reboot / shutdown
sudo reboot
sudo shutdown now
Deployment checklist
- Ubuntu updated
- Git + Node installed
- Repo cloned
.envcreatednpm install+ build done- PM2 running and saved (
pm2 startup+pm2 save) - Nginx installed and reverse proxy configured
- Firewall allows SSH + 80/443
- Backend reachable
- Domain + SSL (recommended next step)
Final URLs
- Without Nginx:
http://SERVER_IP:5000 - With Nginx:
http://SERVER_IP - With SSL:
https://yourdomain.com
Once PM2 and Nginx are stable, every deploy is usually: git pull → build → pm2 restart backend.
#aws#ec2#nodejs#nginx#pm2#devops
Share:

Comments
0Login to post a comment.
Sign inLoading comments…