How to Deploy Next.js to a VPS Without Docker

How to Deploy Next.js to a VPS Without Docker

Tako-kun ·

The two paths most Next.js deploy tutorials show: push to Vercel, or write a Dockerfile and ship the image somewhere. The first is the easiest thing in the world — until you want to actually own the box. The second works, but you’ve signed up for Dockerfiles, multi-stage builds, image registries, and a docker-compose.yml to run a process that fundamentally just needs Node and a port.

There’s a third path. A $5 VPS, a domain, and Tako. No container in sight.

What you need

Five things. None of them include Docker.

ThingWhere it comes from
A VPSHetzner CX22 (~$6/mo), DigitalOcean, Vultr — anything Linux
A domainWherever; point an A record at the VPS IP
tako-server on the boxOne curl command
The tako CLI on your laptopOne curl command
A Next.js appnpx create-next-app@latest my-app

Step 1 — Install the CLI and tako-server

On your laptop:

curl -fsSL https://tako.sh/install.sh | sh

SSH into the VPS and run the server installer:

sudo sh -c "$(curl -fsSL https://tako.sh/install-server.sh)"

That’s the entire server-side setup. The installer drops a single Rust binary, registers a systemd unit, creates a non-root tako user, and grants it the capability to bind ports 80 and 443. Pingora proxy, ACME, process supervision, and the encrypted secrets store all live inside that one binary. The deployment docs cover the details, but defaults work — skip them on the first pass.

Step 2 — Wire up Next.js

There is exactly one line of Next-specific config. In your next.config.ts:

import { withTako } from "tako.sh/nextjs";

export default withTako({});

withTako() switches Next.js to standalone output, installs the Tako adapter, and lets next dev accept Tako’s local HTTPS hostnames (*.test). On build it emits .next/tako-entry.mjs — the small file Tako launches in production. The framework guide has the full breakdown.

Step 3 — tako init

In the project directory:

tako init

Init reads your package.json, sees next, and offers the nextjs preset. Accept the defaults and you’ll get a tako.toml like this:

name = "my-app"
runtime = "node"
runtime_version = "22.x"
preset = "nextjs"

[envs.production]
route = "my-app.example.com"
servers = ["prod"]

Init also runs npm add tako.sh (or bun add, depending on your package manager) to drop the SDK in, and tunes .gitignore so .tako/* is ignored — except .tako/secrets.json, which stays tracked. The nextjs preset bakes in main = ".next/tako-entry.mjs" so you don’t write that line yourself.

Change route to a domain you actually own, then register the server once:

tako servers add prod.example.com --name prod

Step 4 — tako deploy

tako deploy

Confirm the production prompt and watch the task tree:

Connecting     ✓
Building       ✓
Deploying to prod
  Uploading    ✓
  Preparing    ✓
  Starting     ✓

  https://my-app.example.com/

Open the URL. Your Next.js app is live, on a real Let’s Encrypt cert, with zero-downtime rolling updates on every subsequent tako deploy.

What just happened

Diagram

tako deploy ran next build locally, packaged the result (excluding .git, .tako, .env*, and node_modules) into a .tar.zst artifact, and SFTP’d it to the VPS. tako-server unpacked it under /opt/tako/apps/my-app/production/, ran a production install, and started the Next.js standalone server as a regular Node process. Pingora terminates TLS on :443 and routes to it.

What you didn’t write

  • A Dockerfile
  • A docker-compose.yml
  • An nginx.conf and a certbot cron
  • A .env file copied into a container at build time
  • A GitHub Actions workflow that builds, tags, and pushes an image

That’s the difference. Next.js doesn’t need to be containerized to run; it’s a Node program that listens on a port. Tako treats it like one. The proxy, the TLS, the secrets store, and the rolling-restart coordinator all live in a single Rust binary on the box. Your Next.js app is a process, not a container image.

When you’re ready for more — secrets that don’t sit in env files, multiple environments on the same box, or durable workflows from inside your routes — it’s all the same tako deploy. Start with the CLI reference or skim how Tako works.