Skip to content

Gateway Guardian On-Prem Deployment

This runbook covers the on-prem shape for Linux amd64 and arm64 deployments while keeping the developer workflow usable from macOS. It provides two paths:

  • Docker Compose demo: a single-host stack with bundled Postgres and RustFS.
  • Kubernetes/Helm: a production profile that expects external Postgres and external S3-compatible object storage.

RustFS replaces MinIO for bundled artifact storage. RustFS is S3-compatible, supports AWS Signature V4, and publishes multi-architecture Docker images. The demo pins rustfs/rustfs:1.0.0-alpha.94, the newest versioned multi-arch tag available when this profile was added.

References:

Gateway Guardian uses two persistence layers on-prem:

  • PostgreSQL: registry, audit, auth, plugin metadata, and state blobs.
  • S3-compatible object storage: immutable plugin WASM artifact bytes.

The current on-prem profile keeps state attestation blobs in Postgres. RustFS is only bundled for plugin artifacts in the Compose demo. Kubernetes deployments should use an operator-managed RustFS/S3 endpoint and an operator-managed Postgres instance.

Prerequisites:

  • Docker Engine with Compose v2 on Linux amd64 or arm64.
  • Go installed locally if you want to run the demo smoke tests from source.
  • Network access to pull third-party base/runtime images unless they are already mirrored locally.

Build the local Guardian images:

Terminal window
just --justfile deploy/onprem/justfile build

Start the stack:

Terminal window
just --justfile deploy/onprem/justfile up

up also runs the local image build and then starts services with --no-build, so the stack uses the images built from the checkout instead of official images from GHCR.

Endpoints:

  • Console and control-plane API: http://localhost:8080
  • Gateway through HAProxy: http://localhost:10000
  • RustFS S3 API: http://127.0.0.1:9000
  • RustFS console: http://127.0.0.1:9001

Run the demo artifact flow:

Terminal window
just --justfile deploy/onprem/justfile demo-artifact

That publishes an allow-all WASM plugin through the control-plane, stores the artifact in RustFS, restarts the gateway, and checks that the gateway cached the artifact after loading the active snapshot.

Run the demo agent registration flow:

Terminal window
just --justfile deploy/onprem/justfile demo-registration

That asks the control-plane to mint a short-lived provisioning token, registers a deterministic local did:key with the gateway, and checks that the control-plane can list the active agent. To run the full local smoke suite:

Terminal window
just --justfile deploy/onprem/justfile test-e2e

Stop the stack:

Terminal window
just --justfile deploy/onprem/justfile down

Remove volumes when you want a clean slate:

Terminal window
just --justfile deploy/onprem/justfile down-volumes

Use the airgap packaging flow when the target Linux VM or DPU should not clone the repository, install Go/Node/Rust, or pull from public registries. The bundle contains a no-build Compose file, .env.example, HAProxy config, Linux helper binaries, Docker image archives, a manifest, checksums, and install/test scripts.

Build an amd64 bundle:

Terminal window
just --justfile deploy/onprem/justfile package-airgap amd64 dev

Build an arm64 bundle:

Terminal window
just --justfile deploy/onprem/justfile package-airgap arm64 dev

The output is written to:

deploy/onprem/dist/guardian-onprem-dev-linux-<arch>.tar.gz

The target host install flow is:

Terminal window
tar -xzf guardian-onprem-dev-linux-amd64.tar.gz
cd guardian-onprem-dev-linux-amd64
./bin/load-images.sh
./bin/install.sh
./bin/test-e2e.sh

The target host only needs Docker Engine with Compose v2. It does not need Git, Go, Node, Rust, or registry access after receiving the tarball. For quick local layout validation without creating image archives:

Terminal window
just --justfile deploy/onprem/justfile package-airgap-layout amd64 dev

The first up creates deploy/onprem/compose/.env from .env.example. Change these values before sharing the stack:

  • POSTGRES_PASSWORD
  • GUARDIAN_DB_DSN
  • RUSTFS_ACCESS_KEY
  • RUSTFS_SECRET_KEY
  • GUARDIAN_PLUGIN_SIGNER_*
  • GUARDIAN_REGISTRATION_TOKEN_SECRET
  • GUARDIAN_AGENT_REGISTRATION_*

