Your VPS comes with Node.js LTS, npm, nvm, PM2, Nginx, Certbot and Git all pre-installed. This guide walks you through connecting, deploying your first app and keeping it running.
Connect to your VPS
SSH in as root:
ssh root@YOUR_IP_ADDRESS
Verify everything is working:
node --version npm --version pm2 --version
Deploy your first application
Clone your project or upload it via SFTP, then follow the steps below.
Step 1 – Clone your project
git clone https://github.com/youruser/yourproject.git cd yourproject
Step 2 – Install dependencies
npm install
Step 3 – Start with PM2
pm2 start app.js --name my-app
If your project uses a start script in package.json:
pm2 start npm --name my-app -- start
Step 4 – Save the process list
pm2 save
Saving means PM2 restarts your app automatically after a server reboot.
Manage processes with PM2
PM2 keeps your apps running and restarts them if they crash.
pm2 list # Show all running processes pm2 logs my-app # Stream live logs pm2 logs my-app --lines 100 # Show last 100 log lines pm2 restart my-app # Restart an app pm2 reload my-app # Zero-downtime reload pm2 stop my-app # Stop without removing pm2 delete my-app # Remove from PM2 pm2 monit # Live CPU and memory monitor pm2 show my-app # Detailed process info
Switch Node.js versions with nvm
nvm lets you install and switch between Node.js versions without touching the system installation.
nvm list # Show installed versions nvm list-remote # Show available versions nvm install 20 # Install Node 20 nvm use 20 # Switch to Node 20 nvm alias default 20 # Set as default for new sessions node --version # Confirm active version
Set up Nginx as a reverse proxy
Nginx is pre-installed. To point a domain at your Node.js app, edit the config:
Step 1 – Open the config
nano /etc/nginx/sites-available/nodejs-app
Step 2 – Replace the placeholder with your domain and port
server { listen 80; server_name yourdomain.com www.yourdomain.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-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; } }
Step 3 – Test and reload
nginx -t systemctl reload nginx
Other useful Nginx commands:
systemctl restart nginx tail -f /var/log/nginx/access.log tail -f /var/log/nginx/error.log
Add an SSL certificate
Once your domain's DNS A record points to the server IP, run:
certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot configures HTTPS and sets up auto-renewal automatically.
Use environment variables
Store API keys and credentials in a .env file rather than hardcoding them.
nano /root/yourproject/.env
Example:
PORT=3000 DATABASE_URL=postgres://user:pass@localhost/mydb API_KEY=your-secret-key
Install dotenv and load them in your app:
npm install dotenv
require('dotenv').config() console.log(process.env.API_KEY)
Enable the firewall
ufw is installed but inactive by default. To enable it:
ufw allow ssh ufw allow 'Nginx Full' ufw enable ufw status
Common issues
Port already in use
Find what's occupying the port and stop it:
lsof -i :3000 kill -9 PID
App not restarting after reboot
You probably haven't saved the PM2 process list:
pm2 save
Nginx showing 502 Bad Gateway
Your Node.js app isn't running or isn't listening on the expected port. Check:
pm2 list pm2 logs my-app
