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.
Core server config
Section titled “Core server config”KINDGI_API_PORT
Section titled “KINDGI_API_PORT”HTTP port the Kindgi API server listens on. Default 4000.
- Read by: the server
- Required: no
- Example:
4000
KINDGI_API_HOST
Section titled “KINDGI_API_HOST”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
KINDGI_DATABASE_URL
Section titled “KINDGI_DATABASE_URL”Postgres connection string. Default postgres://localhost:5432/kindgi (dev only).
- Read by: the server
- Required: no
- Example:
postgres://user:pass@postgres.internal:5432/kindgi
KINDGI_OPENFGA_API_URL
Section titled “KINDGI_OPENFGA_API_URL”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
KINDGI_TENANT_ID
Section titled “KINDGI_TENANT_ID”Tenant UUID to seed / reuse. Default: fresh UUID printed at boot.
- Read by: the server
- Required: no
- Example:
00000000-0000-4000-8000-000000000001
KINDGI_API_TOKEN
Section titled “KINDGI_API_TOKEN”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
KINDGI_SEED_USER_ID
Section titled “KINDGI_SEED_USER_ID”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
KINDGI_DOCS
Section titled “KINDGI_DOCS”Mount /docs (Scalar API reference). true (default) | false.
- Read by: the server
- Required: no
- Values:
true,false,1,0 - Example:
true
KINDGI_DEV
Section titled “KINDGI_DEV”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
KINDGI_TENANT_HOST_ACCESS
Section titled “KINDGI_TENANT_HOST_ACCESS”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
KINDGI_LICENSE_KEY
Section titled “KINDGI_LICENSE_KEY”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
KINDGI_ENV
Section titled “KINDGI_ENV”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
KINDGI_PUBLIC_TOKEN_SIGNING_KEY_PATH
Section titled “KINDGI_PUBLIC_TOKEN_SIGNING_KEY_PATH”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
KINDGI_PUBLIC_TOKEN_SIGNING_KEY
Section titled “KINDGI_PUBLIC_TOKEN_SIGNING_KEY”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
KINDGI_CORS_ORIGINS
Section titled “KINDGI_CORS_ORIGINS”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
Secrets backend selection
Section titled “Secrets backend selection”KINDGI_SECRETS_BACKEND
Section titled “KINDGI_SECRETS_BACKEND”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
KINDGI_SECRETS_DOTENV_DIR
Section titled “KINDGI_SECRETS_DOTENV_DIR”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
KINDGI_SECRETS_DOTENV_FILES
Section titled “KINDGI_SECRETS_DOTENV_FILES”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
KINDGI_SECRETS_BACKEND_KMS
Section titled “KINDGI_SECRETS_BACKEND_KMS”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
KINDGI_SECRETS_AAD_KEY_PATH
Section titled “KINDGI_SECRETS_AAD_KEY_PATH”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
KINDGI_SECRETS_AAD_KEY
Section titled “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 vendor config (postgres + gcp KMS)
Section titled “GCP vendor config (postgres + gcp KMS)”KINDGI_SECRETS_GCP_PROJECT_ID
Section titled “KINDGI_SECRETS_GCP_PROJECT_ID”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
KINDGI_SECRETS_GCP_LOCATION_ID
Section titled “KINDGI_SECRETS_GCP_LOCATION_ID”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
KINDGI_SECRETS_GCP_KEY_RING_ID
Section titled “KINDGI_SECRETS_GCP_KEY_RING_ID”KMS keyring id within the location.
- Read by: the server, with
KINDGI_SECRETS_BACKEND=postgres,KINDGI_SECRETS_BACKEND_KMS=gcp - Required: yes
- Example:
kindgi
KINDGI_SECRETS_GCP_KEY_ID
Section titled “KINDGI_SECRETS_GCP_KEY_ID”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)”KINDGI_PACK_SERVICE_URL
Section titled “KINDGI_PACK_SERVICE_URL”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
KINDGI_PACK_CALL_TIMEOUT_MS
Section titled “KINDGI_PACK_CALL_TIMEOUT_MS”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_URLset) - Required: no
- Example:
120000
KINDGI_PACK_SERVICE_AUTH
Section titled “KINDGI_PACK_SERVICE_AUTH”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_URLset) - Required: no
- Values:
token,google-id-token - Example:
token
KINDGI_PACK_SERVICE_TOKEN
Section titled “KINDGI_PACK_SERVICE_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_URLset); the pack service - Required: yes
KINDGI_PACK_INDEX
Section titled “KINDGI_PACK_INDEX”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
KINDGI_PACK_SERVICE_MAX_CONCURRENCY
Section titled “KINDGI_PACK_SERVICE_MAX_CONCURRENCY”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
KINDGI_PACK_ENV_CHECK
Section titled “KINDGI_PACK_ENV_CHECK”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)”KINDGI_IMAGE_REGISTRY_HOST
Section titled “KINDGI_IMAGE_REGISTRY_HOST”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
KINDGI_IMAGE_REGISTRY_USERNAME
Section titled “KINDGI_IMAGE_REGISTRY_USERNAME”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
KINDGI_IMAGE_REGISTRY_PASSWORD
Section titled “KINDGI_IMAGE_REGISTRY_PASSWORD”Password or access token for KINDGI_IMAGE_REGISTRY_HOST. Read-only (pull) access is enough.
- Read by: the server
- Required: no
KINDGI_IMAGE_REGISTRY_INSECURE_HOSTS
Section titled “KINDGI_IMAGE_REGISTRY_INSECURE_HOSTS”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
KINDGI_IMAGE_REGISTRY_AUTH
Section titled “KINDGI_IMAGE_REGISTRY_AUTH”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)”KINDGI_PACK_DIR
Section titled “KINDGI_PACK_DIR”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
KINDGI_DEV_CONSOLE_LOGIN
Section titled “KINDGI_DEV_CONSOLE_LOGIN”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
KINDGI_DEV_HOST_ALIAS
Section titled “KINDGI_DEV_HOST_ALIAS”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