Helm values reference

Every Helm chart value, what it does, and the recommended setting.

The chart is at deploy/helm/simian/. Reference for every value lives in the chart’s values.yaml — that file has long inline comments explaining each setting and is the canonical source. This page summarizes by category.

For installs that want a known-good starting point rather than the chart defaults, layer the recommended overlay on top.

Image

ValueDefaultNotes
image.repositoryghcr.io/go-steer/simian-agentPublished by the release workflow on every v* tag.
image.tag"" (falls back to Chart.AppVersion)Pin explicitly for production so chart upgrades don’t silently change the running binary.
image.pullPolicyIfNotPresent

Eligibility

ValueDefaultNotes
eligibleNamespaces[]Static allowlist. When empty, the controller falls back to annotation-based lookup (simian.chaos/eligible="true"), which is the preferred mode for installations using simian arena create.

Provisioner subsystem (M2 Part A)

ValueDefaultNotes
provisioner.enabledtrueShips the simian-provisioner SA + ClusterRole + ValidatingAdmissionPolicy backstop. Disable for installs where arenas are managed by an operator using their kubeconfig (no in-cluster provisioner).

LLM provider

ValueDefaultNotes
llm.providergeminigemini or stub.
llm.model"" (default gemini-2.5-pro)
llm.vertex.enabledtrueVertex via Workload Identity (production-recommended).
llm.vertex.project""Required while llm.vertex.enabled: the GCP project whose Vertex AI the controller calls. The chart refuses to render without it.
llm.vertex.locationus-central1
llm.apiKey.enabledfalseAlternative to Vertex; mounts a Kubernetes Secret.
llm.apiKey.secretRef / secretKeysimian-llm / geminiApiKey

Executor safety policy

ValueDefaultNotes
executor.durationCeiling15mHard cap per fault. Recommended overlay: 5m.
executor.permittedTiers[namespace, node]Blast-radius tiers permitted: namespace, node, external. Renders one --permitted-tiers= arg per entry. Recommended overlay: [namespace] (opt-in to node tier per install).
executor.maxConcurrentFaults0 (no cap)Total leased faults across namespaces. Recommended overlay: 1.
executor.minCooldown0sPer-namespace cooldown. Recommended overlay: 60s.
executor.recentFaultsCapacity100Bounded ring backing the get_recent_faults MCP tool.

How permittedTiers fails

This is the one value an operator sets to make the policy narrower — usually to keep node-level chaos off a cluster they care about — so its failure modes are deliberately loud rather than convenient.

  • An unrecognised tier name stops the controller starting, with --permitted-tiers: unknown blast-radius tier "...". A typo that fell back to the default would silently restore the very tier the operator was removing.
  • An empty list means “use the built-in default” (namespace, node), not “permit nothing”. The chart renders no flag at all in that case, and a flag the operator never set must not be a capability change.
  • --set executor.permittedTiers={} is not an empty list. Helm’s --set turns it into a one-element list holding the empty string, which renders --permitted-tiers= and stops the controller with an unknown-tier error. Use --set-json 'executor.permittedTiers=[]', or set it in a values file.

autonomous.maxSeverityPerCycle is validated the same way, at startup rather than in the loop: an unparseable cap makes every planned step ineligible, which otherwise looks exactly like a planner that produced nothing.

Topology + SUT

ValueDefaultNotes
topology.resync30sInformer resync interval. Recommended overlay: 60s for prod (lower API server load).
sutInController.enabledfalseRequired for simian sut deploy --use-controller (the in-controller SUT path). Recommended overlay: true. Covers only the namespaces in eligibleNamespaces; for arenas made with simian arena create, pass --sut-in-controller there (or sut deploy --create-arena --use-controller, which does it for you).
sutInjection.envoyFaultsfalseWhether to inject the Envoy fault sidecar into SUT Deployments. Off by default because the iptables interception breaks gRPC kubelet probes — see Known limitations. Only enable for SUTs whose probes are HTTP-only or TCP-only.

Autonomous mode

The autonomous.* values are the install’s settings. With the web UI behind IAP, ui.iap.admins may change them at runtime within the executor.* limits; their changes are kept in the simian-runtime-config ConfigMap and win over these until reverted from the page.

ValueDefaultNotes
autonomous.enabledfalseWhen true, the controller runs the autonomous planning loop.
autonomous.namespaces[]Required when enabled: true. Arena namespaces the loop targets.
autonomous.cycleInterval5mRecommended overlay: 10m (slower; more time to observe).
autonomous.maxFaultsPerCycle3Recommended overlay: 1 (one fault per cycle to start).
autonomous.maxSeverityPerCyclenamespaceHighest blast tier the loop will apply.
autonomous.hypothesisHint""Optional soft preference passed to the LLM. Use this to bias toward newer engines (network-policy, envoy-fault).

Audit trail

