Environment variables
The KUBEBOLT_* variables an operator actually sets, grouped by family, with the code default for each.
The backend reads well over a hundred KUBEBOLT_* variables. This page covers
the ones an operator sets; the rest are internal knobs with defaults you should
not need to touch. deploy/.env.example in the repository is the exhaustive,
commented list.
Environment is the boot baseline, not the last word. Most of these have a matching field in the Administration pages. A value saved there is persisted and wins on every later read, hot, with no restart. So config-as-code keeps working — until someone edits it in the UI, at which point the UI is the authority for that setting.
Defaults below are what the code falls back to when the variable is unset.
Some are set to a different explicit value in .env.example; the code default
is what an unset variable gives you.
Core
| Variable | Default | What it does |
|---|---|---|
KUBEBOLT_DATA_DIR | ./data | Where the embedded BoltDB lives — users, tokens, agent registry, sessions. Mount a PersistentVolume here. Cannot be set from the UI |
KUBEBOLT_METRICS_STORAGE_URL | http://localhost:8428 | The bundled VictoriaMetrics endpoint |
KUBEBOLT_CORS_ORIGINS | http://localhost:3000,http://localhost:5173 | Comma-separated allowed origins. Required when the UI is served from a different origin than the API. Wildcards work |
KUBEBOLT_DISPLAY_NAME | KubeBolt | Label in the topbar and browser title, to tell installs apart |
KUBEBOLT_LOG_LEVEL | info | debug, info, warn, error |
KUBEBOLT_LOG_FORMAT | text | text or json |
KUBEBOLT_UPDATE_CHECK_ENABLED | true | Periodic check of the GitHub releases API. Set false when air-gapped |
KUBEBOLT_CACHE_SYNC_TIMEOUT_SECONDS | 45 | How long a cold cluster connect waits for informer caches. Floored at 5 |
KUBEBOLT_DEFAULT_REFRESH_INTERVAL_SECONDS | 30 | Fallback UI refresh cadence. One of 5, 10, 15, 30, 60, 120 |
Authentication
Full context in Authentication.
| Variable | Default | What it does |
|---|---|---|
KUBEBOLT_AUTH_ENABLED | true | Set false only when access is already restricted at the network layer |
KUBEBOLT_ADMIN_PASSWORD | auto-generated | Seeds the admin password on first boot. Ignored once the admin exists |
KUBEBOLT_RESET_ADMIN_PASSWORD | — | Resets the admin password on the next boot, then continues booting. Clear it afterwards |
KUBEBOLT_JWT_SECRET | auto-generated, persisted | Signing key. An operator-supplied value under 32 bytes fails the boot on purpose |
KUBEBOLT_JWT_EXPIRY | 15m | Access-token lifetime |
KUBEBOLT_JWT_REFRESH_EXPIRY | 168h | Refresh-token lifetime (7 days) |
KUBEBOLT_PLATFORM_ADMINS | — | Comma-separated emails that carry platform-admin capability. Inert single-tenant, where the lone admin already is one |
Both JWT lifetimes are editable in Administration → Access → Authentication but need a restart, because the JWT service is wired at boot. The UI flags that.
AI and Kobi
The full set, and the Helm equivalents, are in Enabling Kobi.
| Variable | Default | What it does |
|---|---|---|
KUBEBOLT_AI_API_KEY | — | This is the switch. Kobi is off when neither this nor a key saved in Administration → AI (Kobi) → Configuration is set |
KUBEBOLT_AI_PROVIDER | anthropic | anthropic or openai — the only two values; every OpenAI-compatible API uses openai |
KUBEBOLT_AI_MODEL | claude-sonnet-5 · gpt-4o | Provider default when unset |
KUBEBOLT_AI_BASE_URL | provider default | Full endpoint URL, used verbatim — for OpenAI-compatible APIs it must end in /chat/completions |
KUBEBOLT_AI_MAX_TOKENS | 4096 | Ceiling per response |
KUBEBOLT_AI_MAX_ROUNDS | 20 | Tool-calling rounds per answer. Clamped to 2–40 |
KUBEBOLT_AI_FALLBACK_API_KEY | — | Setting this arms the fallback provider (_PROVIDER, _MODEL, _BASE_URL are optional) |
KUBEBOLT_AI_ACTIONS_ENABLED | true | Master switch for the propose_* action tools |
KUBEBOLT_AI_DESTRUCTIVE_ACTIONS_ENABLED | true | Gates delete and scale-to-zero |
KUBEBOLT_AI_ACTION_PROGRESS_TIMEOUT | 90s | How long the UI polls an executed action for convergence. Floored at 10s |
KUBEBOLT_AI_AUTO_COMPACT | true | Fold old turns into a summary as the context fills |
KUBEBOLT_AI_AUTO_COMPACT_THRESHOLD | 0.80 | Fraction of the budget at which compaction fires |
KUBEBOLT_AI_SESSION_BUDGET_TOKENS | model context window | The budget compaction measures against |
KUBEBOLT_AI_COMPACT_MODEL | claude-haiku-4-5 · gpt-4o-mini | Model that writes the summary. Set it for any non-OpenAI endpoint |
KUBEBOLT_AI_COMPACT_PRESERVE_TURNS | 3 | Turns kept intact after a fold |
KUBEBOLT_AI_SHOW_TOOL_CALLS | true | Render each tool call as a card in the panel |
Notifications
See Notifications.
| Variable | Default | What it does |
|---|---|---|
KUBEBOLT_NOTIFICATIONS_ENABLED | true | Global kill switch. false silences every channel without unconfiguring it |
KUBEBOLT_NOTIFICATIONS_MIN_SEVERITY | warning | critical, warning, info. An invalid value falls back to warning |
KUBEBOLT_NOTIFICATIONS_COOLDOWN | 1h | Dedup window for the same insight |
KUBEBOLT_NOTIFICATIONS_INCLUDE_RESOLVED | false | Also notify when an insight resolves |
KUBEBOLT_NOTIFICATIONS_BASE_URL | — | Public URL used to build links inside messages |
KUBEBOLT_SLACK_WEBHOOK_URL · KUBEBOLT_DISCORD_WEBHOOK_URL | — | Configuring a URL enables that channel |
KUBEBOLT_SLACK_ENABLED · KUBEBOLT_DISCORD_ENABLED · KUBEBOLT_EMAIL_ENABLED | true | Pause one channel without clearing its destination |
KUBEBOLT_SMTP_HOST · _USERNAME · _PASSWORD · _FROM · _TO | — | Email needs host, from, and at least one recipient to count as configured. _TO is comma-separated |
KUBEBOLT_SMTP_PORT | 587 | STARTTLS |
KUBEBOLT_SMTP_DIGEST_MODE | instant | instant, hourly, daily |
Agent ingest
The channel between the agent and the backend. Defaults are permissive so a fresh install boots and can then be locked down from Administration → Agents & Ingest → Configuration.
| Variable | Default | What it does |
|---|---|---|
KUBEBOLT_AGENT_AUTH_MODE | disabled | disabled, permissive, enforced. Restart required |
KUBEBOLT_AGENT_TOKEN_AUDIENCE | kubebolt-backend | Expected audience on agent tokens |
KUBEBOLT_AGENT_REQUIRE_MTLS | false | Require client certificates on the gRPC channel |
KUBEBOLT_AGENT_INGEST_URL | — | External host:port remote agents dial. Setting it marks the install as hosted and changes the wizard’s defaults |
KUBEBOLT_AGENT_AUTOREGISTER_CLUSTERS | false | Let an agent-proxy peer register its own cluster |
KUBEBOLT_AGENT_REGISTRY_PRUNE_HORIZON | 24h | When a stale agent record is pruned |
KUBEBOLT_AGENT_RATE_LIMIT_ENABLED | false | Fleet-wide rate limit on the ingest channel |
KUBEBOLT_AGENT_RATE_LIMIT_RPS · _BURST | 1000 · 2000 | Its rate and burst |
KUBEBOLT_AGENT_TUNNEL_IDLE_TIMEOUT | 5m | Idle SPDY tunnels (exec, port-forward) close after this |
KUBEBOLT_AGENT_PROXY_CONNECT_TIMEOUT | 25s | Cold-connect deadline through an agent |
KUBEBOLT_AGENT_PROXY_STUCK_TIMEOUT | 45s | Stuck-agent watchdog. 0 disables it |
KUBEBOLT_AGENT_PROXY_REQUEST_TIMEOUT | 30s | Per-request deadline through the tunnel |
KUBEBOLT_AGENT_PROXY_CONNECT_TIMEOUT is the one to raise if a large,
churning cluster reports “Cluster unreachable” while it is still syncing —
see Troubleshooting. It is a blunt instrument: it
also loosens the protection that exists for genuinely wedged agents.
Metrics ingest
| Variable | Default | What it does |
|---|---|---|
KUBEBOLT_REMOTE_WRITE_ENABLED | false | Accept Prometheus remote_write at /api/v1/prom/write |
KUBEBOLT_REMOTE_WRITE_AUTH_MODE | disabled | disabled, permissive, enforced |
KUBEBOLT_PROM_WRITE_DEFAULT_SAMPLES_PER_SEC | 10000 | Per-tenant sample rate |
KUBEBOLT_PROM_WRITE_DEFAULT_BURST_SAMPLES | 100000 | Its burst |
KUBEBOLT_PROM_WRITE_DEFAULT_MAX_ACTIVE_SERIES | 1000000 | Per-tenant active-series ceiling |
KUBEBOLT_PROM_WRITE_DEFAULT_MAX_ACTIVE_SERIES_GLOBAL | 0 (off) | Install-wide ceiling |
KUBEBOLT_PROM_WRITE_NAME_FILTER_ENABLED | true | Classify incoming series by name |
KUBEBOLT_PROM_WRITE_ALLOW_CUSTOM_SERIES | false | Accept series outside the core set |
Retention
One hourly pass, per organization. All Go durations. Active insights never expire, and neither do firing episodes.
| Variable | Default | What it bounds |
|---|---|---|
KUBEBOLT_INSIGHTS_RETENTION_HORIZON | 168h (7 days) | Resolved insights and their episodes |
KUBEBOLT_INSIGHT_EXPIRE_TTL | 15m | A firing episode with no signal for longer flips to expired instead of staying active forever after an agent leaves |
KUBEBOLT_FINDINGS_RETENTION_HORIZON | 720h (30 days) | Security findings and runtime events |
KUBEBOLT_AUDIT_RETENTION_HORIZON | 2160h (90 days) | The mutation and access audit trail |
KUBEBOLT_COPILOT_CONVERSATION_RETENTION_HORIZON | 2160h (90 days) | Kobi transcripts — the highest-PII store in the product |
KUBEBOLT_COPILOT_CONVERSATION_MAX_PER_USER | 200 | Conversations kept per user |
On Cloud these are not yours to set: retention is a plan dimension, listed in Security and compliance.
Setting them
With Helm, first-class values exist for auth, the copilot and agent ingest. For anything without one, use the chart’s escape hatch rather than waiting for a template change:
extraEnv:
- name: KUBEBOLT_FINDINGS_RETENTION_HORIZON
value: "2160h"
- name: KUBEBOLT_AGENT_PROXY_CONNECT_TIMEOUT
value: "45s"
With Docker Compose, copy deploy/.env.example to deploy/.env and edit it.
System environment variables take precedence over the file — it only fills gaps.