TL;DR
Complete guide to deploying a production Node.js application on Ubuntu 24.04 with PM2, nginx, and SSL.
Key facts
- Topology
- Node.js on Ubuntu 24.04
TL;DR
This guide covers deploying a production Node.js application on Ubuntu 24.04, from system preparation through process management, reverse proxy, and SSL termination.
Prerequisites
- Ubuntu 24.04 LTS with root or sudo access
- A domain name pointing to your server's IP
- Your Node.js application in a Git repository
Step 1 — System preparation
Update the system and install essential packages:
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git build-essential
Create a non-root deploy user:
sudo adduser deploy
sudo usermod -aG sudo deploy
Step 2 — Install Node.js
Install Node.js via NodeSource (LTS version):
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node -v && npm -v
Or use nvm for version flexibility:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
source ~/.bashrc
nvm install 22
Step 3 — Deploy your application
sudo mkdir -p /var/www/myapp
sudo chown deploy:deploy /var/www/myapp
cd /var/www/myapp
git clone git@github.com:yourorg/yourapp.git .
npm ci --production
cp .env.example .env
# Edit .env with production values
Step 4 — Process management with PM2
Install PM2 globally and start your app:
sudo npm install -g pm2
pm2 start ecosystem.config.js --env production
pm2 startup systemd
pm2 save
A production ecosystem file:
module.exports = {
apps: [{
name: 'myapp',
script: 'server.js',
instances: 'max',
exec_mode: 'cluster',
max_memory_restart: '1G',
env_production: {
NODE_ENV: 'production',
PORT: 3000,
},
}],
};
Step 5 — nginx reverse proxy
sudo apt install -y nginx
Create a site configuration:
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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Step 6 — SSL and firewall
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable
With Reflex
Once deployed, install reflexd on your server to gain continuous monitoring, zero-downtime deploys, and automated incident response. Reflex manages PM2 process health, nginx configuration, SSL renewal, and disk/memory thresholds — replacing manual SSH maintenance with audited, repeatable playbooks. See How it works.