The demo signer in .env.example is deterministic and only suitable for local validation. Generate a fresh signer for any shared environment:

Terminal window
SIGNER_SEED=$(just --justfile llm-gateway/justfile gen-key | awk -F= '/seed_b64url/{print $2; exit}')
just --justfile llm-gateway/justfile pubkey-from-seed "$SIGNER_SEED"

Put the seed in GUARDIAN_PLUGIN_SIGNER_SEED_B64URL for the demo publisher and put the public key in GUARDIAN_PLUGIN_SIGNER_PUBLIC_KEY for the services.

The Compose file does not pin platform:. On Linux it pulls the host architecture automatically. On macOS, Docker Desktop still runs the Linux image variant for the host architecture; set DOCKER_DEFAULT_PLATFORM=linux/amd64 or DOCKER_DEFAULT_PLATFORM=linux/arm64 only when deliberately testing emulation.

The on-prem Helm profile is deploy/values-onprem.yaml. It disables the bundled Postgres and HAProxy ingress dependencies and configures both services for an external S3-compatible artifact store.

Create the required secrets:

Terminal window
kubectl create namespace guardian
kubectl -n guardian create secret generic guardian-db \
--from-literal=dsn='postgres://guardian:REPLACE@postgres.example.internal:5432/guardian_gateway?sslmode=require'
kubectl -n guardian create secret generic guardian-artifact-s3 \
--from-literal=accessKeyID='REPLACE' \
--from-literal=secretAccessKey='REPLACE'

Render or install:

Terminal window
helm dependency build deploy/charts/guardian-stack
helm upgrade --install guardian deploy/charts/guardian-stack \
--namespace guardian \
-f deploy/values-onprem.yaml \
--set llmGateway.image.tag=REPLACE_WITH_RELEASE \
--set controlPlane.image.tag=REPLACE_WITH_RELEASE \
--set guardianUI.image.tag=REPLACE_WITH_RELEASE \
--set llmGateway.plugins.artifactStorage.s3.endpoint=https://s3.example.internal \
--set controlPlane.plugins.artifactStorage.s3.endpoint=https://s3.example.internal

Replace the placeholder hosts, TLS secret names, image tags, S3 endpoint, and trusted plugin signer in deploy/values-onprem.yaml before applying it.

For airgapped sites, mirror these images into the customer registry:

  • ghcr.io/eqtylab/guardian-llm-gateway for Helm deployments, or build guardian-llm-gateway:local from this checkout for Compose demos
  • ghcr.io/eqtylab/guardian-control-plane for Helm deployments, or build guardian-control-plane:local from this checkout for Compose demos
  • ghcr.io/eqtylab/guardian-console for Helm deployments, or build guardian-console:local from this checkout for Compose demos
  • postgres:16 for the Helm init container and Compose demo
  • rustfs/rustfs:1.0.0-alpha.94 for the Compose demo
  • amazon/aws-cli:latest for the Compose bucket initializer
  • haproxy:3.0-alpine for the Compose demo
  • alpine:3.20 for Compose volume permission helpers

Then set the image repositories in deploy/values-onprem.yaml to the mirrored registry. For Compose demos, either keep the default local image names and build on the target host, or set deploy/onprem/compose/.env to preloaded/mirrored image names. Helm dependencies should be built and vendored before transfer when the target environment cannot reach public chart repositories.

  • Postgres must be migrated by the gateway before the control-plane is useful. In Compose, both services share one Postgres instance and the gateway applies migrations on startup.
  • RustFS is bound to 127.0.0.1 in Compose so the S3 API and console stay local to the demo host.
  • The Helm profile expects the S3 bucket to exist. The Compose demo creates the bucket with an AWS CLI one-shot container.
  • The S3 provider uses path-style requests for RustFS.
  • OIDC is intentionally disabled in the on-prem profile. Wire customer OIDC as a follow-up by enabling controlPlane.auth.bearer and the browser login provider appropriate to the customer environment.