Skip to main content

Configuration

Everything that isn’t the database layout or ingress: how settings reach the services, where secrets come from, and how to substitute your own infrastructure.

Application settings

Anything that would otherwise be a bespoke env var — encryption keys, timeouts, log levels, model config — goes under appSettings, and lands as an env var on every service. Each entry takes one of three shapes:
These render to native env: entries — scalars as value:, maps as valueFrom.secretKeyRef or valueFrom.configMapKeyRef. A map that is neither shape fails the install rather than rendering something odd.

Per-service overrides

services.<name>.settings takes the same three shapes and wins over appSettings for the same key:
The defaults ship ENCRYPTION_KEY and AUDIT_HASHCHAIN_SIGNING_KEYS wired to the chart-generated Secret, plus LOG_LEVEL=info — enough for a first install to work with no input. Override them with your own key management when you go to production.

Secrets

The chart generates a Secret named swarmd-generated-credentials at install: Passwords are 24 random alphanumeric characters. On helm upgrade the chart reads the existing Secret via lookup and reuses the values — upgrades do not rotate credentials. The Secret carries helm.sh/resource-policy: keep, so helm uninstall leaves it behind.
Back up encryption-key separately from your database. It encrypts data at rest in registry, relay and teams. A database restore without the matching key leaves you with rows nobody can decrypt.

Supplying your own

Then pre-create a Secret of that name with the keys above. Useful when your platform team owns secret material, or you sync from Vault or OpenBao with an operator.

SMTP

tenant-auth sends email for verification, password reset and team invites. With smtp.enabled: false — the default — every one of those is logged and dropped. Users can register, but nothing arrives.
The install refuses to render with smtp.enabled: true and any of host, from or credentialsSecret missing.
Turning SMTP on also flips Keycloak’s verifyEmail action on. Existing unverified users will be asked to verify at next login — worth knowing before you enable it on a deployment that already has people in it.

Bring your own infrastructure

Every optional component follows the same three-state pattern: enabled: false · enabled: true, deploy: true · enabled: true, deploy: false plus an external block. The chart fails the render if you choose the third and leave a required URL empty.

Bring your own Keycloak

adminSecret holds master-realm admin credentials. Registry, relay, tenant-auth and teams call the Admin API to manage agent service accounts, so this is not optional.
External Postgres forces external Keycloak. keycloak.deploy=true with postgres.deploy=false is unsupported and fails the render — the chart can’t derive host and port from an arbitrary JDBC URL for the Keycloak container.

PII detection

Both analyzers are off by default. With neither enabled, prompts pass through the LLM path unfiltered.
Piiranha cannot be deployed in-cluster from a licensed install. Its analyzer image lives in swarmd/piiranha-analyzer, which is deliberately outside the release set — your licence grants pulls from swarmd/releases/* and swarmd/charts/* only.So piiranha.deploy: true schedules a pod that ImagePullBackOffs, while relay is handed a PIIRANHA_ANALYZER_URL pointing at a Service with no endpoints. Either run the analyzer yourself and use deploy: false with external.url, or point piiranha.image.repository at your own copy.Presidio has no such constraint — its image comes from Microsoft’s public registry, so deploy: true works.

a2a-payments

Off by default, and the only service that genuinely cannot start without configuration: its X402_WALLET_PRIVATE_KEY is @NotBlank-validated with no degraded mode.

Turning services off

Gateway, registry, relay, audit and tenant-auth are the core — disabling any of them gives you a platform that doesn’t work.

Settings that bite later

Some settings don’t block startup but fail the first time a feature is used. The chart can’t enforce them, because the service boots fine without them. Provide them under services.<name>.settings when you enable the feature.

Scaling: core and worker

Every DB-backed service ships as one image that can run three ways, and the chart splits every one of them by default: The worker’s web server stays up so health probes work, but the Service never routes traffic to it. Worker sizing falls back to the service’s own replicaCount / resources when left empty.
Why this is the default. In the combined topology, scaling the API to N replicas also runs N copies of every @Scheduled job — outbox drainers and monitor evaluators racing each other, which is a data problem rather than a performance one. Splitting also stops a slow scheduler starving the API’s thread pool, and takes Flyway out of pod startup so a long migration can’t trip readiness on every replica at once.

Collapsing a service back

Worth doing on a laptop, where the extra pod per service costs more than the isolation buys you. Setting it on every service takes the default install from 18 Deployments to 11.
Don’t run a collapsed service at replicaCount > 1. That is exactly the scheduler-duplication case the split exists to prevent.

Observability

Prometheus scrape annotations land on every service pod; tracing points the OTLP exporter at your collector.

Verifying a change before you apply it

The chart’s validation runs during template, so a bad combination fails here — before it touches your cluster.

Next

Presets

Tested values files that combine all of this.

Databases

Layouts, external Postgres, ClickHouse and backups.