Deploy a Node.js App on a VPS with PM2
Running a Node.js app on your own VPS gives you full control and a fixed hourly cost. Here's a clean setup that restarts on crashes and survives reboots.
1. Install Node.js LTS
The simplest reliable route is nvm, the Node version manager:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install --lts
node -v
2. Get your app onto the server
git clone https://github.com/you/your-app.git
cd your-app
npm ci --omit=dev
Put secrets in a .env file on the server — never commit them.
3. Run it under PM2
PM2 keeps the process alive, restarts it if it crashes, and collects logs.
npm install -g pm2
pm2 start server.js --name my-app
pm2 logs my-app
4. Start on boot
pm2 startup
pm2 save
pm2 startup prints one command — run it, and your app comes back after every reboot.
5. Put it behind Nginx with HTTPS
Keep Node listening on localhost (say port 3000) and let Nginx face the internet. Install Nginx and Certbot:
apt install -y nginx certbot python3-certbot-nginx
A minimal site config in /etc/nginx/sites-available/my-app:
server {
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable it and get a certificate:
ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
certbot --nginx -d app.example.com
Updating later
git pull && npm ci --omit=dev && pm2 restart my-app
Which size?
A typical Node app runs happily on Spark (2 GB RAM). Move up if you add a database on the same box.
Deploy a server and have your app online in minutes.