Skip to main content

Pull the image

Tags: latest, and X.Y.Z for each release. Images are multi-architecture (linux/amd64, linux/arm64), each built natively.
Published when a vX.Y.Z tag is pushed. Before the first release, build locally: docker build -t warden:local .The package is built from a private repository, so it inherits private visibility, and GitHub offers no API to change that — the setting exists only in the web UI. Make it public once, at https://github.com/users/Abhishek-Mallick/packages/container/warden/settings; every later release inherits the setting. Until then docker pull needs a ghcr.io login, and an anonymous pull reports that the package does not exist.

Run it

The image runs as UID 65532 and contains no shell. A named volume mounted at the state directory inherits the right ownership on first use; a bind mount from the host does not, so chown 65532:65532 it first.

The whole stack, with a database beside it

The demo stack — Warden plus a seeded PostgreSQL, one command — lives in the source repository, which is private. With access to it:
Without access, compose your own: the image above, a PostgreSQL service, and the configuration from the quickstart. The only thing the demo adds is seed data.
Whatever the source of the compose file, two properties are worth copying:
  • Do not publish the database port. Agents reach it through Warden or not at all, which is the arrangement Warden exists to create.
  • Publish Warden’s port to loopback unless TLS is configured. Warden refuses a non-loopback listener without TLS unless told otherwise.

Production notes

  • TLS. Warden refuses a non-loopback listener without TLS unless allow_insecure_listen: true is set — appropriate only when something in front terminates TLS. Mount the certificate and key and set tls.cert / tls.key. See TLS and state.
  • Secrets. The configuration file holds a database DSN. Mount it from a secret store rather than baking it into an image, and prefer key_hash / token_hash over plaintext credentials — the gateway warns when it finds plaintext.
  • Health. GET /health is unauthenticated and reports process liveness and how many connections are configured, and nothing about what it governs. Use it as the container health check.
  • Restarts. With data_dir on a volume, the audit chain, leases, and idempotency keys survive. A pending async approval does not: it never ran, and the agent is told the outcome is unknown if it retries the same key.