LLM Gateway Configuration
Chart values, environment variables, and startup validation for the LLM Gateway.
The LLM Gateway is configured through the gateway-stack values of the platform chart, under gateway-stack.llmGateway. This page describes the chart values operators set, the environment variables the service reads outside the chart, and the checks it runs at startup.
Required Configuration Areas
- Gateway database connection, the same PostgreSQL database the Control Plane uses. The platform chart supplies it from the
gateway-dsnkey of the platform database Secret. - Agent registration turned on, with a credential signer seed. The chart gives the gateway the Control Plane’s registration token secret and issuer, so set those once, in Control Plane Configuration.
- The Auth Service URL, for agents that register with an API key.
- The plugin runtime, with the same trusted signer keys, artifact storage, and plugin secrets key as the Control Plane, before you configure policies.
- Project context, so project configurations and memberships apply.
Chart Values
The platform chart already points the gateway at the platform database and sets deploymentEnvironment to production. Set the rest yourself. <release> is your platform release name, such as guardian-platform.
gateway-stack:
enabled: true
llmGateway:
registration:
enabled: true
credentialSigner:
existingSecret: "guardian-gateway-credential-signer" # holds seed
authServiceBaseURL: "http://<release>-auth-service:8080"
plugins:
enabled: true
artifactStorage:
provider: "gcs"
bucket: "guardian-plugins"
trustedSignerKeys:
signer-v1: "did:key:z6Mk..."
secrets:
resolutionOrder: ["store"]
encryptionKey:
existingSecret: "guardian-plugin-secrets-key" # holds encryption-key
projectContext:
mode: "enforce"
ingress:
enabled: true
className: "nginx"
hosts:
llmGateway: "gateway.example.com"| Value | Default | Notes |
|---|---|---|
signature.label | sig | The label Viper signs with. With any other label, every signed request is refused. |
signature.defaultSigMaxAge / defaultClockSkew | 60s / 120s | How old a signature may be, and how far a client’s clock may drift. |
registration.enabled | false | Must be true for agents to register, with a registration token or an API key. |
registration.credentialSigner.existingSecret / seed | none | A Secret with the Ed25519 seed the gateway signs registration credentials with, under secretKey (default seed), or the seed inline. With registration on, the gateway exits at startup without it. |
authServiceBaseURL | none | Turns on API-key registration. Use the Auth Service URL the Control Plane uses, http://<release>-auth-service:8080 in the platform chart, so both derive the same identity issuer. |
authServiceIdentityIssuer | <authServiceBaseURL>/api/v1/auth | Override only when the Control Plane reaches Auth Service at a different URL. |
upstreams.anthropicURL / openaiURL | the public provider APIs | The ChatGPT backend has no chart value; override it with extraArgs: ["-chatgpt-backend-upstream-url=…"]. |
audit.enabled | true | |
audit.retentionDays | 90 | Exchanges older than this are deleted every 24 hours, counted from pod start. |
audit.queueMaxBytes | 10737418240 (10 GiB) | The on-disk queue, an emptyDir. Once it is full, new audit records are dropped. |
audit.batchSize / flushInterval | 100 / 1s | |
plugins.enabled | false | Runs the global and project plugin configurations. Without a trusted signer key, the gateway exits at startup. |
plugins.pollInterval | 15s | How often the gateway reloads the active configurations. |
plugins.authorizerShadowEnabled | false | Compares plugin decisions with the legacy authorizer, without enforcing the legacy result. |
plugins.artifactStorage.* | none | The same provider, bucket, and prefix as controlPlane.plugins.artifactStorage, with credentials that can read them. The same keys as the Control Plane’s, except maxUploadBytes and gcs.kmsKeyName. |
serviceAccount.annotations | none | The gateway runs as its own service account. Without a storage credentials Secret, bind the cloud identity that reads the artifact bucket here. |
plugins.trustedSignerKeys | none | Map of key ID to did:key. The same keys as controlPlane.plugins.trustedSignerKeys, including the Control Plane’s publisher signer. |
plugins.secrets.resolutionOrder | none | Set ["store"] so plugins can read the secrets stored through the Control Plane. Without it, plugins that need a secret fail. |
plugins.secrets.encryptionKey.existingSecret | none | The same Secret as controlPlane.plugins.secrets.encryptionKey. Required when resolutionOrder includes store. |
plugins.secretEnvs / secretEnvsSecret.name | none | Plugin secrets as environment variables, inline or from a Secret, for local development. With either set and resolutionOrder empty, the chart sets the resolution order to env. |
projectContext.mode | disabled | observe or enforce turns on project context; see Project Context. |
extraArgs | none | Command-line flags for settings without a chart value. |
extraEnv | none | Extra environment variables, such as the OTEL_* exporter settings. See Observability. |
replicaCount / autoscaling.* / podDisruptionBudget.* | 1 / off / off | |
probes.startup.failureThreshold / periodSeconds | 180 / 5 | Allows 15 minutes for database migrations before liveness checks start. |
Project Context
Project context is off unless you turn it on with projectContext.mode. While it is off, the gateway ignores the project an agent presents: project configurations, project membership, and project trust do not apply, and every request runs under the global configuration only. Set it to enforce (or observe, which currently behaves the same) once plugins are on; the chart refuses to render with project context on and plugins off. The gateway’s mode denies nothing itself: with either value, a request that presents a project is denied when no project membership entry can admit it, and otherwise the Project Membership entry’s own mode decides whether a failed membership check denies it; see Gateway Policies.
Environment Variables
Outside the chart, the gateway reads these variables. Every name starts with LLM_GATEWAY_, left out below. The service also reads a TOML file named by -config or LLM_GATEWAY_CONFIG_FILE, and accepts a command-line flag for most settings. A flag overrides its environment variable, which overrides the file.
| Category | Variable | Default |
|---|---|---|
| Server | LISTEN | :10000 |
| Server | METRICS_LISTEN | :10001 |
| Server | DEPLOYMENT_ENVIRONMENT | none |
| Server | SERVICE_VERSION | none; reported as dev |
| Server | MAX_REQUEST_BODY_BYTES | 33554432 (32 MiB) |
| Database | REGISTRY_DB_DSN | AUDIT_DB_DSN; one of the two is required |
| Database | AUDIT_DB_DSN | none; required while audit is enabled |
| Database | BLOB_STORE_DB_DSN | REGISTRY_DB_DSN |
| Registration | AGENT_REGISTRATION_ENABLED | true |
| Registration | REGISTRATION_TOKEN_SECRET | none; required when registration is enabled |
| Registration | REGISTRATION_TOKEN_ISSUER | control-plane |
| Registration | CREDENTIAL_SIGNER_SEED | none; required when registration is enabled |
| Registration | AUTH_SERVICE_BASE_URL | none; API-key registration is off without it |
| Registration | AUTH_SERVICE_IDENTITY_ISSUER | <AUTH_SERVICE_BASE_URL>/api/v1/auth |
| Registration | AUTH_SERVICE_HTTP_TIMEOUT / AUTH_SERVICE_CACHE_TTL | 10s / 30s |
| Verification | SIGNATURE_LABEL | sig |
| Verification | DEFAULT_SIG_MAX_AGE / DEFAULT_CLOCK_SKEW | 60s / 120s |
| Verification | TRUSTED_YUBIKEY_ROOT_CERTS | none |
| Upstreams | ANTHROPIC_UPSTREAM_URL | https://api.anthropic.com |
| Upstreams | OPENAI_UPSTREAM_URL | https://api.openai.com |
| Upstreams | CHATGPT_BACKEND_UPSTREAM_URL | https://chatgpt.com/backend-api |
| Audit | AUDIT_ENABLED | true |
| Audit | AUDIT_QUEUE_DIR / AUDIT_QUEUE_MAX_BYTES | data/audit-queue / 10737418240 (10 GiB) |
| Audit | AUDIT_BATCH_SIZE / AUDIT_FLUSH_INTERVAL | 100 / 1s |
| Audit | AUDIT_RETENTION_DAYS | 90 |
| Blobs | BLOB_MAX_BYTES | 67108864 (64 MiB) |
| Plugins | PLUGINS_ENABLED | false |
| Plugins | PLUGIN_POLL_INTERVAL | 15s |
| Plugins | PLUGIN_END_QUEUE_DIR / PLUGIN_END_QUEUE_MAX_BYTES | data/plugin-end-queue / 134217728 (128 MiB) |
| Plugins | PLUGIN_REDACT_HEADERS | none |
| Plugins | PLUGIN_ARTIFACT_CACHE_DIR | data/plugin-artifacts |
| Plugins | PLUGIN_TRUSTED_SIGNER_KEYS | none; at least one is required when plugins are enabled |
| Plugins | PLUGIN_SECRETS_RESOLUTION_ORDER | none |
| Plugins | PLUGIN_SECRETS_ENCRYPTION_KEY | none |
| Plugins | PLUGIN_SECRETS_ENV_PREFIX | GUARDIAN_SECRET_ |
| Plugins | PLUGIN_AUTHORIZER_SHADOW_ENABLED | false |
| Plugins | PLUGIN_WASM_INTERPRETER | false |
| Plugins | PLUGIN_ARTIFACT_STORAGE_* | none; the Control Plane’s settings except MAX_UPLOAD_BYTES and GCS_KMS_KEY_NAME |
| Projects | PROJECT_CONTEXT_MODE | disabled |
PLUGIN_TRUSTED_SIGNER_KEYS is a comma-separated list of key_id=public_key pairs, where the public key may be a did:key; its flag, -plugin-trusted-signer-key, takes one pair and repeats. TRUSTED_YUBIKEY_ROOT_CERTS is a comma-separated list of PEM file paths. PLUGIN_SECRETS_RESOLUTION_ORDER is a comma-separated list of store and env: store reads the secrets stored through the Control Plane, and env reads environment variables named with PLUGIN_SECRETS_ENV_PREFIX, for local development. The credential signer seed and the plugin secrets key are base64, base64url, or hex; the seed may also be a path to a file that holds it.
PLUGIN_REDACT_HEADERS is a comma-separated list of extra header names, matched case-insensitively, whose values the gateway masks before request.end plugins and their on-disk queue see them. Headers whose names contain auth, token, secret, password, session, cookie, api-key or apikey, or end in -key, are always masked; use this setting for other upstream credential headers.
PLUGIN_WASM_INTERPRETER has no flag: true interprets plugin WebAssembly instead of compiling it to native code.
DEPLOYMENT_ENVIRONMENT is also reported to OpenTelemetry as deployment.environment unless OTEL_RESOURCE_ATTRIBUTES sets it. The service reads a few variables that are not listed here: REGISTRY_BACKEND, which accepts only postgres; the EXT_REGISTRY_* external registry settings, which are not supported in production; and PROJECT_CONTEXT_REQUIRE_MEMBERSHIP and PROJECT_TRUSTED_ISSUER_DIDS, which are deprecated and have no effect.
The Control Plane must use the same registration token secret and issuer, trusted signer keys, and plugin secrets key as the gateway, listed in Control Plane Configuration, as well as the same artifact storage and Auth Service URL.
Startup Validation
The gateway refuses to start when its configuration is inconsistent, and logs LLM Gateway failed: invalid config: followed by the setting at fault, usually in flag form. The checks include:
- A database DSN is required.
- The upstream URLs and the signature label must be set, and the upstream URLs must be
httporhttpsURLs with a host. - The request body and blob size limits must be above zero.
- Registration requires a registration token secret.
- An Auth Service identity issuer requires an Auth Service URL, the URL must be valid, and its timeout and cache TTL must be above zero.
- Audit capture requires an audit DSN and a queue directory, and its queue size, batch size, flush interval, and retention must be above zero.
- Plugins require at least one trusted signer key, a positive poll interval, their queue and cache directories, and a queue size above zero.
- Project context must be
disabled,observe, orenforce, and any mode other thandisabledrequires plugins. - Artifact storage needs a bucket once a provider is set, a region and credentials for
s3, and exactly one of a connection string, an account key, or managed identity for Azure.
These also stop startup, with LLM Gateway failed: and the reason:
- a missing credential signer seed while registration is on, or an unreadable seed
- a
storesecret resolver without the plugin secrets key, or a resolver other thanstoreorenv - a trusted signer key that is not a valid public key
- unreadable YubiKey root certificates
- an active plugin configuration that cannot be loaded, such as one whose artifact is unreachable or signed by an untrusted key
- an unreachable database
Keep secrets such as the credential signer seed, the plugin secrets key, and storage credentials in the deployment’s secret management system, not in values files.
Related
- Chart Values — where the gateway stack settings live in values.yaml
- Control Plane Configuration — the registration token secret and the plugin settings the gateway shares
- Register Agents — the registration paths these settings turn on
- LLM Gateway Operations — checks to run once the service is configured
- Observability — metrics and OpenTelemetry settings