Skip to main content

Node.js – Getting started guide

Connect, deploy and manage Node.js apps on your VPS using PM2, Nginx and nvm.

A
Written by Alexandru Stan
Updated yesterday

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
Did this answer your question?