Skip to content
Zenith / Docs
Enterprise Gateway
OpenAI compatible

Docker / Swarm

Run the Gateway with Docker Compose, or use Swarm when your infrastructure requires it.

Enter the hostname your application uses to reach Zenith Gateway. Every Enterprise example below updates instantly.

Hostname only, or paste a full URL. Saved in this browser.
Image ghcr.io/vestavision/zenith-gateway:vYYYY.MM.DD.x
Assets https://zenithgw.com/install/
Stack compose.yml
Replicas 1 gateway only

Choose a path

  • Compose — single host, simplest ops. Default for labs and many production gateways.
  • Swarm — multi-node cluster with overlay networking. Still one gateway replica; stateful volumes stay on one data node.
  • install.sh — downloads stack files, generates gateway.env, and deploys either mode for you. See /docs/enterprise/install.

This page covers the Gateway-only stack: Gateway, Postgres, and optional NATS. Download the Compose files and environment example from https://zenithgw.com/install/.

Stack shape

ServiceRole
zenithOpenAI-compatible /v1, local /admin, activation client
postgresGateway state: licenses, pools, encrypted provider keys
nats (optional)Telemetry / cluster rate coordination via JetStream
VolumeMountWhy it matters
gateway-data/var/lib/zenithmaster.key — must survive recreate
pg-data/var/lib/postgresql/dataGateway database
nats-data/data/jetstreamJetStream when NATS is enabled

Production default publishes only the gateway host port (9090). Postgres and NATS stay on the Compose/Swarm network unless you intentionally publish them.

Prerequisites

  • Docker Engine with the Compose plugin (Compose path) or an initialized Swarm (Swarm path).
  • Pinned CalVer image from ghcr.io/vestavision/zenith-gateway — avoid floating :latest in production.
  • gateway.env derived from https://zenithgw.com/install/gateway.env.example with unique secrets.
  • HTTPS issuer URL for production activation (ZENITH_ISSUER_URL).

gateway.env feeds ${VAR} interpolation in the Compose/Swarm YAML and supplies values listed under the zenith service environment. A key present only in the file but omitted from that environment list never reaches the process. Required: ZENITH_ADMIN_SESSION_SECRET, ZENITH_BOOTSTRAP_API_KEY, POSTGRES_PASSWORD / ZENITH_POSTGRES_DSN. Brand, SMTP, public base URL, and similar product settings are configured in /admin/organization/settings after activation — not via env.

Compose

compose-up.sh
mkdir -p ~/zenith-gateway && cd ~/zenith-gateway

curl -fsSL https://zenithgw.com/install/compose.yml -o compose.yml
curl -fsSL https://zenithgw.com/install/gateway.env.example -o gateway.env.example

cp gateway.env.example gateway.env

docker compose --env-file gateway.env \
  -f compose.yml \
  --profile nats up -d
compose-down.sh
docker compose --env-file gateway.env \
  -f compose.yml --profile nats down

Swarm

swarm-deploy.sh
mkdir -p ~/zenith-gateway && cd ~/zenith-gateway

curl -fsSL https://zenithgw.com/install/compose.swarm.yml \
  -o compose.swarm.yml
curl -fsSL https://zenithgw.com/install/gateway.env.example -o gateway.env.example
cp gateway.env.example gateway.env
docker swarm init

set -a
source ./gateway.env
set +a

docker stack deploy -c compose.swarm.yml zenith-gateway

docker stack services zenith-gateway
docker service logs zenith-gateway_zenith

Prefer curl -fsSL https://zenithgw.com/install.sh | bash -s -- --yes --mode swarm --swarm-data-node YOUR_NODE when you want env generation and verify handled for you. Add --publish-deps only when you need host Postgres/NATS ports.

swarm-rm.sh
# Remove stack (keeps volumes unless you purge them separately)
docker stack rm zenith-gateway

Hard rules

  • Secrets are deploy-time env interpolation from the shell (or install.sh sourcing gateway.env). The published Swarm stack does not create Docker configs/secrets — wire Swarm secrets yourself if policy requires it.
  • Changing POSTGRES_PASSWORD after first deploy requires deleting the Postgres volume before redeploy — the volume keeps the original DB password.
  • Demo/lab wipe: delete gateway-data and pg-data together (and optionally nats-data). Wiping only one side leaves an unreadable or orphaned state.

Upgrade

  • Pin ZENITH_GATEWAY_IMAGE (or install.sh --tag) to the new CalVer release.
  • Compose: pull and up -d with the same gateway.env and volumes.
  • Swarm: export gateway.env and docker stack deploy again; leave ZENITH_SWARM_DATA_NODE_HOSTNAME unchanged.
  • Version or instance ID changes may require re-activation — confirm /readyz after upgrade.

Backup & recovery

Always back up Postgres and gateway-data together. Losing master.key while keeping the database (or the reverse) breaks encrypted provider/OIDC secrets. On mismatch the process stays up in recovery at /admin/recovery/master-key (/readyz 503, no crash-loop): restore the matching volume, or owner-confirm RESET ENCRYPTED SECRETS to wipe ciphertext and rebind.

Terminate TLS on an edge proxy in front of the gateway. The container listens on plain HTTP inside the network; set the public origin under Settings → Runtime after activation.

Verify

  • /healthz → 200 while the process is up.
  • /admin/activate → upload .lic → activate against the issuer.
  • Empty org continues to /setup for owner creation; then /readyz → 200.
  • Configure a provider and pool alias; call the OpenAI SDK at /v1 (see Gateway OpenAI SDK).