Helm Values Reference
Full reference for values.yaml. Pass overrides via --set key=value or a values.yaml file.
helm upgrade --install kubemanta oci://registry.kubemanta.com/kubemanta/charts/stable/kubemanta \
--version 1.0.0 \
-n kubemanta-system --create-namespace \
-f my-values.yaml
Global
| Value |
Default |
Description |
global.hostname |
"" |
Public hostname for the UI. When set, triggers Ingress creation + CORS auto-config. |
global.tls |
true |
Enable HTTPS on the Ingress. |
global.tlsProvider |
"" |
TLS mode: gcp-managed · acm · cert-manager · manual. Auto-detected from ingressClassName when empty. |
global.tlsSecret |
"" |
Name of an existing TLS Secret (manual mode). |
global.certManagerIssuer |
letsencrypt-prod |
cert-manager ClusterIssuer name. |
global.installCertManager |
false |
Install cert-manager as a subchart + create a Let's Encrypt ClusterIssuer automatically. Requires certManagerIssuerEmail. |
global.certManagerIssuerEmail |
"" |
Email for Let's Encrypt ACME registration (required when installCertManager=true). |
global.ingressClassName |
"" |
Ingress class: gce · alb · traefik, or any installed class. |
global.staticIpName |
"" |
GCP only: name of a reserved global static IP to pin the GCE load balancer. |
global.acmCertificateArn |
"" |
AWS only: ACM certificate ARN for ALB TLS termination. |
global.pullToken |
"" |
GHCR PAT fallback (internal/dev only). Use license.key for all customer installs. |
License
| Value |
Default |
Description |
license.key |
"" |
Per-cluster license key. Stored in a Secret; auto-creates the registry pull secret for registry.kubemanta.com. |
license.accountId |
cf6c7851-... |
Keygen vendor account ID (pre-set, do not change). |
license.apiUrl |
https://api.keygen.sh |
License service URL (override for self-hosted Keygen). |
RBAC
| Value |
Default |
Description |
rbac.allowWrites |
false |
Grant the agent write verbs: pod restart/delete, deployment scale, namespace create, pod exec. Read-only without this. |
rbac.readSecrets |
false |
Grant the agent get/list on Secrets cluster-wide. Off by default — AI/MCP/terminal can otherwise read every Secret during diagnosis. Enable only if Secret inspection is needed. |
Security
| Value |
Default |
Description |
security.adminPassword |
"" |
Admin password, seeded at install (the agent sets it on first startup — there is no first-login setup, which is blocked from a public URL by design). Empty = auto-generate a stable one; retrieve it with kubectl get secret <release>-admin -n <ns> -o jsonpath='{.data.password}' \| base64 -d. The seed never overwrites an already-set password (a later km-reset-pw or Admin change survives upgrades). Min 8 chars. |
~~security.apiKey~~ |
— |
Removed. Programmatic access and the MCP server now use per-user API keys, created in Admin → Users. There is no shared secret to configure. See Security model. |
security.appArmorProfile |
runtime/default |
AppArmor profile applied to every container. Relax knob for policy-enforced clusters: set unconfined to emit no AppArmor annotation (e.g. if a terminal user's tooling needs syscalls the default profile blocks), or localhost/<name> to pin a custom loaded profile. |
security.cookieSecure |
auto |
Session-cookie Secure attribute. auto computes it from the exposure (true when serving HTTPS via Ingress, false for port-forward / HTTP-only). Set an explicit true/false to override — required (true) when you serve HTTPS through your own edge with no hostname set. |
security.aiRateLimitPerMin |
10 |
Per-session AI request rate limit. |
security.discoveryRateLimitPerMin |
60 |
K8s API discovery rate limit. |
security.requireApproval |
false |
Force approval for all AI write operations (overrides agent mode). |
security.viewerPassword |
"" |
Optional viewer password → read-only "viewer" role (bcrypt hash or plaintext). Empty = single-admin mode. |
security.encryptionAtRest |
true |
Encrypt cloud/Helm/integration/SSO credentials in SQLite with AES-256-GCM. A random key is generated on first install and preserved across upgrades (helm.sh/resource-policy: keep). |
security.encryptionKey |
"" |
BYO encryption key (raw 16/24/32 bytes or base64). Empty = auto-generated. |
security.blockImds |
true |
NetworkPolicy that blocks access to the cloud Instance Metadata Service (169.254.169.254) from all pods in kubemanta-system. |
security.trustedProxyCidrs |
"" |
Comma-separated CIDRs of proxies/LBs allowed to set X-Forwarded-For. Empty = trust nothing (always use the socket peer). Required in service-only mode. |
security.sessionIdleTimeout |
1800 |
Sliding session idle-timeout in seconds (every authenticated request extends it). 0 disables the idle check; the absolute 24h TTL always remains the hard ceiling. Runtime-editable in Admin → Access Control. |
Hardened by default (OPA Gatekeeper / restricted clusters)
Every container ships non-root with a read-only root filesystem, dropped capabilities, RuntimeDefault seccomp, an AppArmor annotation, projected ServiceAccount tokens, and CPU + memory limits — no profile flag to flip. On a policy-enforced cluster you must allowlist the KubeManta images (registry.kubemanta.com/kubemanta/*, the python:3.12-alpine preflight image, and aquasec/trivy:* for self-scan). security.appArmorProfile and terminal.readOnlyRootFilesystem are the two relax knobs. See Restricted / policy-enforced clusters.
Container scanning
| Value |
Default |
Description |
security.scanning.enabled |
false |
Grants the reader role get/list on CRDs (operator detection) + get/list/watch on trivy-operator report CRDs, and gates the self-scan: left at false, POST /security/scan is refused with a 403. It previously only withheld RBAC while the scan Job still ran through expert-exec's own token, so an install with it off could still deploy Trivy and pull the CVE database. |
security.scanning.mode |
auto |
Scan-source seed: auto · operator (BYO, hard-disables self-scan) · self. Overridden at runtime by the admin scanner_source setting. |
security.scanning.retentionDays |
90 |
How long scan history is kept — scan_runs, vuln_findings and posture_findings, pruned by age on the insert path. |
security.scanning.selfScan.image |
aquasec/trivy:0.72.0 |
Trivy image for the self-scan Job. |
security.scanning.selfScan.cache.enabled |
true |
Reuse a PVC for Trivy's CVE database between scans. Off, every scan re-downloads ~103 MB (measured 73s cold vs 33s warm). |
security.scanning.selfScan.cache.size |
2Gi |
Size of that cache PVC. |
security.scanning.selfScan.resources |
250m/256Mi req, 1/1Gi limit |
Self-scan Job resources. |
selfScan.waitSecs was removed
POST /security/scan no longer waits for the scan. It launches the Job and
returns {"status": "running", "job_name": ...} immediately; results are
collected by a background sweep and by GET /security/scan/{id}. The old
bounded wait defaulted below the time a real cold scan takes, so timed_out
was the common outcome for a Job that succeeded moments later. Setting
selfScan.waitSecs now has no effect and can be dropped from your values.
Self-scan additionally requires expertMode.enabled=true (the Job is created via expert-exec). See Container Scanning.
Metrics
| Value |
Default |
Description |
metrics.kubeletScrape.enabled |
false |
Grant the reader ClusterRole get on nodes/proxy (read-only) so the agent's metrics sampler can scrape each node's kubelet cadvisor through the API-server proxy. This exists solely to light up the Metrics tab's network bandwidth trends with zero Prometheus setup — metrics-server exposes no network metrics. CPU/memory always come from metrics-server and work without this flag; only bandwidth stays empty when it's off. Exposed to the agent as METRICS_KUBELET_SCRAPE. |
nodes/proxy reaches kubelet handlers, which is why it stays off by default and is granted only on explicit opt-in. Prefer your own Prometheus instead? Leave this off and set the metrics source to prometheus (PUT /metrics/source) — Admin → Observability → Generate scrape config emits the RBAC + prometheus.yml your Prometheus needs. See Metrics.
Agent
| Value |
Default |
Description |
agent.prometheusUrl |
"" |
Prometheus API URL (e.g. http://prometheus-server.monitoring.svc:9090). Enables the query_metrics PromQL tool. Seed only — a Prometheus source saved in Admin → Observability takes precedence at runtime. |
agent.alertInvestigation |
false |
Auto-investigate critical alerts with the AI agent and post results to Slack. |
agent.alertMinSeverity |
critical |
Minimum severity to trigger autonomous investigation: critical · high · medium. |
agent.agentApiKey |
"" |
Anthropic API key for autonomous alert investigations. Stored in a Secret. |
agent.anthropicApiKey |
"" |
Server-side default Anthropic key for the agent's AI loop (stored in a Secret). Never exposed to PTY terminal sessions — the terminal is BYO-LLM (ANTHROPIC_API_KEY is stripped from the PTY env; Claude Code authenticates via its own claude OAuth login). |
agent.blastRadiusLimit |
5 |
Max write operations per agent session. Sessions that hit this limit block further write tools. |
agent.circuitBreakerThreshold |
3 |
Number of consecutive write-tool failures before the circuit breaker trips. |
agent.circuitBreakerResetSecs |
300 |
Seconds before the circuit breaker auto-resets. |
Expert Mode
| Value |
Default |
Description |
expertMode.enabled |
false |
Provision the separate kubemanta-expert-exec pod holding the cluster-admin token (used by the terminal and Helm/agent write ops). Default off — the agent pod never mounts this token. |
expertMode.image / expertMode.tag |
"" |
Override image/tag for the expert-exec pod (defaults to image.repository/tag). |
expertMode.resources |
500m/256Mi limit, 100m/128Mi req |
expert-exec pod resources. |
Terminal
| Value |
Default |
Description |
terminal.image / terminal.tag |
"" |
Override image/tag for the terminal sidecar (defaults to agent image). |
terminal.readOnlyRootFilesystem |
true |
Read-only root filesystem on the terminal sidecar (hardened). Relax knob for the one container where users run arbitrary commands: set false if a user's tooling insists on writing outside $HOME and /tmp (both stay writable regardless). Every other container's root filesystem is read-only unconditionally. |
terminal.idleTimeoutSecs |
1800 |
Terminate a terminal session with no PTY I/O for this many seconds and reclaim its slot/RAM. 0 disables the reaper. |
terminal.resources.limits.cpu |
1000m |
CPU limit for the terminal sidecar. |
terminal.resources.limits.memory |
4Gi |
Memory limit for the terminal sidecar. |
Enterprise SSO
| Value |
Default |
Description |
sso.publicUrl |
"" |
Optional seed for the SSO wizard's external_base_url (ACS/EntityID base). Only pre-fills the wizard; the admin-entered config is authoritative. See Enterprise SSO. |
Persistence
| Value |
Default |
Description |
persistence.enabled |
true |
Create a PVC for agent data (SQLite DB, terminal home, Helm cache). |
persistence.size |
1Gi |
PVC size. |
persistence.storageClass |
"" |
StorageClass name. Empty = cluster default. |
persistence.mountPath |
/data/kubemanta |
Mount path inside the agent container. |
A+ SQLite → S3 replication (Litestream)
Optional continuous replication of the SQLite DB to object storage, so the pod survives node/PVC loss. Default off — a default install is unchanged. See Disaster Recovery.
| Value |
Default |
Description |
persistence.replication.enabled |
false |
Enable Litestream WAL replication. With persistence.enabled=false the DB dir becomes an emptyDir, a restore init-container rebuilds the DB on boot, and a sidecar ships the WAL continuously. |
persistence.replication.bucket |
"" |
Required when enabled. Target bucket. |
persistence.replication.path |
kubemanta-db |
Key prefix within the bucket. |
persistence.replication.region |
us-east-1 |
Bucket region. |
persistence.replication.endpoint |
"" |
Set for MinIO / other S3-compatible stores. |
persistence.replication.forcePathStyle |
false |
Set true for MinIO / path-style endpoints. |
persistence.replication.credentialsSecret |
"" |
Secret with AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. Empty = use IRSA / workload identity. |
persistence.replication.image |
litestream/litestream:0.3.13 |
Litestream image. |
Warning
Enabling this renders correctly but is not proven until you run an attended kill-pod failover test against your real object store. Never host the bucket in the cluster you are observing.
Alerting
| Value |
Default |
Description |
alerting.webhookUrl |
"" |
Webhook URL for alert delivery. |
alerting.slackWebhookUrl |
"" |
Slack incoming webhook URL. |
alerting.pagerdutyRoutingKey |
"" |
PagerDuty Events API v2 routing key. |
alerting.watchIntervalSecs |
60 |
Alert rule evaluation interval. |
alerting.dedupeWindowSecs |
300 |
Cooldown window per rule+resource to suppress repeated firings. |
Audit
| Value |
Default |
Description |
audit.webhookUrl |
"" |
Forward every audited request to an HTTP collector (SIEM / Splunk). Disabled when empty. |
audit.webhookToken |
"" |
Optional Bearer token for the audit webhook. Stored in the agent Secret. |
audit.worm.enabled |
false |
Tamper-evident off-box WORM export: write every audit row as one object into an Object-Lock S3 bucket (closes the trim-newest-rows gap the in-DB hash-chain can't). See Activity & Audit. |
audit.worm.bucket |
"" |
Target bucket (Object Lock + default retention required). |
audit.worm.prefix |
audit |
Key prefix. |
audit.worm.region |
us-east-1 |
Bucket region. |
audit.worm.endpoint |
"" |
Set for MinIO / S3-compatible; empty = real AWS S3. |
audit.worm.credentialsSecret |
"" |
Secret holding S3 credentials. Empty = IRSA / workload identity. |
The in-pod audit_log is always hash-chained regardless of this block — verify it with GET /audit/verify-chain.
Cloud provider
| Value |
Default |
Description |
aws.region |
"" |
AWS region override (auto-discovered from topology.kubernetes.io/region node label when empty). |
gcp.region |
"" |
GCP region override (auto-discovered). |
azure.location |
"" |
Azure location override (auto-discovered). |
Namespace control
| Value |
Default |
Description |
tenantNamespaces |
[] |
Restrict KubeManta to these namespaces. Empty = auto-discover all non-system namespaces. |
blocklist |
see values.yaml |
Namespaces always hidden. Includes kube-system, kube-public, kubemanta-system, istio-system, cert-manager, argo, argocd, and others. |
Image and resources
| Value |
Default |
Description |
replicaCount |
1 |
Agent replicas. The agent is stateful (RWO PVC) — keep at 1 unless your storage is RWX. |
image.repository |
registry.kubemanta.com/kubemanta/kubemanta-agent |
Agent image. |
image.tag |
latest |
Agent image tag. |
image.pullPolicy |
Always |
Image pull policy. |
resources.requests.cpu |
250m |
Agent CPU request (for scheduling). |
resources.requests.memory |
512Mi |
Agent memory request. |
resources.limits.memory |
512Mi |
Agent memory limit (== request, so the working set is reserved and bounded). No CPU limit by default — a hard CPU cap throttles the async event loop (a 250m cap caused /healthz >1s + overview timeouts). Use priorityClassName for eviction protection instead. |
ui.image.repository |
registry.kubemanta.com/kubemanta/kubemanta-ui |
UI image. |
ui.image.tag |
latest |
UI image tag. |
ui.resources.limits.cpu |
250m |
UI CPU limit. |
ui.resources.limits.memory |
256Mi |
UI memory limit. |
Sizing presets
The defaults are the Medium tier (≤ ~1,000 pods). Apply a preset with a second -f: -f helm/values-small.yaml (≤200 pods, mem 256Mi) or -f helm/values-large.yaml (≤5,000 pods, mem 1Gi). All-cluster list calls are paginated, so memory doesn't scale with cluster size.
Scheduling & availability
| Value |
Default |
Description |
priorityClassName |
"" |
Makes the agent harder to evict under node pressure. For production set an existing high-priority class (e.g. system-cluster-critical). Pair with Guaranteed/reserved memory. |
updateStrategy |
{} |
Empty = auto: Recreate while the agent holds a ReadWriteOnce PVC (a rolling update would deadlock on Multi-Attach), RollingUpdate once persistence is off. Override only if your storage is ReadWriteMany. |
podDisruptionBudget.enabled |
false |
Off by default: at replicaCount: 1 a PDB cannot provide availability and maxUnavailable: 0 will block node drains. Enable once you run replicas > 1, or to deliberately make the single replica un-evictable by the autoscaler. |
podDisruptionBudget.maxUnavailable |
0 |
Used when the PDB is enabled. |
podDisruptionBudget.minAvailable |
"" |
Set (e.g. 1) to use minAvailable instead of maxUnavailable. |
Exposure
| Value |
Default |
Description |
ingress.enabled |
true |
false = service-only mode: render only the agent + UI Services (no Ingress/BackendConfig/ManagedCertificate) so you can front KubeManta with your own edge/LB/Gateway/WAF. See Access Control. |
service.type |
ClusterIP |
Agent Service type: ClusterIP · NodePort · LoadBalancer. |
service.port |
8080 |
Agent Service port. |
service.annotations |
{} |
Pass-through annotations (e.g. internal-LB). |
ui.service.type |
ClusterIP |
UI Service type. |
ui.service.nodePort |
"" |
Pin the NodePort (30000–32767) when type=NodePort. |
ui.service.annotations |
{} |
Pass-through annotations for the UI Service. |
Service-only mode requires security.trustedProxyCidrs
When you front KubeManta yourself, you must set security.trustedProxyCidrs to your edge's egress CIDR(s) — otherwise every request is attributed to the proxy IP, breaking audit attribution and letting one client's failed logins auto-ban the shared edge IP for everyone. The terminal WebSocket path /api/agent/terminal/ws must reach the agent Service directly; all other traffic goes to the UI Service.