Skip to content

Environment variables

Every KINDGI_* variable the Kindgi runtime (the server) and the pack service read. Generated from @kindgi/env-schema, Kindgi's own list, so it matches this version.

The KINDGI_ prefix is reserved for Kindgi: a pack can't declare such a name in its env, and kindgi dev never resolves one as a secret, so an app's own variables stay its own.

HTTP port the Kindgi API server listens on. Default 4000.

  • Read by: the server
  • Required: no
  • Example: 4000

Address the API server binds. Default: all interfaces (what a container platform such as Cloud Run needs). 127.0.0.1 keeps it off the network; kindgi dev sets that on Linux, where the runtime container shares the host network.

  • Read by: the server
  • Required: no
  • Example: 127.0.0.1

Postgres connection string. Default postgres://localhost:5432/kindgi (dev only).

  • Read by: the server
  • Required: no
  • Example: postgres://user:pass@postgres.internal:5432/kindgi

OpenFGA HTTP API URL. Set → per-tenant FGA stores are bootstrapped and authorization is enforced; unset → routes mount without enforcement (dev only; production MUST set it).

  • Read by: the server
  • Required: no
  • Example: http://openfga.internal:8080

Tenant UUID to seed / reuse. Default: fresh UUID printed at boot.

  • Read by: the server
  • Required: no
  • Example: 00000000-0000-4000-8000-000000000001

Bearer token to seed / reuse. Default: fresh kgi_bt_... token per boot.

  • Read by: the server
  • Required: no
  • Example: kgi_bt_my_stable_local_token

Seed user UUID. Pinning this across restarts keeps the FGA admin@tenant tuple stable.

  • Read by: the server
  • Required: no
  • Example: 00000000-0000-4000-8000-000000000002

Mount /docs (Scalar API reference). true (default) | false.

  • Read by: the server
  • Required: no
  • Values: true, false, 1, 0
  • Example: true

Development mode: true enables development-only settings (the dotenv secrets backend, KINDGI_PACK_DIR, KINDGI_DEV_CONSOLE_LOGIN, KINDGI_DEV_HOST_ALIAS). The server refuses those settings when this is off. Never set it in production.

  • Read by: the server
  • Required: no
  • Values: true, false, 1, 0
  • Example: false

How far what tenants register may reach into the server's own host. deployed refuses a stdio MCP endpoint (a command the server would run in its container, as its user) at registration (403 host-access-denied) and at connect; run MCP servers over HTTP instead. It also refuses the server's connections to the cloud metadata endpoints (link-local addresses) and to its own host (loopback) when a tenant chose the host: an MCP endpoint, a model provider's base URL, an HTTP tool, an image reference. Private networks stay reachable. local allows all of it: only for a machine where every token holder may run commands. Unset: local with KINDGI_DEV, deployed otherwise; a value set here always wins.

  • Read by: the server
  • Required: no
  • Values: local, deployed
  • Example: deployed

The commercial license key (kgi_lk_...) Kindgi issues: signed, checked offline at startup, with no call to Kindgi. Required outside development mode: without a valid key the server refuses to start, naming this variable. KINDGI_DEV=true needs none. A production key comes with a commercial license; a free non-production key covers staging and CI. A secret: give it from your secrets store.

  • Read by: the server
  • Required: no

The env this runtime serves. Secrets a tool declares by name (needsSpec.secrets) resolve under this env name. Unset: local in development mode (the .env and .env.local files); otherwise a tool that declares secrets fails its calls, naming this variable.

  • Read by: the server
  • Required: no
  • Example: production

