How to Host a Node.js or Next.js App on a VPS (Nginx, PM2 and SSL)
A practical, step-by-step guide to deploying a Node.js or Next.js application on an Ubuntu VPS with PM2 for process management, Nginx as a reverse proxy and a free SSL certificate.
Back to BlogWhat You Will Set Up
By the end of this guide your application will run as a background service that restarts automatically, sit behind Nginx on ports 80 and 443, and be served over HTTPS with a free Let's Encrypt certificate.
The steps assume a fresh Ubuntu LTS server, a domain name you control and an application that listens on a local port such as 3000. Commands shown are typical; adjust names and paths to your project.
1. Log In and Create a Non-Root User
Connect to the server with SSH using the details from your provider.
ssh root@YOUR_SERVER_IP
Create a regular user with sudo rights and use it from now on.
adduser deploy
usermod -aG sudo deploy
Copy your SSH key to the new user, then log in as that user and, once it works, disable root and password logins in the SSH configuration. Working as root all the time is a common cause of accidents.
2. Update the System and Turn On the Firewall
sudo apt update && sudo apt upgrade -y
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
Only SSH, HTTP and HTTPS are open. Your application port stays closed to the internet because Nginx will reach it locally.
3. Install Node.js
Install a current Node.js LTS release. The NodeSource repository or the nvm tool both work. After installing, check the versions.
node -v
npm -v
Use the same major Node version in production that you develop with, to avoid surprises.
4. Deploy Your Code and Build It
Clone your repository into a folder such as /var/www/myapp, install dependencies and build.
git clone YOUR_REPO_URL /var/www/myapp
cd /var/www/myapp
npm ci
npm run build
Place environment variables in a .env file that is not committed to git. For Next.js, npm run build creates the production build that npm start serves.
5. Keep It Running with PM2
PM2 runs your app in the background, restarts it if it crashes and starts it after a reboot.
sudo npm install -g pm2
pm2 start npm --name myapp -- start
pm2 save
pm2 startup
Run the command that pm2 startup prints, so the process list is restored when the server restarts. Use pm2 logs myapp to see output and pm2 restart myapp after each deployment.
6. Put Nginx in Front as a Reverse Proxy
Install Nginx and create a site configuration that forwards requests to your app.
sudo apt install nginx -y
In /etc/nginx/sites-available/myapp, set server_name to your domain and add a location block with proxy_pass http://127.0.0.1:3000; plus the usual proxy_set_header lines for Host, X-Real-IP and X-Forwarded-For.
Enable it and reload.
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Point your domain's A record at the server's IP address first so the next step works.
7. Add a Free SSL Certificate
Certbot obtains and renews a Let's Encrypt certificate for Nginx automatically.
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com
Choose the option to redirect HTTP to HTTPS. Certbot installs a renewal timer, and you can test it with sudo certbot renew --dry-run.
Updating Your App Later
For each release, pull the latest code, install dependencies if they changed, rebuild and restart.
cd /var/www/myapp && git pull && npm ci && npm run build && pm2 restart myapp
If you would rather not manage the server yourself, webzworld offers managed Node.js hosting with GitHub auto-deploy, managed SSL, daily backups and a managed MySQL database, and managed VPS plans where our team looks after the server for you.
Frequently Asked Questions
Do I need Nginx if Node can serve traffic itself?
It is strongly recommended. Nginx handles TLS, compression, static files and slow clients efficiently, and lets you run several sites on one server.
How much RAM does a small Node.js app need?
A small API or a Next.js site usually runs comfortably on 1 to 2 GB of RAM, but building a large Next.js project can need more memory than running it does, so size the server for the build too.
Should I use PM2 or systemd?
Both work. PM2 is quick to set up and shows logs and status clearly, while systemd is built in and needs no extra package.
Your feedback helps us grow and helps others discover our services.
Related Articles
Let's Build Your Next Project
From hosting to full-stack development — webzworld has the expertise to scale your business.


