How to Deploy a Next.js App on a VPS with Nginx and PM2

Deploying a Next.js application to production can feel complicated if you’ve only worked locally. But once you understand the process, it’s actually very structured.
In this guide, you’ll learn how to deploy a Next.js app on a VPS using Nginx and PM2, step by step. This setup is widely used in production because it gives you:
- Full control over your server
- Better performance compared to shared hosting
- Ability to scale and optimize
- No platform lock-in
By the end of this guide, your Next.js app will be live with:
- Nginx as a reverse proxy
- PM2 for process management
- SSL (HTTPS) enabled
- Production-ready configuration
Prerequisites
Before you start, you need:
- A VPS (Ubuntu 22.04 recommended)
- Domain name pointing to your server
- Basic knowledge of SSH
- Node.js installed (v18+ recommended)
Step 1: Connect to Your VPS
ssh user@your-server-ip
Update your system:
sudo apt update && sudo apt upgrade -y
Step 2: Install Node.js
Install Node.js:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install nodejs -y
Verify:
node -v
npm -v
Step 3: Upload Your Next.js App
You can:
- Use Git clone
- Upload via SCP
- Pull from GitHub
Example:
git clone https://github.com/yourrepo/nextjs-app.git
cd nextjs-app
Install dependencies:
npm install
Step 4: Build the App
npm run build
This creates an optimized production build.
Step 5: Install PM2
PM2 keeps your app running in background.
sudo npm install -g pm2
Start app:
pm2 start npm --name "nextjs-app" -- start
Save process:
pm2 save
pm2 startup
Step 6: Install Nginx
sudo apt install nginx -y
Start Nginx:
sudo systemctl start nginx
Step 7: Configure Nginx Reverse Proxy
Create config:
sudo nano /etc/nginx/sites-available/nextjs
Paste:
server {
listen 80;
server_name 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_cache_bypass $http_upgrade;
}
}
Enable config:
sudo ln -s /etc/nginx/sites-available/nextjs /etc/nginx/sites-enabled/
Test:
sudo nginx -t
Restart:
sudo systemctl restart nginx
Step 8: Configure Firewall
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Step 9: Add SSL with Let’s Encrypt
Install Certbot:
sudo apt install certbot python3-certbot-nginx -y
Run:
sudo certbot --nginx -d yourdomain.com
Step 10: Verify Deployment
Visit:
Your Next.js app should be live.
Performance Optimization Tips
- Enable caching in Nginx
- Use CDN (Cloudflare)
- Optimize images
- Use gzip compression
Common Errors
Port Already in Use
Fix:
lsof -i :3000
Nginx 502 Bad Gateway
Check PM2:
pm2 logs
Best Practices
- Use environment variables
- Monitor logs
- Keep dependencies updated
- Use CI/CD pipeline
FAQs
Can I deploy without PM2?
Yes, but not recommended.
Can I use Apache instead of Nginx?
Yes, but Nginx is faster.
Final Thoughts
Deploying a Next.js app on a VPS with Nginx and PM2 is one of the best ways to host modern web apps with full control and scalability