Absolute path to the Ed25519 private key (PKCS#8 PEM, mode 0600) that signs public run tokens (kgi_pt_…): the short-lived, read-only tokens a browser uses to follow a run. Use a key for this alone (openssl genpkey -algorithm ed25519). Unset: in development mode the server signs with a key generated at startup (tokens end at restart); otherwise public run tokens are off.

  • Read by: the server
  • Required: no
  • Example: /etc/kindgi/public-token-signing.pem

The same key's PEM file, base64 (base64 < key.pem): for platforms that give secrets as environment variables (Cloud Run with Secret Manager), where a key file's mode can't be 0600. Set this or KINDGI_PUBLIC_TOKEN_SIGNING_KEY_PATH, not both.

  • Read by: the server
  • Required: no

Comma-separated browser origins allowed to call, cross-origin, the routes a public run token can use (GET /v1/runs/{runId}/progress and its stream). Exact origins, no wildcards. Unset: no CORS headers on any route.

  • Read by: the server
  • Required: no
  • Example: https://app.example.com

Where secret bytes live. none (default; /v1/secrets/* unmounted) | postgres (envelope-encrypted, needs KMS) | dotenv (.env files in a directory; development only, needs KINDGI_DEV=true) | secret-manager (reserved; not supported through this variable).

  • Read by: the server
  • Required: no
  • Values: none, postgres, dotenv, secret-manager
  • Example: postgres

Absolute path of the directory whose .env files hold secrets (dotenv backend). Mount the project directory here; secrets written through the API land in its files.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=dotenv
  • Required: yes
  • Example: /pack

Comma-separated .env files read for secrets (dotenv backend), relative to KINDGI_SECRETS_DOTENV_DIR, lowest precedence first. Default .env,.env.local.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=dotenv
  • Required: no
  • Example: .env,.env.local

Which KMS vendor wraps DEKs (postgres backend only). Currently supported: gcp. Reserved: aws, libsodium.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=postgres
  • Required: yes
  • Values: gcp, aws, libsodium
  • Example: gcp

Absolute path to a 32-byte AAD/HMAC key file (mode 0600). Same key across every replica; protects AEAD associated data over every secret row. The postgres backend needs this or KINDGI_SECRETS_AAD_KEY, not both.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=postgres
  • Required: no
  • Example: /etc/kindgi/secrets-aad.key

The 32-byte AAD/HMAC key itself, base64: for platforms that give secrets as environment variables (Cloud Run with Secret Manager), where a key file's mode can't be 0600. The postgres backend needs this or KINDGI_SECRETS_AAD_KEY_PATH, not both.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=postgres
  • Required: no

GCP project id owning the KMS keyring + key.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=postgres, KINDGI_SECRETS_BACKEND_KMS=gcp
  • Required: yes
  • Example: my-proj

KMS location, e.g. us-central1, europe-west1, global.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=postgres, KINDGI_SECRETS_BACKEND_KMS=gcp
  • Required: yes
  • Example: us-central1

KMS keyring id within the location.

  • Read by: the server, with KINDGI_SECRETS_BACKEND=postgres, KINDGI_SECRETS_BACKEND_KMS=gcp
  • Required: yes
  • Example: kindgi

CryptoKey id within the keyring (symmetric GOOGLE_SYMMETRIC_ENCRYPTION).

  • Read by: the server, with KINDGI_SECRETS_BACKEND=postgres, KINDGI_SECRETS_BACKEND_KMS=gcp
  • Required: yes
  • Example: secrets-kek

Pack service (runs the pack code: tools and guardrail checks)

Section titled “Pack service (runs the pack code: tools and guardrail checks)”

Base URL of the pack service, the separate process that runs the pack code (its tools and guardrail checks), e.g. http://pack-service:8080 or its internal Cloud Run URL. Set: the server calls it over HTTP for every pack tool and check, and needs KINDGI_PACK_SERVICE_TOKEN. Unset: no pack code runs, and a pack tool fails saying no pack service is wired. kindgi dev runs its own.

  • Read by: the server
  • Required: no
  • Example: http://pack-service:8080

How long one pack call (a tool or a guardrail check) may take, in milliseconds. Default 120000. The deadline travels with the call, and the pack service aborts the handler when it passes.

  • Read by: the server, when it calls a pack service (KINDGI_PACK_SERVICE_URL set)
  • Required: no
  • Example: 120000

How the server proves itself to the pack service besides the pack token. token (default): the pack token alone. google-id-token: also a Google ID token for the pack service URL, from the server's own identity, for a pack service on Cloud Run behind IAM (--no-allow-unauthenticated); the URL must be https. The identity is a service account: on Cloud Run the server's own; elsewhere, impersonate one (a person's own credentials can't mint an ID token for a service).

  • Read by: the server, when it calls a pack service (KINDGI_PACK_SERVICE_URL set)
  • Required: no
  • Values: token, google-id-token
  • Example: token

Shared secret between the server and the pack service. The pack service refuses any call without it, and the server sends it with every call. Required by the pack service, and by the server when KINDGI_PACK_SERVICE_URL is set. Use a long random value (openssl rand -base64 32). The pack service removes it from its environment before it loads the pack code.

  • Read by: the server, when it calls a pack service (KINDGI_PACK_SERVICE_URL set); the pack service
  • Required: yes

Path of the pack's index.json in the pack service's image. Default /app/index.json, where kindgi build puts it; the --index flag overrides it.

  • Read by: the pack service
  • Required: no
  • Example: /app/index.json

How many calls the pack service runs at once. Past it, calls get 503 (overloaded), which the server retries. Default 32. On Cloud Run, set the service's concurrency to the same number.

  • Read by: the pack service
  • Required: no
  • Example: 32

What the pack service does when a name the pack's env.required declares is unset or empty in its environment. strict (default): it isn't ready, and /readyz and every call answer 503 naming the missing names. warn: it serves, and names them in its log and /v1/info. kindgi dev uses warn.

  • Read by: the pack service
  • Required: no
  • Values: strict, warn
  • Example: strict

Image registry (where deployments' images are read from)

Section titled “Image registry (where deployments' images are read from)”

The registry host the credentials below are for, with its port when it has one (e.g. registry.example, ghcr.io). Other registries are read anonymously.

  • Read by: the server
  • Required: no
  • Example: registry.example

Username for KINDGI_IMAGE_REGISTRY_HOST. Used for the registry's token flow, or as basic auth.

  • Read by: the server
  • Required: no
  • Example: kindgi-reader

Password or access token for KINDGI_IMAGE_REGISTRY_HOST. Read-only (pull) access is enough.

  • Read by: the server
  • Required: no

Comma-separated registry hosts reached over plain HTTP instead of HTTPS, e.g. a local registry:2. Loopback hosts (localhost, 127.0.0.1) always are.

  • Read by: the server
  • Required: no
  • Example: registry.internal:5000

How the server signs in to KINDGI_IMAGE_REGISTRY_HOST. static (default): KINDGI_IMAGE_REGISTRY_USERNAME and _PASSWORD. google: the server's own Google identity (Application Default Credentials: the service's identity on Cloud Run), for Artifact Registry; no username or password is set, and Kindgi keeps no key file.

  • Read by: the server
  • Required: no
  • Values: static, google
  • Example: static

Development (kindgi dev; each needs KINDGI_DEV=true)

Section titled “Development (kindgi dev; each needs KINDGI_DEV=true)”

Development only: the pack directory kindgi dev runs. The server reads the pack's tools, guardrails, agents and flows from the index kindgi dev writes there (.kindgi/dev/index.json), on every change, instead of from Postgres; signed deployments are off. Mount the directory, not the file: the index is replaced by rename.

  • Read by: the server
  • Required: no
  • Example: /pack

Development only: true lets the console log in by itself. GET /__dev/bearer hands it the API token, answering only requests addressed to a loopback host (localhost, 127.0.0.1, [::1]). Needs the console.

  • Read by: the server
  • Required: no
  • Values: true, false, 1, 0
  • Example: true

Development only: where the server's outbound calls to a loopback address (localhost, 127.0.0.1, [::1]) connect instead. This covers webhooks to the app, HTTP MCP endpoints, model providers and the pack service. Inside a container, loopback is the container itself; kindgi dev sets host.docker.internal on Docker Desktop. The URL, the Host header and the TLS server name stay as written; only the connection goes to the alias.

  • Read by: the server
  • Required: no
  • Example: host.docker.internal