Why Self-Host Next.js on a VPS?
Next.js is often associated with a specific hosting platform, but its standalone Node.js server runs perfectly on any VPS. Self-hosting becomes worthwhile as soon as you make intensive use of SSR, ISR (incremental static regeneration), or API routes: these features consume billed invocations on managed platforms, whereas they are free and unlimited on your server. You control the ISR cache on disk, the bandwidth of optimized images, and the function execution time, with no 10-second limit. For an agency hosting several client sites, a VPS pools the costs and simplifies billing.
Concrete Benefits of a Self-Hosted Next.js
- SSR and API routes with no invocation quota or per-function billing.
- Persistent ISR cache on disk, no revalidation lost between deployments.
- Included bandwidth, ideal for image- and video-rich sites.
- Several Next.js projects on a single VPS, pooled under Nginx.
next/imageimage optimization served locally with no per-transformation extra cost.- Build and deployment controlled via Git, CI/CD, or a simple
git pulland rebuild.
Hardware and Software Prerequisites
The Next.js build is memory-hungry: plan for at least 2 GB of RAM (4 GB for a large project with many pages), otherwise the build may fail for lack of memory. On the runtime side, 1 to 2 vCPU are enough to serve SSR. Install Node.js 18 or 20 LTS, either natively with nvm or via a node:20-alpine Docker image. Use PM2 to supervise the Node process, or Docker for isolation. A domain pointed to the VPS is required for SSL. Enable output: 'standalone' in next.config.js for a lightweight deployment.
Deploy Next.js Step by Step
Prepare the Server
Over SSH, install Node.js 20 LTS and PM2 (npm install -g pm2), or Docker. Clone the repository and create .env.production with your variables (NEXT_PUBLIC_* for the client, server secrets for the API routes).
Build the Application
Run npm ci, then npm run build. With output: 'standalone', Next.js generates a self-contained .next/standalone folder containing only the necessary dependencies, which greatly lightens the image.
Start the Node Server
Start the server with pm2 start node --name nextjs -- .next/standalone/server.js on port 3000, or via a Docker container. Configure pm2 startup and pm2 save for automatic restart on VPS reboot.
Configure Nginx as the Front End
Create a server block that does proxy_pass http://localhost:3000, forwards the Host and X-Forwarded-For headers, and serves /_next/static/ directly from disk to relieve Node. Enable gzip compression.
Install the SSL Certificate
Obtain a Let's Encrypt certificate via Certbot for yourdomain.com, force the HTTPS redirect, and configure automatic renewal. Verify that the X-Forwarded-Proto headers are properly forwarded for SSR.
Set Up Deployments
Automate the git pull && npm ci && npm run build && pm2 reload nextjs cycle via a script or a Git webhook. PM2's reload ensures a zero-downtime restart between two versions.
If you use ISR, mount a persistent volume for the .next/cache folder so that revalidated pages survive redeployments. Without this, each rebuild starts from an empty cache and causes a spike of on-the-fly generation. For several Node instances behind a load balancer, externalize this cache to shared storage or Redis with a custom cache handler.