TutorialsJune 9, 20263 min read

How to deploy a Node.js app on a VPS

Take a Node.js app from your laptop to a live server. This guide covers installing Node, running the app with PM2, and fronting it with Nginx and HTTPS.

NBy Nxeon

Deploying a Node.js app to a VPS means it runs 24/7 on your own server, reachable at your own domain. The production pattern is simple: run the app with a process manager, put Nginx in front as a reverse proxy, and add HTTPS. Here's the full path.

Step 1: Prepare the server

On a fresh Ubuntu VPS, update and create a non-root user to run the app (never run apps as root):

sudo apt update && sudo apt upgrade -y
sudo adduser deploy && sudo usermod -aG sudo deploy

Step 2: Install Node.js

Install a current LTS release from NodeSource:

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install nodejs -y
node -v && npm -v

Step 3: Get your code onto the server

Clone from Git (recommended) or copy files up:

git clone https://github.com/you/your-app.git
cd your-app
npm ci

Set any production environment variables in a .env file or your process manager, and build if your app needs it:

npm run build

Step 4: Keep it running with PM2

If you just run node app.js, the app dies when you close SSH or the server reboots. PM2 keeps it alive, restarts it on crashes, and starts it on boot:

sudo npm install -g pm2
pm2 start app.js --name my-app

For a build with an npm start script:

pm2 start npm --name my-app -- start

Make PM2 survive reboots:

pm2 startup systemd
pm2 save

Useful PM2 commands:

pm2 status
pm2 logs my-app
pm2 restart my-app

Step 5: Reverse-proxy with Nginx

Your app listens on a local port like 3000. You don't expose that directly — Nginx sits in front on port 80/443 and forwards requests. Install Nginx and create /etc/nginx/sites-available/my-app:

server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        proxy_pass http://localhost: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;
        proxy_cache_bypass $http_upgrade;
    }
}

The Upgrade/Connection headers are important — they let WebSockets work through the proxy. Enable and reload:

sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Step 6: Add HTTPS

Point your domain's A record at the server, then:

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

Your app is now live over HTTPS at your domain.

Step 7: Open the firewall

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Note you allow Nginx's ports, not 3000 — the app port stays private on localhost.

Updating the app

Deploys become a short routine:

cd your-app
git pull
npm ci
npm run build
pm2 restart my-app

Why a VPS for Node

Serverless is fine for some workloads, but a VPS gives you a persistent process, WebSockets, background jobs and predictable cost — all things Node apps often need. On a Nxeon NVMe VPS with full root you control the Node version, the proxy and the whole environment, and npm ci flies on fast disk. Set this pattern up once and every future deploy is a three-line update.

#nodejs#deployment#pm2#nginx#vps

Deploy your first server in under a minute

No credit card required to get started. Spin up a VPS, break things, and only pay for what you keep running.