Web Servers & Stacks Intermediate 20 min

How to Deploy Node.js Applications with PM2 and Nginx on Ubuntu 24.04

Deploy production Node.js backends with automatic daemon restarts, cluster scaling, and Nginx SSL termination

IndSoft Cloud Engineering
Reviewed October 2026
Production Verified Commands

Guide Overview & Architecture Outcome

By following this guide, you will have a production-ready Node.js application running continuously in the background using PM2 process manager. It will be securely reverse-proxied behind Nginx with automatic crash restarts and system reboot persistence.

Prerequisites & System Requirements

An Ubuntu 24.04 instance with at least 1 GB RAM, non-root user with sudo access. Recommended: IndSoft Node.js Optimized Cloud.

1

Install Node.js LTS via NodeSource Repository

Add the NodeSource repository to install the latest Long Term Support (LTS) release of Node.js and npm.

bash · step-1-command.sh
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install nodejs -y node -v && npm -v
Expected System Output:
v20.18.0 10.8.2
2

Install PM2 Process Manager Globally

Install PM2 globally using npm to handle process monitoring, clustering, and auto-restart on crashes.

bash · step-2-command.sh
sudo npm install pm2@latest -g
Expected System Output:
+ pm2@5.4.2 added 184 packages in 5s
3

Start Your Node Application with PM2

Navigate to your application directory, launch your entry point with PM2, and register the systemd startup hook.

bash · step-3-command.sh
cd /var/www/my-app npm install pm2 start app.js --name 'backend-api' pm2 startup systemd pm2 save
Expected System Output:
┌─────┬──────────────┬─────────────┬─────────┬─────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ ├─────┼──────────────┼─────────────┼─────────┼─────────┼──────────┤ │ 0 │ backend-api │ fork │ 0 │ online │ 0% │ └─────┴──────────────┴─────────────┴─────────┴─────────┴──────────┘
4

Configure Nginx as a High-Performance Reverse Proxy

Route incoming web traffic on port 80/443 to your Node.js application running locally on port 3000.

bash · step-4-command.sh
sudo nano /etc/nginx/sites-available/nodejs-app # proxy_pass http://localhost:3000; sudo ln -s /etc/nginx/sites-available/nodejs-app /etc/nginx/sites-enabled/ sudo systemctl reload nginx
Expected System Output:
Reloading nginx: nginx.service [ OK ]

Check That It Worked (Verification)

Run this quick verification check to confirm your installation is responding properly:

verify-service.sh
pm2 status
Expected Response:
App name [backend-api] is online with uptime 1h 45m, 0 restarts, memory usage 48.2MB.

Troubleshooting Common Errors

Quick resolutions for frequent setup pitfalls and configuration issues.

Diagnostic Tips
App crashes on restart or memory leak
Run pm2 logs backend-api to inspect error tracebacks. Use pm2 start app.js --max-memory-restart 300M to guard against memory exhaustion.
Nginx 502 Bad Gateway to Node.js
Check if the Node.js process is listening on the expected port: sudo ss -tulpn | grep 3000.
PM2 does not restart after server reboot
Ensure you executed pm2 save after generating the systemd startup script with pm2 startup.