Requirements
What nextship needs, why it needs each thing, and which of them are enforced.
What you need#
| Requirement | Why | Enforced |
|---|---|---|
| Node.js 22 or newer | Runs the CLI | Declared in engines, so your package manager warns or refuses |
| Docker 23 or newer | Every build runs inside BuildKit, so nothing compiles on your machine | Yes. nextship queries the daemon and refuses older versions by name |
| Next.js 16.2 or newer | The Deployment Adapter API became stable in 16.2 | Yes, with the reason in the error |
| A DigitalOcean API token | Only for deploy, rollback, logs, env and domain | Yes, the error names the variable |
| Or your own server | An OpenSSH client, and an Ubuntu 22.04, 24.04 or Debian 12 server you can reach as root or a sudo user. New in 1.1.0; see Your own server | Yes, server add refuses anything else by name |
Docker must be running. The local commands need nothing else.
Why Docker is not optional#
Building inside a container is what makes the result predictable. Your dependencies are
installed for the platform the app will run on rather than the platform you develop on, so
sharp and every other native module are correct without you having to think about it.
It also means an Apple Silicon machine cannot produce an image your cloud target refuses
to run: the build always targets linux/amd64. That has been verified from a MacBook Pro
with an M3 Max, where nextship 0.4.4 from npm built a Next.js app whose image carried the
Linux build of sharp and served on App Platform.
Why the floor is Next.js 16.2#
The Deployment Adapter API stabilised in 16.2. nextship injects an adapter through
NEXT_ADAPTER_PATH and reads the manifest that adapter writes, so an older Next.js has
nothing to inject into.
The check reads the installed version rather than the range declared in
package.json, because a declared range is a wish and the installed version is a fact.
The token#
Set it before any command that touches your account:
export DIGITALOCEAN_TOKEN=dop_v1_...It needs read and write scope on apps and on the container registry.
nextship never writes it into your project and never logs it. It reaches docker push
through a temporary config directory with 0600 permissions rather than a command line
argument, where any other local process could have read it.

