Skip to content
Back to the blog

Host a Next.js app on a VPS with Node.js, systemd and Nginx

Tell static output from SSR, then run a Next.js Node server on a VPS behind Nginx with systemd and private environment variables.

  • Next.js
  • VPS
  • Node.js
  • SSR

A Next.js site does not always need a server in production. If it can export HTML and static assets, serve those files as a website. If it relies on request-time rendering, cookies, Server Actions or server routes, it needs a compatible runtime. Next.js documents Node.js, Docker and static export as different deployment options with different feature support.

This guide covers a self-managed Node.js server on a VPS. It is not a one-click Next.js installer: you prepare the build, process, proxy, updates and backups.

Decide whether the app needs a runtime

Your project… Needs Hostbrid route to check
Can generate every page as HTML and does not use server-only features Static export Next.js export guide, Sites or Projects
Reads cookies or request headers, runs Server Actions or needs a persistent Node process Node.js server A paid Projects Docker service if its limits fit, or a VPS you operate

Next.js describes static output as limited compared with a Node.js server or Docker in its deployment guide. That is framework capability, not automatic Hostbrid compatibility. Check the paid-service quota and Docker-image workflow in current Projects pricing. If you need root access and control of the operating system, compare the VPS plans.

Check the app before deploying

Inspect package.json, the lockfile and the actual scripts. A typical production setup has scripts like these:

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  }
}

Install with the package manager that created the lockfile (npm ci, pnpm install --frozen-lockfile or the project’s equivalent), build, and start the production app. The Next.js CLI accepts a hostname and port; for a local test, bind only to 127.0.0.1:

npm ci
npm run build
npm run start -- --hostname 127.0.0.1 --port 3000

The current Next.js installation guide lists Node.js 20.9 as its minimum. Check the requirements for your exact project version and install a compatible runtime. Test a data-backed route, a missing route, next/image, forms, authentication and API calls. A successful build does not prove those external services work in production.

Keep the process running with systemd

On the VPS, create a Linux user without admin privileges and put the repository in its own directory, such as /srv/nextjs/app. Build from the lockfile and retain the production artefacts and dependencies required by next start. Keep secrets outside Git. Variables prefixed with NEXT_PUBLIC_ are included in browser JavaScript during the build; do not put private keys there.

A systemd unit can keep the app running and restart it after an unexpected exit:

[Unit]
Description=Next.js application
After=network-online.target
Wants=network-online.target

[Service]
User=nextapp
Group=nextapp
WorkingDirectory=/srv/nextjs/app
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=HOSTNAME=127.0.0.1
EnvironmentFile=/etc/nextjs-app.env
ExecStart=/usr/bin/npm run start -- --hostname 127.0.0.1 --port 3000
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Change the absolute npm path to match the installed Node.js runtime, and restrict /etc/nextjs-app.env to administrators. If the app uses uploads, a database, scheduled jobs or other storage, configure and back them up separately; .next is not a backup of application data.

Put Nginx in front and verify the domain

The official Next.js self-hosting guide recommends a reverse proxy instead of exposing the app server directly. Configure Nginx to forward the hostname to 127.0.0.1:3000, preserve Host and X-Forwarded-* headers, and manage HTTPS with your server’s certificate setup. Do not expose port 3000 to the Internet; expose the proxy and restricted SSH access only.

This minimal HTTP proxy is a starting point; replace the hostnames and add your system’s HTTPS configuration:

server {
    listen 80;
    server_name example.com www.example.com;

    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;
    }
}

From outside the VPS, test the home page, a dynamic route, an invalid request, static assets, logs and a service restart. Next.js keeps part of its cache on disk. One instance can use persistent local disk, but decide how to back up or rebuild that data. Multiple instances need coordinated cache and server configuration.

If your Next.js project only emits static files, do not take on server administration it does not need. If it needs SSR and you want to manage Node, Nginx and the operating system, start with the VPS catalogue. If you prefer to run a container as a service and the plan has enough resources, review Projects and its current limits. For a non-Next app, see the general Node.js hosting guide.

Official sources: Next.js deployment, self-hosting, installation requirements and CLI options.

Manage your sites, servers and email.

Forgot your password?

Free, and it takes a minute.

At least 8 characters. Not all digits, not a common one.

We'll email you to confirm the account.