Skip to content

Technology stack

Each product page repeats the relevant part of this table in context. This page is the single place to see all of it at once.

ComponentTechnologyNotes
ConsoleNext.js 15, React 19, TypeScriptServer-rendered. No client state store; the API is the state.
APIHono on Node.js, TypeScriptPlain functions and explicit SQL. No ORM magic — queries read like SQL because reviewers must be able to see exactly what is sent.
DatabasePostgreSQLIntent, allocations, job queue, audit trail. Schema evolves by forward-only numbered SQL migrations.
Query layerDrizzleUsed as a typed query builder, not as an object mapper. Raw SQL where it is clearer.
API contractOpenAPI 3Hand-written specification; TypeScript client types are generated from it.
Assistant interfaceModel Context Protocol server, TypeScriptCalls the public HTTP API only.
Console accessnoVNC (VNC) and xterm.js (serial)Relayed through the panel; the hypervisor is never exposed.

The API and the console are stateless and can be replicated. The database is the only stateful component, and the job queue lives inside it.

ComponentTechnologyNotes
Executor / agentGo, single static binaryStandard library where possible. Claims jobs, calls Proxmox, reports back. Self-updating with checksum verification and rollback.
HypervisorProxmox VEReached only over its REST API. No SSH, no qm, no writing under /etc/pve.
NetworkingProxmox SDN — VLAN or EVPN/VXLAN zonesChosen per region. EVPN gives each private network its own VRF.
StorageWhatever Proxmox offers — ZFS local with replication, or Cephzone9 places disks; it does not manage the storage backend.
EdgeFortiGate (adapter-based; others can be added)Public block routing and policy. Programmed through the vendor API by the agent.

All appliance images are built from Ubuntu 24.04 LTS, hardened the same way: no SSH daemon, no login shell, no user accounts, snapd removed. See Appliances and the pull model.

ApplianceSoftwareWhat it does
Load balancerHAProxy + zone9-lb (Go)TCP and HTTPS front ends, health checks, live counters. Configuration is rendered by the daemon from panel intent and reloaded without dropping connections.
Gatewayiptables NAT + Tailscale (optional) + zone9-gateway bootstrapSource-NATs selected subnets out through your public address; optionally joins a Zero Trust network for private access.
Object storageGarage + zone9-s3 (Go)S3-compatible storage. The daemon owns the node’s configuration, cluster layout, buckets and access keys.
ComponentTechnology
Node operating systemTalos Linux — immutable, API-driven, no shell and no SSH
DistributionUpstream Kubernetes, version tied to the Talos release
Machine configuration deliveryTalos machine configuration, delivered as a cidata ISO attached to the VM
In-browser accessA kubectl pod inside your cluster, streamed to the panel console

Talos was chosen for the same reason appliances are locked: a node with no shell has no configuration drift and nothing to log into. A cluster does not talk to the zone9 API; if the panel disappears, the cluster does not notice.

FunctionTechnologyNotes
Certificate issuanceACME (Let’s Encrypt) with the DNS-01 challengeThe ACME client runs inside the API process as a locked scheduled scan. There is no separate certificate daemon.
DNS hostingCloudflare, through its APIUsed both for user records and for the ACME challenge records.
Domain registrationNameSilo, through an adapterOther registrars can be added behind the same interface.

DNS-01 was chosen over HTTP-01 deliberately: it works for load balancers with no public address at all, it is the only way to obtain wildcard certificates, it leaves port 80 free for your own use, and — because TXT records are never proxied — it keeps working when a user turns on Cloudflare’s proxy to hide their origin address.

WhatHow
Control planeContainer images; production runs on Kubernetes, but nothing requires it
Database schemaForward-only numbered SQL files, applied by a job before the API rolls out
Region agentA published release; the agent updates itself from it
Appliance binariesThe same release; each appliance fetches the binary it needs
Machine imagesBuilt once per region from a documented script, stored as Proxmox templates

Things a reader might expect to find, and why they are not here.

  • No service mesh, no operator framework, no CRDs. The control plane is a web application talking to a database.
  • No message broker. The job queue is a Postgres table, so a job and the intent that produced it commit together.
  • No shared code between TypeScript and Go. They communicate through the OpenAPI contract and database tables. Sharing code would let business logic drift into whichever language happened to be convenient.
  • No configuration management inside the product. Hypervisor nodes, switches and the edge router are provisioned once, out of band. A control plane that reconfigures the network is one whose bug takes the datacentre with it.