Skip to main content

How to deploy Node.js on Ubuntu 24.04 (production guide)

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.