ValueDefaultNotes
audit.file.enabledtrueAlso append audit events to a JSON-lines file (--audit-file). Stdout logging is unaffected.
audit.file.path/var/lib/simian/audit.jsonlIts directory is the mount point for the audit volume.
audit.file.maxBytes104857600Past this the file rotates to <path>.1; two generations are kept.
audit.file.persistence.enabledtrueKeep the file on a PVC (simian-audit, kept on uninstall) rather than an emptyDir, and switch the Deployment to strategy: Recreate. Needs a default StorageClass, or storageClass below. Default since chart 0.1.10.
audit.file.persistence.size1Gi
audit.file.persistence.storageClass""Empty uses the cluster default.

With persistence off, the file is on an emptyDir, which survives container restarts but not the pod being deleted or rescheduled; persistence keeps the trail past both. At start-up the controller reads the file for faults the previous process applied and never ended. A fault still before its deadline is adopted (lease.adopted, reason untracked-after-restart): it counts against --max-concurrent-faults and the health gate, and is cleared at its deadline as if this process had applied it. Every other one gets a lease.expired event with the same reason, so a restart no longer leaves faults with no end on record. It then lists the faults still running in the arenas from the objects the drivers left (lease.adopted, found_in: cluster) and adopts any the file did not cover — all of them when the file was lost with an emptyDir. A fault with no object of its own (envoy-fault) can only be adopted from the file. Read the trail back with simian audit export.

On GKE the controller’s stdout already reaches Cloud Logging, so the audit events are retained there as well; the file is what you have on clusters without a log pipeline, and what simian audit export reads directly.

Web UI

ValueDefaultNotes
ui.enabledtrueServe the web UI at /ui/, with its JSON API and event stream under /api/, on ui.port. Only false renders a flag (--ui=false).
ui.port8082The UI’s port, on the container and the Service. A value other than 8082 renders --ui-addr.
ui.name""How this controller is labelled in a UI that watches several Simians (e.g. its cluster). Renders --ui-name when set.
ui.allowedOrigins[]Other pages that may call this controller from the browser with the user’s credentials — another Simian’s UI or the standalone UI — e.g. https://simian-2.example.com. Only these get CORS headers; a preflight from them is answered before IAP is checked, and the real request still needs IAP’s assertion and, for writes, X-Simian-UI. Behind IAP the load balancer must also let preflights through. Renders --ui-allowed-origins when set.
ui.controllers[]Other Simians this controller’s page offers to watch, as {name, url} with url the origin of each controller’s UI, e.g. {name: simian-2, url: https://simian-2.example.com}. Each of them must list this page’s origin in its ui.allowedOrigins; users sign in to each once, and can add more in the page. An entry without a name or url fails to render. Renders --ui-controllers when set.
ui.authnonenone: read-only, for a port-forward. iap: behind Identity-Aware Proxy; every request must carry IAP’s assertion, and ui.iap.writers may inject and clear faults. Needs ui.iap.audience or ui.iap.projectNumber.
ui.iap.audience""The backend service’s audience, /projects/NUMBER/global/backendServices/ID, checked exactly.
ui.iap.projectNumber""Without an exact audience: accept any backend service in this project.
ui.iap.writers[]Who may inject and clear faults from the page: emails, or domain:example.com. Empty: nobody. Refused without ui.auth=iap.
ui.iap.admins[]Who may also turn autonomous mode on and off and configure it (within the executor limits), pause and resume it, and clear all faults, from the Configuration panel. Kept in the simian-runtime-config ConfigMap across restarts and upgrades. Refused without ui.auth=iap.
The defaults render no UI flags, so the chart still starts a 0.2.x image; ui.auth=iap and a non-default port need v0.3.

Metrics

ValueDefaultNotes
metrics.enabledtrueServe Prometheus metrics on /metrics (--metrics-addr), with a metrics container and Service port and the prometheus.io/* scrape annotations on the pod.
metrics.port9090
metrics.podMonitoring.enabledfalseCreate a PodMonitoring for GKE Managed Service for Prometheus.
metrics.serviceMonitor.enabledfalseCreate a ServiceMonitor for prometheus-operator. Needs its CRD.

What the metrics are, with example queries and alerts: Seeing what Simian is doing.

MCP server

ValueDefaultNotes
mcp.port8081
mcp.serviceTypeClusterIP

Resources + security

ValueDefaultNotes
resources.requests.cpu / .memory100m / 128MiRecommended overlay: 200m / 256Mi.
resources.limits.cpu / .memory500m / 512MiRecommended overlay: 1000m / 1Gi (prevents OOM during LLM bursts).
podSecurityContextrestricted-PSS-compatiblerunAsNonRoot: true, runAsUser: 65532, fsGroup: 65532 (so the controller can write a PVC-backed audit volume), seccompProfile.type: RuntimeDefault.