Deployment
Server configuration
Reference for every envoy-server.yaml key: server, store, runs, executor, ai, auth, secrets, branding, and boot validation.
Server configuration
The Envoy control plane reads one YAML file at startup. loadServerConfig in src/server/config.ts parses it, resolves environment variables, merges it over built-in defaults, and validates it before the server starts:
envoy server --config /path/to/envoy-server.yamlDocker deployments set ENVOY_CONFIG_PATH and let the image entrypoint generate this file on first boot from environment variables. After first boot the persisted YAML is authoritative — changing an environment variable does not regenerate it. See Docker.
Annotated example
server:
port: 3000
host: 0.0.0.0
cors_origin: https://envoy.example.com
store:
type: sqlite
path: /app/state/envoy-server.db
runs:
log_store: db
log_dir: ./logs/runs
max_concurrent: 50
retention:
max_age_days: 30
delete_runs: false
cleanup_cron: "0 3 * * *"
branding:
app_name: Envoy
logo_url: ""
icon_url: ""
favicon_url: ""
scheduler:
max_inflight_age_minutes: 60
connectors:
upload_max_bytes: 26214400
encryption_key: ${ENVOY_ENCRYPTION_KEY}
tasks_dir: ./tasks
jobs_dir: ./jobs
executor:
type: http
config:
callback_url: http://control-plane:3000
executor_key: ${ENVOY_EXECUTOR_KEY}
auth:
totp_required: true
providers:
microsoft:
client_id: ${MICROSOFT_CLIENT_ID}
client_secret: ${MICROSOFT_CLIENT_SECRET}
tenant_id: common
secrets:
default: azure_key_vault
azure_key_vault:
vault_url: https://my-vault.vault.azure.net/
name_prefix: envoy-
ai:
provider: anthropic
api_key: ${ANTHROPIC_API_KEY}How the config is loaded and validated
loadServerConfig runs these steps in order. Any failure throws and the server does not start.
- The file must exist, otherwise:
Server config file not found: <path>. - The YAML is parsed and every
${VAR}reference is replaced with the value of that environment variable. A missing variable fails the boot. Tokens of the form${secret://...}are left alone at this stage (see below). - The result is deep-merged over the built-in defaults, so you only write the keys you change.
encryption_keymust be present:encryption_key is required in server config. Set ENVOY_ENCRYPTION_KEY env var or provide it directly.The key must be valid base64 that decodes to 32 bytes; otherwise boot fails withEncryption key "default" is not valid base64. Generate one with: openssl rand -base64 32or the 32-byte variant of that message.- Cross-field checks run, each with a verbatim error:
mssql config is missing required fields: <fields>—mssqlis present but lacksserver,database,user, orpassword.runs.log_store is "mssql" but no mssql config section is providedruns.log_store is "victoria_logs" but no victoria_logs.url is providedstore.type is "mssql" but no mssql config section is providedstore.type is "postgres" but no postgres.connection_string is providedruns.log_store is "postgres" but no postgres.connection_string is providedsecrets.default must be one of: sqlite, mssql, postgres, azure_key_vault (got "<value>")secrets.default is "azure_key_vault" but no secrets.azure_key_vault section is providedsecrets.default is "mssql" but the state store is not mssql(and the equivalent messages forsqliteandpostgres)secrets.azure_key_vault.vault_url is required
Environment substitution
Any YAML value may reference an environment variable:
encryption_key: ${ENVOY_ENCRYPTION_KEY}
postgres:
connection_string: ${ENVOY_POSTGRES_CONNECTION_STRING}Secret URIs
After environment substitution, values of the form ${secret://<provider>/<handle>} are resolved through the registered secret providers:
mssql:
password: ${secret://azure_key_vault/envoy-prod-mssql-pwd}Referencing a provider that is not registered fails with Cannot resolve "<token>": SecretProvider "<provider>" is not registered. See Hardening, RBAC, and secrets for the provider model.
server
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
port |
number | No | 3003 |
HTTP listen port. The Docker entrypoint generates configs with port 3000 unless ENVOY_PORT overrides it. |
host |
string | No | 0.0.0.0 |
Listen address. |
cors_origin |
string | No | * |
Allowed browser origin. Restrict to the real application origin in production. |
store
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
type |
sqlite | mssql | postgres |
No | sqlite |
State backend for users, connectors, tasks, jobs, runs, and triggers. |
path |
string | No | ./envoy-server.db |
SQLite database file path. Used when type is sqlite. |
type: mssql requires the top-level mssql section; type: postgres requires postgres.connection_string. See Backups and upgrades for what to back up per backend.
logging
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
level |
string | No | — | Optional log level string. |
file |
string | No | — | Optional log file path string. |
Both keys are declared optional in ServerConfig and default to an empty section. Structured server logs are written to logs/envoy.log by the pino logger regardless.
runs
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
log_store |
file | db | mssql | postgres | victoria_logs |
No | file |
Where per-run task logs are persisted. |
log_dir |
string | No | ./logs/runs |
Directory for the file log store. |
max_concurrent |
number | No | 50 |
Maximum runs the control plane manages at once. 0 means unlimited. |
retention.max_age_days |
number | No | 30 |
Terminal runs older than this are eligible for cleanup. 0 or less disables scheduled cleanup. |
retention.delete_runs |
boolean | No | false |
false deletes only logs; true also deletes run rows and metrics. |
retention.cleanup_cron |
string | No | 0 3 * * * |
Cron schedule for the cleanup job. |
Retention behavior is covered in Retention; the victoria_logs store in VictoriaLogs.
branding
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
app_name |
string | No | Envoy |
Application name shown in the UI and browser title. |
logo_url |
string | No | "" |
Full logo URL. Empty falls back to the product default. |
icon_url |
string | No | "" |
Compact icon URL. |
favicon_url |
string | No | "" |
Browser favicon URL. |
See Branding.
scheduler
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
max_inflight_age_minutes |
number | No | 60 |
Age after which a still-in-flight triggered job run no longer blocks its Trigger from firing again. |
connectors
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
upload_max_bytes |
number | No | 26214400 |
Server-wide size cap for connector file uploads (default is 25 MiB). Must resolve to a positive integer. |
encryption_key
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
encryption_key |
string | Yes | — | Base64 key decoding to 32 bytes. Encrypts connector secrets and TOTP secrets stored in the database. Generate with openssl rand -base64 32. |
Losing this key makes stored secrets unrecoverable. Keep it with your backups. See Hardening, RBAC, and secrets.
tasks_dir and jobs_dir
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
tasks_dir |
string | No | ./tasks |
Directory of task YAML imported at startup. |
jobs_dir |
string | No | ./jobs |
Directory of job template YAML imported at startup. |
Startup import is create-only and can be skipped with ENVOY_SKIP_SEED_IMPORT=true. See Seed import.
executor
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
type |
local | http |
No | — | local runs task subprocesses on the server host. http dispatches to registered remote executors. Omitting the section behaves as local execution. |
config.callback_url |
string | No | — | URL executors use to reach this control plane for logs and completion callbacks. |
config.executor_key |
string | No | — | Shared key authenticating control plane and executors. |
See Control plane and executors.
ai
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
provider |
anthropic |
Yes (when ai is set) |
— | The only supported provider. |
api_key |
string | Yes (when ai is set) |
— | Anthropic API key. |
model |
string | No | — | Model override. |
summarize_model |
string | No | — | Model used for summarization. |
max_tool_iterations |
number | No | 16 |
Maximum model turns in one agent loop; clamped to 1..64 at runtime. |
embeddings.provider |
local | openai_compatible | none |
No | — | Embeddings backend for reference search. |
embeddings.local.model_path |
string | No | — | Local embedding model directory. |
embeddings.local.wasm_path |
string | No | — | ONNX runtime WASM directory. |
embeddings.local.model |
string | No | — | Local model name. |
embeddings.openai_compatible.base_url |
string | Yes (for that provider) | — | OpenAI-compatible endpoint. |
embeddings.openai_compatible.api_key |
string | Yes (for that provider) | — | API key for the endpoint. |
embeddings.openai_compatible.model |
string | Yes (for that provider) | — | Embedding model name. |
prompt_caching.auto_message_cache |
boolean | No | on | Cache growing message history during tool loops. |
compaction.enabled |
boolean | No | true |
Master switch for conversation compaction. |
compaction.trigger_tokens |
number | No | 120000 |
Context tokens that trigger compaction before the next turn. |
compaction.keep_recent_tokens |
number | No | 20000 |
Approximate tokens of recent history kept verbatim. |
The assistant itself is documented in AI assistant.
mssql
Required when store.type or runs.log_store is mssql.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
server |
string | Yes | — | SQL Server hostname. |
database |
string | Yes | — | Database name. |
user |
string | Yes | — | Login user. |
password |
string | Yes | — | Login password. Supports ${secret://...}. |
port |
number | No | — | TCP port. |
encrypt |
boolean | No | — | Encrypt the connection. |
trust_server_certificate |
boolean | No | — | Trust self-signed server certificates. |
pool_size |
number | No | — | Connection pool size. |
postgres
Required when store.type or runs.log_store is postgres.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
connection_string |
string | Yes | — | PostgreSQL connection string. |
pool_size |
number | No | — | Connection pool size. |
ssl |
boolean | string | No | — | SSL mode. |
connection_timeout |
number | string | No | — | Seconds before a new connection attempt fails. |
idle_timeout |
number | string | No | — | Seconds before an idle connection is closed. |
max_lifetime |
number | string | No | — | Seconds before a connection is recycled. |
query_timeout |
number | string | No | — | Milliseconds before a read query is rejected. |
execute_timeout |
number | string | No | — | Milliseconds before a write/DDL statement is rejected. |
auth
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
totp_required |
boolean | No | true |
TOTP (2FA) is mandatory for password-based auth unless explicitly set to false. Existing TOTP secrets are preserved when disabled, so re-enabling resumes enforcement. |
providers.microsoft.client_id |
string | Yes (for that provider) | — | Microsoft Entra ID application client ID. |
providers.microsoft.client_secret |
string | Yes (for that provider) | — | Client secret. |
providers.microsoft.tenant_id |
string | No | — | Tenant restriction. |
providers.google.client_id |
string | Yes (for that provider) | — | Google OAuth client ID. |
providers.google.client_secret |
string | Yes (for that provider) | — | Client secret. |
providers.google.tenant_id |
string | No | — | Declared on the shared provider type; not used by Google. |
Callback URL registration is covered in OAuth redirect URIs.
secrets
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
default |
sqlite | mssql | postgres | azure_key_vault |
No | — | Provider for new secret writes. Unset falls back to the in-database provider matching store.type. |
sqlite |
object | No | — | Reserved; currently no settings. |
mssql |
object | No | — | Reserved; currently no settings. |
postgres |
object | No | — | Reserved; currently no settings. |
azure_key_vault.vault_url |
string | Yes (when configured) | — | Key Vault URL, for example https://my-vault.vault.azure.net/. |
azure_key_vault.name_prefix |
string | No | — | Prefix applied to secret names Envoy creates in the vault. |
An in-database default (sqlite, mssql, postgres) must match store.type; validation rejects mismatches at boot. Changing default affects new writes only — existing secret records keep their original provider and handle.
saffron
Deployment configuration for the optional embedded credential vault and connect UI served under /saffron. Document values come from your delivery; the keys are:
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
enabled |
boolean | No | — | Enable the embedded service. |
db_path |
string | No | ./data/saffron.db |
SQLite path for its own database. |
assets_dir |
string | No | — | Built SPA directory (defaults to node_modules/saffron/ui/dist/app). |
migrations_dir |
string | No | — | Override migrations directory. |
public_origin |
string | No | — | Public origin of this Envoy server, used for OAuth redirects and connect callbacks. Overridden by ENVOY_PUBLIC_ORIGIN when set. |
scheduler_interval_ms |
number | No | — | Internal scheduler interval. |
secrets |
object | No | — | Service keys and tokens (for example SECRETS_ENCRYPTION_KEY, INTERNAL_SERVICE_TOKEN) supplied by your delivery. |
cardamom
Deployment-level catalog defaults. When configured, Envoy registers one connector type per catalog integration at boot; the keys are deployment configuration only.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
enabled |
boolean | No | true when catalog is configured | When false, skip boot-time catalog type registration. |
integrations_dir |
string | No | — | Directory of integration JSON files (file-mode catalog). Env override: ENVOY_CATALOG_INTEGRATIONS_DIR. |
docs_dir |
string | No | — | Directory of integration documentation. Env override: ENVOY_CATALOG_DOCS_DIR. |
owner |
string | No | — | Catalog owner slug. Env override: ENVOY_CATALOG_OWNER. |
clove_url |
string | No | — | Catalog service URL. Env override: ENVOY_CLOVE_URL. |
clove_token |
string | No | — | Catalog service token; required when clove_url is set. Env override: ENVOY_CLOVE_TOKEN. |
saffron_url |
string | No | — | Credential vault URL. Env override: ENVOY_SAFFRON_URL. |
saffron_token |
string | No | — | Vault API token; prefer the env-scoped SAFFRON_API_TOKEN. |
Environment variables take precedence over the YAML values. See Customer builds and catalog.
victoria_logs
Required when runs.log_store is victoria_logs.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
url |
string | Yes | — | VictoriaLogs base URL. |
account_id |
number | No | 0 |
Tenant account ID. |
project_id |
number | No | 0 |
Tenant project ID. |
extra_fields |
map of string | No | — | Static fields attached to every inserted log record. |
decolorize |
boolean | No | true |
Strip terminal color codes from the message field on ingest. |
Full backend behavior is documented in VictoriaLogs.
Related
- Docker — how the entrypoint generates this file on first boot
- Control plane and executors — the
executorsection in practice - Retention — what
runs.retentiondeletes and keeps - Hardening, RBAC, and secrets —
encryption_key,auth, andsecretsin depth