Skip to content

3. Deploy the control plane

The control plane is a web application: a console, an API, and PostgreSQL. Production runs it on Kubernetes; nothing requires that.

ComponentWhat it isScaling
apiThe HTTP APIStateless; replicable
webThe consoleStateless; replicable
migrateA job that applies schema migrationsRuns once per deploy, before the API rolls out
PostgreSQLIntent, allocations, job queue, audit trailThe only stateful component

Migrations run before the API rolls out. In the other order, new API pods spend a few seconds querying a schema that does not have their columns yet and return errors to real users.

The supplied deployment script enforces this: build and push, apply infrastructure manifests, run the migration job to completion, then roll out the API and console.

VariableRequiredPurpose
ZONE9_DATABASE_URLyesPostgreSQL connection string
ZONE9_JWT_SECRETyesSigns session tokens
ZONE9_AGENT_LATESTyesThe agent version the panel expects; drives the “update available” badge
ZONE9_DELETE_BUFFER_SECONDSyesThe two-phase deletion window. 600 is a sensible default
ZONE9_CLOUDFLARE_API_TOKENoptionalDNS hosting and ACME challenges
ZONE9_CLOUDFLARE_ACCOUNT_IDoptionalWhen the token can reach several accounts
ZONE9_NAMESILO_KEYoptionalDomain registration
ZONE9_ACME_EMAILoptionalContact address for the ACME account; expiry notices only
ZONE9_ACME_DIRECTORYoptionalDefaults to Let’s Encrypt production. Point it at staging while testing
ZONE9_CONSOLE_WS_URLyesWhere browsers connect for console sessions
ZONE9_PLATFORM_ADMINSfirst runBootstrap platform operator identities

Provider credentials are optional on purpose: without a DNS token the panel starts normally and only the DNS features are unavailable, with the reason shown on screen. A missing optional integration must not take the whole panel down.

PathService
/console
/api/v1API
/console/wsconsole WebSocket relay

Terminate TLS at your ingress. The console relay needs WebSocket upgrades to pass through.

Any PostgreSQL will do. Production uses an operator-managed cluster, but a managed database service or a single well-backed-up instance is fine.

Back it up. It holds intent, allocations and the audit trail. Losing it does not stop your virtual machines — they keep running, because nothing depends on the panel — but you lose the record of who owns what, and rebuilding that from tags is work you do not want to do under pressure.

Migrations are numbered SQL files applied in order, tracked in a table, and forward only: an applied file is never edited; a new numbered file is added instead. Each migration and its bookkeeping row commit in one transaction, so a half-applied migration is not a state the database can reach.

Terminal window
kubectl -n zone9 get pods
kubectl -n zone9 logs job/migrate --tail=20
curl -sI https://<your-host> | head -1

Then sign in. With ZONE9_PLATFORM_ADMINS set, your identity has platform operator rights and can create organisations and address pools.

Same script. Image tags include the timestamp and commit, so you can see what is running and roll back to a previous tag without rebuilding.

Order for a release that changes both the panel and the agent: publish the agent release first, let regions pick it up, then deploy the panel. An old agent may not understand a new field; the reverse is designed to be safe.