Tutorials26 Aug 2026Joy Team2 min read

How to deploy a Node.js app with PM2 and Nginx on Ubuntu 24.04

Stop running node index.js in a terminal. Deploy Node.js properly on Ubuntu 24.04 using the PM2 process manager and an Nginx reverse proxy on your Joy Services VPS.

1. Install Node.js

curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
node -v

2. Deploy your app

adduser --system --group --home /srv/app app
sudo -u app git clone https://github.com/you/yourapp /srv/app/current
cd /srv/app/current && sudo -u app npm ci --omit=dev

3. Run it with PM2

npm install -g pm2
sudo -u app pm2 start /srv/app/current/index.js --name app -i max   # cluster mode, one worker per vCPU
sudo -u app pm2 save
pm2 startup systemd -u app --hp /srv/app    # run the printed command

Your app should listen on 127.0.0.1:3000 (or another local port), never on 0.0.0.0.

4. Nginx reverse proxy

apt install -y nginx
cat > /etc/nginx/sites-available/app <<'EOF'
server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF
ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

5. HTTPS

apt install -y certbot python3-certbot-nginx
certbot --nginx -d example.com

6. Firewall and updates

ufw allow OpenSSH && ufw allow 'Nginx Full' && ufw enable

Deploy a new version with git pull && npm ci --omit=dev && pm2 reload app — zero-downtime in cluster mode. Logs: pm2 logs app. Take a snapshot before major upgrades, and put the Joy CDN in front for static assets.

nodejsnginxpm2ubuntu
Was this article helpful?
Corrections and suggestions go straight to the team that wrote it.
Need help?

Stuck on a step? The engineers who run the network answer tickets 24/7.

Contact support