Configuration
Delphi configuration is layered. Each source has a different audience, lifecycle, and blast radius. This page is the map: it explains where each kind of setting lives, who can change it, and how it propagates. The deeper pages in this section drill into the manifest schema (vars.yaml), the resolution algorithm (fetch-env.sh), and a few concrete patterns (managed database secrets, runtime composition).
Sources at a glance
| Source | Audience | Lifecycle | Examples |
|---|---|---|---|
| Code defaults | Engineers | Released with the image. | Built-in defaults for ports, timeouts, log levels. |
Manifest defaults (vars.yaml) | Operators | Released with the bundle. | LOG_LEVEL=info, REDIS_PORT=6379, WORKER_CONCURRENCY=5. |
Bootstrap .env | Cloud-init / operators | Written at instance creation; mutable on the host. | ENVIRONMENT, HOSTNAME, NAMESPACE, ECR_REGISTRY, ECR_TAG, AWS creds. |
| AWS SSM Parameter Store | Operators | Mutable; pulled at every restart. | Service URLs, ports, non-secret config, feature toggles. |
| AWS Secrets Manager | Operators | Mutable; pulled at every restart. | DB credentials, JWT keys, provider API keys, TLS PEM material. |
External SM secret (secret.arn_from) | Operators / managed-DB | Pulled at every restart. | RDS master user / password — a JSON secret AWS owns. |
Runtime composition (compose.template) | — | Built at every restart from other vars. | DATABASE_URL from ${DATABASE_USERNAME}:${DATABASE_PASSWORD}@${DATABASE_HOST}…. |
Postgres PlatformSetting | Admins (TelWeb) | Mutable at runtime via TelWeb / API. | Default models, billing toggles, registration policy. |
| TelWeb settings UI | Team users | Mutable at runtime. | Per-team brand, providers, voices, agent prompts, app overrides. |
| Redis | Runtime | Ephemeral / cached. | Active call state in Kamailio, TTS-cache pointers, leader election. |
The first six are boot-time sources — they decide what the container starts with. The last three are runtime sources that the platform mutates in operation.
How the boot-time sources combine
Every Compose service follows the same flow on every restart:
fetch-env.sh reads each service's vars.yaml and walks the resolution order:
- Bootstrap —
source: localvariables come from/opt/deployment/.env. - SSM — every parameter under
/${NAMESPACE}/${SERVICE}/is pulled. - Secrets Manager — every secret under
${NAMESPACE}/${SERVICE}/*is pulled and its JSON keys are merged. - External SM secret (
secret.arn_from) — a per-variable lookup against another secret named by a bootstrap variable (RDS master secret pattern). - Manifest defaults —
default:is used if everything else is empty. compose.template— built last from already-resolved variables (URL composition, etc.).
After step 6, fetch-env.sh validates that every required: true (and every required_when: whose condition is true) has a value. Missing? Bail before Compose touches the host.
For the full algorithm, the namespace conventions, and the concrete gotchas (precedence, encoding), see Environment resolution.
Picking the right source for a new variable
| If your value is… | Put it in… | vars.yaml flag |
|---|---|---|
| A constant that ships with the image. | Code default. | — |
| A safe default operators rarely override. | vars.yaml default: | — |
| Set at instance creation, describes infrastructure. | Bootstrap .env | source: local |
| Per-environment, non-secret, set rarely. | AWS SSM Parameter Store | (none — the default) |
| A secret, rotated. | AWS Secrets Manager | sensitive: true |
| A credential AWS already manages (RDS, etc.). | External SM secret | secret: { arn_from, type, key } |
| Built from other variables at runtime (URL, DSN). | compose.template | compose: { template, encode } |
| Mutable by admins at runtime, no deploy. | PlatformSetting via TelWeb | — |
| Per-team, end-user configurable. | Team domain tables via TelWeb | — |
| Ephemeral runtime state. | Redis | — |
A worked end-to-end example for the managed-RDS case (an external secret + a compose.template building DATABASE_URL) is on Managed database secrets.
Changing a value safely
The general loop is the same regardless of source:
- Update the value at the source (SSM, SM, TelWeb).
- Re-resolve env on every consuming service:
cd /opt/services/<service> && ./update.sh --restart-only. - Verify in the service's logs and in SigNoz.
Specifics:
- SSM (non-sensitive):
aws ssm put-parameter --name "/<namespace>/<service>/<VAR>" --value "..." --type String --overwrite. Thenupdate.sh --restart-only. - Secrets Manager (sensitive):
aws secretsmanager put-secret-value --secret-id "<namespace>/<service>/secrets" --secret-string '{...}'(the whole JSON object). Thenupdate.sh --restart-only. - TelWeb-driven (
PlatformSetting, team settings): change in the TelWeb UI. Takes effect on next read; no restart. - Bootstrap
.env: edit/opt/deployment/.envon the host; restart. Also update your provisioning source so a recreated instance comes up with the same values.
The update.sh flow (deployment manager, shared across all services) handles --ecr-tag, --config-ref, --restart-only, --dry-run, and --yes for non-interactive runs. Full reference on init.sh and update.sh.
Discoverability
- Every variable consumed by a service is declared in that service's
vars.yaml— that file is the source of truth. The Configuration tab on each service operations page lists the highlights with<EnvVar>/<EnvVarTable>callouts. - The cross-service environment variable index summarizes the variables that recur across the stack.
- The delphi-setup CLI applies idempotent registry steps for first-use, updates, feature-flag defaults, and platform settings.
- On any host:
common/show-env.sh --service <name>prints expected variables;common/show-env.sh --allprints the full grid.