Deploying Next.js on a VPS: A Practical Step-by-Step Guide Without Vercel Lock-In

I often see people saying that Next.js “locks you into Vercel.” That’s simply not true. You can deploy a Next.js app to your own VPS in just a few minutes.
However, before going down the VPS route, there are a few important things to understand.
Vercel provides a lot of built-in infrastructure out of the box — things like image optimization, edge functions, and automatic scaling. When you deploy to your own VPS, you’re not losing Next.js features — but you are taking responsibility for the infrastructure that Vercel normally manages for you.
Let’s quickly look at what that means.
What You Don’t Get Automatically on a VPS
When deploying on Vercel, many services are handled for you in exchange for cost. On a VPS, you need to set these up yourself:
❌ No Automatic Image Optimization CDN Layer
Next.js image optimization still works, but you don’t get a globally distributed CDN by default.
❌ No Built-in Edge Functions Runtime
Edge Functions won’t automatically run at the edge. You’ll need a separate edge provider if you want that behavior.
❌ No Automatic ISR Cache Persistence
Incremental Static Regeneration cache won’t persist across multiple instances unless you configure shared storage.
❌ No Automatic Serverless Scaling
Your VPS won’t scale automatically with traffic. You are responsible for process management and scaling.
That’s the trade-off: more control, more responsibility.
Now, let’s deploy.
Server Assumptions
In this guide, I’ll assume:
- You have a VPS with a Debian-based OS (Ubuntu works fine).
- Node.js is already installed.
- You have a domain pointing to your server.
If you’re using a different OS, just adapt the commands accordingly.
1. SSH into Your Server
ssh [email protected]2. Update and Upgrade Your Server
Always start by updating your system:
apt update -y && apt upgrade -yYour server is now ready.
3. Clone Your Project
Next, pull your project into the server. In this example, I’m using GitHub and deploying into /var/www/example-project.
mkdir -p /var/www
git clone https://github.com/madatbay/example-project.git /var/www/example-projectNow your code lives on the server.
4. Install PM2 (Process Manager)
Since Next.js runs as a Node.js server, we need a way to keep it running in the background — even if the terminal closes or the server restarts.
What is PM2?
PM2 is a production process manager for Node.js applications. It keeps your app alive and automatically restarts it if it crashes.
Install PM2 globally:
npm install pm2@latest -g5. Install Dependencies and Build
Move into your project directory:
cd /var/www/example-projectInstall dependencies:
npm installBuild your Next.js app:
npm run build6. Start Next.js with PM2
Now we’ll start the app using PM2.
Basic format:
pm2 start npm --name <app_name> -- start --port <port>In our example:
pm2 start npm --name next-app -- start --port 3000Your Next.js app is now running on port 3000 🎉
7. Configure NGINX as Reverse Proxy
We’ll use NGINX to:
- Connect your domain
- Forward traffic to port 3000
- Prepare for SSL
Install NGINX
apt install nginx -yCreate NGINX Config
Navigate to:
cd /etc/nginx/sites-available/
vim app.confAdd this configuration:
server {
server_name <app_domain>;
client_max_body_size 20M;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache_bypass $http_upgrade;
proxy_buffering off;
}
}This tells NGINX to forward all traffic from your domain to your Next.js app running on port 3000.
Enable the Configuration
Create a symlink:
ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/Validate config:
nginx -tRestart NGINX:
service nginx restartYour app should now be accessible via your domain (without SSL yet).
8. Enable SSL with Certbot 🔐
Let’s secure the site with HTTPS.
Install Certbot
apt install certbot python3-certbot-nginx -yRun Certbot
certbot --nginxFollow the prompts to generate and install your SSL certificate.
Finally, restart NGINX:
service nginx restartNow your app is live with HTTPS.
Final Thoughts
Yes, deploying to a VPS requires a few more steps compared to Vercel.
But you gain:
- Full infrastructure control
- Lower cost at scale
- No vendor lock-in
And once you’ve done it once, it becomes a simple repeatable process.
That’s it — your Next.js app is now running on your own VPS 🚀