Skip to Content
CLI Referencenkapp migrate

nkapp migrate

Migrate an entire environment from the deploy target it currently runs on to a different deploy target — moving services, stateful data, TLS certificates, and DNS — with a readiness‑gated cutover and the source kept as a rollback fallback.

nkapp migrate -e <env> --to <deployTarget> [options]

migrate is the one command that performs a complete host‑to‑host move (e.g. kama-vps → nk-prod-vps). It re‑points the environment, provisions the destination, copies the data, carries the gateway’s TLS certs, flips DNS, and verifies — all without touching the source until you explicitly decommission it.

Options

FlagTypeDefaultDescription
-e, --env <env>stringRequired. Environment to migrate.
--to <deployTarget>stringRequired. Destination deploy target — must be a key under deploy: in nanokit.yml.
--from <name>stringcurrentSource deploy target. Defaults to the environment’s currently‑resolved target.
--dry-runbooleanfalsePrint the plan and change nothing — fully side‑effect‑free.
-y, --yesbooleanfalseSkip confirmation prompts (CI).
--no-databooleanProvision + re‑point only; skip stateful data movement.
--data-onlybooleanfalseMove only the stateful data (assumes the destination is already provisioned).
--no-certsbooleanSkip carrying the gateway TLS certificates to the destination.
--no-dnsbooleanSkip the DNS cutover (no live traffic move).
--forcebooleanfalseOverwrite non‑empty destination volumes during the data copy (clean‑replace). Required on any re‑run/cutover where the destination already holds data.
--decommissionbooleanfalseTear down the source after a verified cutover. Off by default — the source is kept as a rollback fallback.
--services <list>stringallLimit volume migration to specific services (comma‑separated).
--keep-sourcebooleantrueKeep the source after cutover (the default; --decommission is the opt‑in to remove it).

What it does

The migration is a deterministic, idempotent pipeline. Each phase is re‑runnable.

1. Resolve & validate

Resolves the from (current) and to targets, validates that --to exists under deploy:, and rejects from === to. Validates SSH reachability.

2. Plan & confirm

Renders a structured plan — Infrastructure · Data · DNS · TLS Certs · Config · Decommission — and asks for confirmation (unless -y). --dry-run stops here.

3. Re‑point config

Flips environments.<env>.deploy in nanokit.yml to the destination target (preserving the string‑shorthand vs object form). This is the authoritative binding that deploy/up use thereafter.

4. Provision destination

Runs host setup + deploy against the destination to bootstrap the host and stand up the services and gateway. DNS sync is suppressed during this step — only the dedicated cutover phase changes DNS.

5. Migrate data

Copies every stateful asset byte‑for‑byte (clean‑replace) from source → destination: all environment databases and all service named volumes. The source is never modified.

6. Restart destination services

Restarts the destination services that received migrated data so they reload with the real config/data (a freshly‑provisioned stateful service boots empty before the data lands).

7. Carry TLS certificates

Copies the gateway’s already‑issued public certificates for the environment’s grey (non‑proxied) hosts from the source gateway to the destination’s — so those hosts serve valid HTTPS immediately at cutover, with no ACME race.

8. Readiness gate

Confirms the destination is actually serving the expected service containers. DNS is never changed unless this passes — production traffic is never pointed at an unprepared host.

9. DNS cutover

Re‑points the environment’s hostnames to the destination IP via the configured DNS provider (e.g. Cloudflare), preserving each service’s proxied flag. Skipped with --no-dns.

10. Verify

Confirms the destination passed the deploy health gate.

11. Decommission (opt‑in)

With --decommission, tears down the source last, after verify. Default keeps the source as a rollback fallback.


What gets migrated (scoping)

AssetScope
ServicesThe environment’s effective services (its services: block — same scoping deploy uses).
DatabasesAll databases the environment provisions (parity with the reconciler), copied as their data volumes.
VolumesEvery named volume declared by an in‑scope service. Bind mounts (host paths) are skipped.
TLS certificatesPublic certs for the environment’s grey (non‑proxied) hosts. Proxied hosts use tls internal behind the CDN and need no carry.
DNSAll project‑ and service‑level hosts of the environment, re‑pointed to the destination IP.

Cutover & TLS

Two kinds of host behave differently at the DNS flip:

  • Proxied hosts (e.g. nanokit.dev behind Cloudflare) serve immediately — the CDN terminates TLS and accepts the origin’s tls internal certificate.
  • Grey / non‑proxied hosts (e.g. mail.nanokit.dev, storage.nanokit.dev) are hit directly and need a valid public certificate on the destination. Because HTTP‑01/TLS‑ALPN‑01 ACME validates against the live A record, a certificate cannot be freshly issued during the flip (the record still resolves to the source). migrate solves this by carrying the existing certificates from the source gateway to the destination (phase 7), so grey hosts serve valid HTTPS the moment DNS changes.

For a live environment, run it staged so you can verify before moving traffic.

# 1. Preview — changes nothing nkapp migrate -e production --to nk-prod-vps --dry-run # 2. Provision + data + certs, WITHOUT touching DNS (traffic stays on the source) nkapp migrate -e production --to nk-prod-vps --no-dns # 3. Verify the destination directly (bypass DNS via the Host header) curl -sk --resolve nanokit.dev:443:<dest-ip> https://nanokit.dev/ -o /dev/null -w '%{http_code}\n' # 4. Cutover — re-sync the latest data, carry certs, then flip DNS nkapp migrate -e production --to nk-prod-vps --force -y # 5. Once fully confident, decommission the source nkapp migrate -e production --to nk-prod-vps --no-data --no-dns --decommission

Or, in a single maintenance window:

nkapp migrate -e production --to nk-prod-vps --force -y # re-point → provision → data → certs → DNS → verify

Safety & rollback

  • Plan‑first + confirm. --dry-run is fully side‑effect‑free; a real run prints the plan and asks before acting.
  • Source kept by default. The cutover is reversible — flip the binding back and re‑point DNS (the source still holds its data) until you run --decommission.
  • Readiness gate. DNS is never changed unless the destination is confirmed serving — production traffic is never pointed at an unprepared host.
  • Source is never modified by the data/cert copy (read‑only on the source; the destination is the only thing written).

Limitations

  • SSH / Docker targets. Data movement, cert carry, and DNS cutover apply to type: ssh (Docker‑over‑SSH) targets. Cloud targets (type: cloud) are guarded — their managed stores/DNS need provider‑native snapshot/restore, not yet automated.
  • Stateful‑service downtime window. Copying a database or volume briefly quiesces the owning source container for a consistent copy — a short interruption on the source during the data phase.
  • Complex mail servers. A self‑hosted mail server (Stalwart) carries both a config volume and a database; ensure the data phase + service restart complete before cutting over, and verify SMTP/IMAP on the destination, not just the web UI.

See also

  • nkapp deploy — the underlying VPS deploy that migrate drives to provision the destination.
  • nkapp host — VPS bootstrap and certificate trust.
  • nkapp destroy — teardown used by --decommission.