Self-host Next.js on your own server for full control and predictable cost. Learn to build, run with PM2, reverse-proxy with Nginx, and add HTTPS.
- Topic
- Tutorials
- Read time
- 3 min read
- Covers
- nextjs, deployment, pm2
- Last updated
- July 23, 2026
You don't need a managed platform to run Next.js. Self-hosting on a VPS gives you full control, no per-request pricing, and no vendor lock-in. The production Next.js server runs great behind Nginx with a process manager. Here's the complete deployment.
Step 1: Prepare the server
On a fresh Ubuntu VPS, update and add a deploy user:
sudo apt update && sudo apt upgrade -y
sudo adduser deploy && sudo usermod -aG sudo deployInstall a current Node.js LTS:
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install nodejs -yStep 2: Get the code and build
Clone your repo, install dependencies, and create the production build:
git clone https://github.com/you/my-next-app.git
cd my-next-app
npm ci
npm run buildThe build compiles your app into an optimized production bundle. Set production environment variables in a .env or .env.production file — things like your database URL and API keys — before building if they're needed at build time.
Step 3: Run the production server with PM2
Next.js has its own production server started with next start (via your npm start script). Keep it alive with PM2:
sudo npm install -g pm2
pm2 start npm --name my-next-app -- start
pm2 startup systemd
pm2 saveBy default Next.js listens on port 3000. Confirm it's up:
pm2 status
curl http://localhost:3000If you need a different port, set it: pm2 start npm --name my-next-app -- start -- -p 4000.
Step 4: Reverse-proxy with Nginx
Expose the app on ports 80/443 through Nginx rather than opening 3000 to the world. Install Nginx and create /etc/nginx/sites-available/my-next-app:
server {
listen 80;
server_name example.com www.example.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-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}Enable and reload:
sudo ln -s /etc/nginx/sites-available/my-next-app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxStep 5: Add HTTPS
Point your domain's A record at the VPS, then let Certbot handle TLS:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.comStep 6: Firewall
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enableServing images and caching
Next.js image optimization and server rendering benefit from real CPU and fast disk. On a NVMe VPS the build step and on-demand rendering are noticeably quicker than on slower storage. If your site is image-heavy, give it a bit more RAM so the Node process has headroom.
Updating deploys
Your update routine:
cd my-next-app
git pull
npm ci
npm run build
pm2 restart my-next-appFor zero-downtime, PM2 restarts are near-instant, and Nginx keeps serving until the new process is ready.
Optional: run it in Docker
If you prefer containers, add a Dockerfile using Next.js standalone output and run it with docker run or Compose, still behind Nginx or Caddy. Either way the front-end proxy pattern is the same.
Why self-host Next.js
You get predictable flat-rate pricing, no cold starts, full access to the filesystem and background processes, and the freedom to run whatever database and services you like alongside the app. On a Nxeon full-root NVMe VPS, a Next.js deploy is a one-time setup followed by four-line updates — your app, your server, your rules.
Put this guide to work on Cloud VPS hosting. From $8.88 for the first term, then $12.78 a month.
Nxeon editorial · Straight-talking guides from the team that runs the servers.