How Do I Deploy a Node.js App on DigitalOcean with PM2?
Deploy a Node.js application on a DigitalOcean Droplet using PM2 for process management, auto-restart, and zero-downtime reloads.
The Stack
A typical Node.js deployment on DigitalOcean uses three layers: your app running on a port (e.g. 3000), PM2 to keep it alive and restart on crashes, and Nginx as a reverse proxy on port 80/443. This tutorial covers the PM2 layer.
Step 1 — Install Node.js
On your Droplet, install Node.js 20 LTS via NodeSource:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node --version
Step 2 — Upload Your Application
Clone from Git or copy files to /var/www/myapp:
git clone https://github.com/you/myapp.git /var/www/myapp
cd /var/www/myapp
npm ci --production
Create a .env file with production variables. Never commit secrets to Git.
Step 3 — Install and Configure PM2
sudo npm install -g pm2
Start your app:
pm2 start npm --name "myapp" -- start
Or point directly at your entry file:
pm2 start server.js --name "myapp"
Verify it is running:
pm2 status
pm2 logs myapp
Step 4 — Persist PM2 Across Reboots
pm2 startup systemd
pm2 save
The startup command prints a line you may need to copy and run with sudo. After that, PM2 restores all saved processes whenever the Droplet reboots.
Step 5 — Use an Ecosystem File
For production, create ecosystem.config.js in your project root:
module.exports = {
apps: [{
name: 'myapp',
script: 'server.js',
instances: 1,
env: {
NODE_ENV: 'production',
PORT: 3000
}
}]
};
Deploy with: pm2 start ecosystem.config.js
Step 6 — Zero-Downtime Reloads
When you push new code:
cd /var/www/myapp
git pull
npm ci --production
pm2 reload myapp
reload restarts the process gracefully without dropping active connections.
PM2 Commands Cheat Sheet
pm2 status— list all processespm2 logs— stream logspm2 monit— live CPU/memory dashboardpm2 restart myapp— hard restartpm2 delete myapp— remove from PM2
Pair PM2 with Nginx as a reverse proxy and Certbot for SSL to complete your production setup.