Configuration reference

Every environment variable by service — shared secrets, gateway, worker, auth, AI, MCP and the UI build — with defaults and what each one does.

Services are configured entirely through environment variables. Defaults shown are the shipped ones; ”—” means no default (the service fails to start, or the feature stays off). Defaults that name a local host (localhost, a compose service) are placeholders for development.

Shared secrets and identity#

VariableUsed byMeaning
JWK_SETauthRSA JWK set used to sign JWTs. No default — generate with make gen-keys.
KELTA_ENCRYPTION_KEYworker, authAES-256 master key for envelope encryption (ENCRYPTED fields, stored secrets). No default. Losing it makes encrypted data unrecoverable.
KELTA_INTERNAL_TOKENworker, auth, aiShared secret for service-to-service calls under /internal/**.
KELTA_AUTH_ISSUER_URIgateway, worker, auth, aiThe OIDC issuer (https://auth.example.com). Must be identical everywhere. The gateway also honours the legacy OIDC_ISSUER_URI / JWT_ISSUER_URI.
HOSTNAMEallBecomes service.instance.id for metrics; the pod name in Kubernetes. Leave unset.
LOG_LEVEL, SECURITY_LOG_LEVELallRoot and security-logger levels (INFO, WARN).
MANAGEMENT_OPENTELEMETRY_TRACING_EXPORT_OTLP_ENDPOINTgateway, worker, authOTLP/HTTP traces endpoint (…/v1/traces).
MANAGEMENT_OTLP_METRICS_EXPORT_URLallOTLP/HTTP metrics endpoint (…/v1/metrics).
OTEL_TRACES_SAMPLER_ARGallTrace sampling ratio (default 1.0).
SERVER_PORTJava servicesHTTP port (default 8080).

Gateway#

VariableDefaultMeaning
REDIS_HOST, REDIS_PORTlocalhost, 6379Rate limits, PAT cache and revocation, identity cache
REDIS_POOL_MAX_ACTIVE / MAX_IDLE / MIN_IDLE / MAX_WAIT_MS100 / 50 / 10 / 2000Connection pool
NATS_URLnats://localhost:4222Event bus
WORKER_SERVICE_URL, AI_SERVICE_URLin-cluster service URLsUpstreams
CERBOS_HOST, CERBOS_GRPC_PORT—, 3593Policy decision point
CORS_ALLOWED_ORIGIN_PATTERN— (required)Allowed browser origins; * is accepted but logged as a warning
TENANT_SLUG_ENABLEDtrueResolve tenants from the first path segment
TENANT_SLUG_REQUIRE_PREFIXfalseReject /api requests with no slug or header
PERMISSIONS_ENABLED, PERMISSIONS_CACHE_TTLtrue, 5 (min)Cerbos route checks and the identity/permission cache
KELTA_SECURITY_TRUSTED_PROXIES—Comma-separated CIDRs or bare IPs of the proxies in front of the gateway (e.g. 10.42.0.0/16). When set, X-Forwarded-For / X-Real-IP are believed only from those peers and the client is the right-most untrusted hop; this drives audit logs, login history, geolocation, rate limits and tenant IP allowlists. Required behind an ingress if tenants use IP allowlists: empty, the allowlist judges the socket peer only (the ingress pod), so restricted tenants’ non-admins are refused; audit, geo and rate limits keep the legacy behaviour below
IP_ALLOWLIST_ENABLED, IP_ALLOWLIST_TRUST_XFFtrue, trueTenant IP allowlist feature and, when KELTA_SECURITY_TRUSTED_PROXIES is empty, whether the left-most X-Forwarded-For hop is the client IP for audit, geolocation and rate limits (spoofable). The allowlist never uses it — without trusted proxies it is strict (socket peer only). Ignored once trusted proxies are set
RATE_LIMIT_IP_PATHS/actuator/health=100,/api/modules/webhooks=300,/api/webhooks=300,/api/webhooks/mail=600,/api/webhooks/ses=600Per-IP per-minute budgets for unauthenticated prefixes, longest-prefix match
RATE_LIMIT_EXEMPT_CIDRS—Addresses exempt from both limiters; keep to narrow trusted ranges
RATE_LIMIT_USER_SHARE0.9Fraction of the tenant window one member may use; 1.0 disables
GEO_ENABLED, GEO_DB_PATH, GEO_REFRESH_MS, GEO_STALE_AFTER_DAYS, GEO_DOWNLOAD_TIMEOUT_MS, MAXMIND_LICENSE_KEYtrue, /data/geoip/GeoLite2-City.mmdb, 1 day, 7, 120000, —IP geolocation; without a MaxMind key enrichment is silently inactive
GATEWAY_HTTPCLIENT_MAX_CONNECTIONS / MAX_IDLE_TIME / ACQUIRE_TIMEOUT_MS2000 / 30s / 5000Upstream HTTP client

Worker#

VariableDefaultMeaning
SPRING_DATASOURCE_URL / USERNAME / PASSWORDlocalPostgreSQL
DB_POOL_MAX / MIN_IDLE / CONNECTION_TIMEOUT_MS / IDLE_TIMEOUT_MS / MAX_LIFETIME_MS / LEAK_DETECTION_MS10 / 5 / 20000 / 300000 / 1200000 / 30000Connection pool
SPRING_FLYWAY_ENABLEDfalseRun migrations at startup (compose) — Kubernetes uses the migrate profile
KELTA_SCHEMA_BOOTSTRAP_ENABLEDfalseApply collection DDL at pod startup; leave off where a migrate Job runs
SPRING_DATA_REDIS_HOST / PORTlocalRedis
NATS_URLlocalEvent bus
CERBOS_HOST, CERBOS_GRPC_PORT, CERBOS_CB_THRESHOLD, CERBOS_CB_COOLDOWN_SECONDS, CERBOS_SEED_FORCE—, 3593, 3, 10, falsePDP, its fail-closed circuit breaker, force a full policy seed on start
EXTERNAL_BASE_URLhttp://localhost:8080Public API base used in links (tracking, mailbox)
SCHEDULER_ENABLED, SCHEDULER_POLL_INTERVAL_MStrue, 60000Scheduled-job executor
REQUEST_LOGGING_ENABLEDtrueTenant request log
WORKER_ID—Optional stable worker identifier
EMAIL_ENABLED, EMAIL_FROM_ADDRESS, EMAIL_FROM_NAMEtrue, —, Kelta PlatformOutbound email
SMTP_HOST / PORT / USERNAME / PASSWORD / AUTH / STARTTLSlocalhost / 1025 / — / — / false / falsePlatform SMTP
KELTA_SMS_PROVIDERloglog or twilio
TWILIO_ACCOUNT_SID, TWILIO_KEY_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER—Twilio (Messaging)
KELTA_PUSH_VAPID_PUBLIC_KEY / PRIVATE_KEY / SUBJECT—Browser Web Push; absent ⇒ provider not registered
kelta.push.provider (property)logMobile push: log, fcm, apns (with kelta.push.apns.*)
KELTA_S3_ENABLED, KELTA_S3_ENDPOINT, KELTA_S3_PUBLIC_ENDPOINT, KELTA_S3_REGION, KELTA_S3_BUCKET, KELTA_S3_ACCESS_KEY, KELTA_S3_SECRET_KEY, KELTA_S3_URL_EXPIRY_MINUTESfalse, …, 15Attachments and module JARs; the public endpoint is what presigned URLs use
SVIX_SERVER_URL, SVIX_PUBLIC_URL, SVIX_AUTH_TOKEN—Outbound webhooks
SUPERSET_URL, SUPERSET_PUBLIC_URL, SUPERSET_ADMIN_USERNAME, SUPERSET_ADMIN_PASSWORD—Embedded BI
FLOW_RETENTION_ENABLED / DRY_RUN / MAX_AGE_DAYS / BATCH_SIZE / MAX_BATCHES / POLL_INTERVAL_MStrue / true / 60 / 1000 / 20 / hourlyFlow-log pruning; dry-run until you set FLOW_RETENTION_DRY_RUN=false
KELTA_MODULES_SIGNING_REQUIREDfalseSet true in production (Modules)
KELTA_MODULES_SIGNING_PUBLIC_KEY, KELTA_MODULES_SIGNING_ALGORITHM—, Ed25519Legacy platform-wide signing anchor (prefer per-tenant keys)
KELTA_MODULES_STUB_MODEfalseDevelopment only
LOKI_URL, TEMPO_URL, MIMIR_URL—Backends the console’s monitoring pages query for logs, traces and metrics
CAMPAIGN_*, KELTA_MAILBOX_*, KELTA_TELEHEALTH_VISIT_SECRET, KELTA_LIVEKIT_*, TELEHEALTH_REMINDER*, KELTA_WATCH_PROMOTABLE_SOURCES—Optional feature areas (campaigns, support mailboxes, telehealth video, availability watches). Some HMAC secrets fail startup when unset — see .env.example

Auth#

VariableDefaultMeaning
DB_URL / DB_USERNAME / DB_PASSWORD, DB_POOL_*local, DB_POOL_MAX 10PostgreSQL
REDIS_HOST / REDIS_PORTlocalSessions and caches
WORKER_SERVICE_URLlocalInternal user lookup
UI_BASE_URLhttp://localhost:5173Where to send users after login
COOKIE_DOMAIN—Session cookie domain
CORS_ALLOWED_ORIGINShttp://localhost:5173
DIRECT_LOGIN_ENABLEDfalsePassword grant for bootstrap/tests — keep false in production
KELTA_BOOTSTRAP_ADMIN_PASSWORD—Initial password for the platform admin admin@kelta.local, applied once on the first boot that finds the database’s seeded password, with a forced change at first sign-in. Never logged. Unset: a random password is generated and printed once in a WARN banner in the kelta-auth log. No effect once the password has been replaced
SUPERSET_CLIENT_ID / CLIENT_SECRET / REDIRECT_URI—OAuth client for embedded BI
KELTA_AUTH_RATE_LIMIT_IP_PATHS/portal/api/signup=5,/portal/api/login/request=10,/portal/api/challenge=30,/portal/login=10Per-IP budgets on public portal paths
KELTA_AUTH_RATE_LIMIT_TRUSTED_PROXY_COUNT1X-Forwarded-For hops to trust from the right; 0 when directly exposed. Used only when KELTA_SECURITY_TRUSTED_PROXIES is empty
KELTA_SECURITY_TRUSTED_PROXIES—Same meaning as on the gateway: CIDRs or bare IPs of the auth server’s ingress; when set, the portal rate limit keys on the right-most untrusted X-Forwarded-For hop
KELTA_AUTH_BOT_CHALLENGE_ENABLED, _HMAC_KEY, _MAX_NUMBER, _TTL_SECONDSfalse, —, 100000, 600Proof-of-work challenge on portal signup; enabling without a key fails startup on purpose
kelta.auth.saml.sp-signing-certificate / sp-signing-private-key (properties)—Platform SP key pair for signed SAML requests

AI#

VariableDefaultMeaning
ANTHROPIC_API_KEY— (required)
AI_DEFAULT_MODEL, AI_DEFAULT_MAX_TOKENS, AI_DEFAULT_TEMPERATUREclaude-sonnet-5, 32768, 0.7Defaults a tenant can override
AI_RATE_LIMIT_ENABLED, AI_RATE_LIMIT_REQUESTS_PER_MINUTEtrue, 60Per-user
AI_SSE_TIMEOUT_MS300000Streaming timeout
SPRING_DATASOURCE_*, DB_POOL_*, SPRING_DATA_REDIS_*, WORKER_SERVICE_URLlocal

MCP#

VariableDefaultMeaning
GATEWAY_URLin-cluster gatewayWhere tool calls go
MCP_SESSION_TTL_MINUTES30
MCP_TOOL_TIMEOUT_MS60000Per tool call

UI (build-time)#

VITE_API_BASE_URL (the gateway origin — required), VITE_APP_VERSION, VITE_OTEL_ENDPOINT, VITE_OTEL_SERVICE_NAME, VITE_OTEL_SERVICE_NAMESPACE, VITE_OTEL_DEPLOYMENT_ENVIRONMENT. These are baked into the static bundle when the image is built.

Generating secrets#

make gen-keys            # JWK_SET, KELTA_ENCRYPTION_KEY and the HMAC secrets into .env
make gen-vapid           # Web Push key pair
openssl rand -base64 32  # any single HMAC key

Edit this page on GitHub