> ## Documentation Index
> Fetch the complete documentation index at: https://filament.getgalaxy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Configure the server, control plane, and workers

The server, control plane, and worker read configuration from environment
variables. A deployment must give all three the same datastore, event bus, and
secret-provider settings. The Helm chart renders these variables from chart
values; other platforms set them directly.

This page does not cover the `filament` CLI, which uses a YAML configuration
file.

## Shared configuration

The server, control plane, and worker read the variables in this section.
Only the worker links connector drivers; the server and control plane reach
them through `WORKER_URL`.

### Private HTTP manifests

| Variable | Default | Description |
| - | - | - |
| `HTTP_MANIFESTS_DIR` | unset | Directory containing private `<connector>/registry.json` files and API-version manifest folders. Adds private versions and can change default aliases; collisions with concrete bundled registrations fail startup. |

Set it on every worker: the persistent worker that answers connector calls and
the workers that execute runs. Files are loaded once at startup; missing,
empty, or invalid configured directories stop startup. The variable does not mount or distribute files. See
[private catalog setup](/pages/connectors/building-a-connector/http-manifests#load-a-private-catalog-at-startup)
for the directory structure and override behavior.

### Datastore

| Variable | Default | Description |
| - | - | - |
| `PERSISTENCE_PROVIDER` | `postgres` | Datastore implementation. Accepts `postgres` or `sqlite` |
| `PERSISTENCE_DSN` | — | PostgreSQL connection string. Required for `postgres` |
| `STORE_PATH` | — | SQLite database path. Required for `sqlite` |

Use PostgreSQL for a split deployment. The service binaries accept SQLite,
but a local SQLite file is not a shared datastore for services running on
different hosts.

### Event bus

| Variable | Default | Description |
| - | - | - |
| `EVENTBUS_PROVIDER` | `nats` | Event bus implementation. `nats` is the only supported value |
| `NATS_URL` | — | **Required.** NATS connection URL |
| `NATS_STREAM` | `EVENTBUS` | JetStream stream name; Filament creates it when needed |
| `NATS_SUBJECTS` | `>` | JetStream subject filter. The Helm chart uses `ingestion.v1.>` |
| `NATS_TTL_SECONDS` | `604800` | Maximum message age in seconds. Set to `0` to disable age-based expiration |

<Note>
  `DISPATCH_MODE` changes where runs execute; it does not replace the event bus.
</Note>

### Secret provider

| Variable | Default | Description |
| - | - | - |
| `SECRET_PROVIDER` | unset | Unset uses the configured datastore. External values are `aws-secrets-manager` and `gcp-secret-manager` |
| `ENCRYPTION_KEY` | — | Base64-encoded AES key. Required when `SECRET_PROVIDER` is unset; it must decode to 16, 24, or 32 bytes |
| `ENCRYPTION_KEY_ID` | `default` | Identifier stored with secrets written by the datastore-backed provider |
| `SECRETS_PREFIX` | empty | Root name for external secrets, default `filament`. AWS names secrets `<prefix>/<tenant>/...` and GCP `<prefix>-<hash>`; GCP allows only letters, digits, `_`, and `-` |
| `AWS_REGION` | AWS SDK chain | AWS region. Startup fails if the SDK cannot resolve one |
| `GCP_PROJECT_ID` | — | GCP project containing Secret Manager secrets. Required for `gcp-secret-manager` |
| `GCP_REGION` | — | GCP region containing Secret Manager secrets. Required for `gcp-secret-manager` |

The datastore-backed provider stores AES-GCM encrypted values in PostgreSQL or
SQLite. Every service must receive the same encryption key.

<Warning>
  Keep `ENCRYPTION_KEY` safe and stable. Changing it makes existing secrets
  unreadable. `ENCRYPTION_KEY_ID` records an identifier, but it does not provide
  a multi-key rotation mechanism.
</Warning>

The AWS provider loads credentials through the standard AWS SDK chain. It
stores each Filament secret as a JSON envelope in AWS Secrets Manager.

The GCP provider loads Application Default Credentials and uses regional Secret
Manager secrets. Filament refs are mapped to deterministic
GCP-safe IDs and retained in secret annotations. Grant workloads access through
their attached service account or Workload Identity. Deleting a connection
permanently deletes its managed GCP secrets.

### Logs and OpenTelemetry

| Variable | Default | Description |
| - | - | - |
| `LOG_LEVEL` | `INFO` | Log level: `INFO`, `DEBUG`, or `TRACE` |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | — | Shared OTLP endpoint for metrics and traces |
| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | — | Metrics-specific OTLP endpoint |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | — | Trace-specific OTLP endpoint |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `grpc` | Transport for both exporters: `grpc` or `http/protobuf` |
| `OTEL_SERVICE_NAME` | SDK default | Service name attached to telemetry |

Filament enables OpenTelemetry export when any OTLP endpoint is set. It
creates both metrics and trace exporters using the selected protocol. The
exporters also honor the standard OTLP headers, TLS, timeout, and compression
variables for that transport. Application logs remain JSON on standard output;
Filament does not export logs through OTLP.

## Server

| Variable | Default | Description |
| - | - | - |
| `SERVER_ADDR` | `:8080` | Listen address for the API, web application, and health endpoints |
| `WORKER_URL` | — | **Required.** Address of the persistent worker that answers connector calls, for example `http://filament-worker:8080` |
| `DEFAULT_TENANT_ID` | `00000000-0000-0000-0000-000000000000` | Tenant used when a request does not provide one |
| `METRICSSTORE_PROVIDER` | unset | Unset reads dashboard metrics from the configured datastore. No explicit values are currently supported |

### Authentication

| Variable | Default | Description |
| - | - | - |
| `AUTH_PROVIDER` | unset | Unset disables authentication. Supported providers are `zitadel` and `keycloak` |
| `AUTH_ISSUER` | — | Issuer URL. The Zitadel base URL, or the Keycloak realm URL in the form `https://<host>/realms/<realm>`. Required when `AUTH_PROVIDER` is set |
| `AUTH_PAT` | — | Zitadel machine-user personal access token. Required when `AUTH_PROVIDER=zitadel` |
| `AUTH_CLIENT_ID` | — | Filament's confidential client in the Keycloak realm. Required when `AUTH_PROVIDER=keycloak` |
| `AUTH_CLIENT_SECRET` | — | That client's secret. Required when `AUTH_PROVIDER=keycloak` |
| `AUTH_ADMIN_USERNAME` | unset | Keycloak admin on the master realm. With `AUTH_ADMIN_PASSWORD`, the server creates the realm and client on boot when they are missing; unset, the realm's owners provision both |
| `AUTH_ADMIN_PASSWORD` | unset | That admin's password |
| `AUTH_BOOTSTRAP_TENANT` | unset | Tenant converged on every boot |
| `AUTH_BOOTSTRAP_ADMIN_EMAIL` | unset | Person who administers the bootstrap tenant, created on boot and left alone once it exists. Closes sign-up: people join by invitation |
| `AUTH_BOOTSTRAP_ADMIN_PASSWORD` | unset | That person's initial password, chosen by you. Required with `AUTH_BOOTSTRAP_ADMIN_EMAIL` |
| `AUTH_BOOTSTRAP_CLIENT_ID` | unset | Admin service account on the bootstrap tenant, so an SDK can act before any person signs in. Keycloak only; set with `AUTH_BOOTSTRAP_CLIENT_SECRET` or not at all |
| `AUTH_BOOTSTRAP_CLIENT_SECRET` | unset | Secret that service account authenticates with, chosen by you |
| `AUTH_UI_ORIGIN` | `http://localhost:5173` | Origin that serves the web application. An `https://` origin enables secure session cookies |

<Warning>
  When `AUTH_PROVIDER` is unset, the API and web application are unauthenticated.
</Warning>

Only the server reads authentication variables.

## Control plane

<Warning>
  Run exactly one control-plane replica. Multiple replicas may race while
  coordinating schedules and runs.
</Warning>

| Variable | Default | Description |
| - | - | - |
| `HEALTH_ADDR` | `:8081` | Listen address for `/livez`, `/startupz`, and `/readyz` |
| `WORKER_URL` | — | **Required.** Address of the persistent worker that answers connector calls |
| `DISPATCH_MODE` | `kubernetes` | Run execution mode: `kubernetes` or `worker` |
| `REAPER_INTERVAL_SECONDS` | `60` | Interval between stale-run sweeps in Kubernetes mode |
| `REAPER_STALE_AFTER_SECONDS` | `300` | Time without a worker heartbeat before a running run is failed |

In `kubernetes` mode, the control plane creates a worker Job for each run and
uses the reaper to detect workers that stop reporting heartbeats. In `worker`
mode, the control plane dispatches nothing: a long-lived worker started with
`-execute` consumes requested runs from the event bus. There are no worker
Jobs, heartbeats, or reaper.

Pipeline webhooks run automatically in the control plane and standalone app,
using the existing datastore and secrets provider. Standalone uses environment
secret references for destinations. See [Notifications](/pages/api-reference/service/pipelines#notifications).

### Kubernetes dispatch

These variables apply only when `DISPATCH_MODE=kubernetes`. The Helm chart
sets them from its `worker` values.

| Variable | Default | Description |
| - | - | - |
| `K8S_WORKER_IMAGE` | — | **Required.** Container image for worker Jobs |
| `K8S_WORKER_SECRET_NAME` | — | **Required.** Secret loaded into worker containers with `envFrom` |
| `K8S_WORKER_CONFIGMAP_NAME` | — | Optional ConfigMap loaded with `envFrom` |
| `K8S_NAMESPACE` | ServiceAccount namespace | Namespace in which to create Jobs |
| `K8S_KUBECONFIG` | in-cluster configuration | Kubeconfig path. Falls back to `KUBECONFIG` |
| `K8S_WORKER_SERVICE_ACCOUNT` | namespace default | ServiceAccount assigned to worker pods |
| `K8S_WORKER_APP_NAME` | `filament` | Value of the worker's `app.kubernetes.io/name` label |
| `K8S_WORKER_IMAGE_PULL_POLICY` | `IfNotPresent` | Worker image pull policy |
| `K8S_WORKER_RESTART_POLICY` | `Never` | Worker pod restart policy |
| `K8S_WORKER_TERMINATION_GRACE_SECONDS` | Kubernetes default | Worker termination grace period |
| `K8S_WORKER_ACTIVE_DEADLINE_SECONDS` | unset | Maximum lifetime of a worker Job |
| `K8S_JOB_NAME_PREFIX` | `filament` | Prefix for generated Job names |
| `K8S_JOB_BACKOFF_LIMIT` | `1` | Number of retries before Kubernetes marks a Job failed |
| `K8S_JOB_TTL_SECONDS_AFTER_FINISHED` | unset | Time to retain a finished Job |

## Worker

The worker is the one binary that links connector drivers. Without flags it
executes one dispatched run and exits. With `-serve` it runs long-lived and
answers connector calls for the server and control plane, needing neither
datastore nor event bus. With `-execute` it runs long-lived and executes
requested runs from the event bus, for deployments without Kubernetes. The two
flags combine; neither combines with `RUN_ID`.

With `-serve`, `/readyz` reports whether connector serving is available. This
also applies to `-serve -execute`: a datastore or event-bus outage does not remove
the connector service from its Service endpoints. An execution-only worker's
readiness checks its datastore and event bus. Both modes report not ready before
startup completes and during shutdown.

| Variable | Default | Description |
| - | - | - |
| `TENANT_ID` | — | **Required** for a dispatched run. Tenant that owns the run |
| `RUN_ID` | — | **Required** for a dispatched run. Persisted run to execute |
| `WORKER_ADDR` | `:8080` | Listen address for connector calls and health endpoints when long-lived |
| `HEARTBEAT_SECONDS` | `30` | Interval between worker heartbeats |

The Kubernetes dispatcher injects `TENANT_ID` and `RUN_ID`. The worker loads
the remaining shared settings from its Secret and ConfigMap. Invalid or
non-positive `HEARTBEAT_SECONDS` values use the 30-second default.

## Standalone

Standalone is intended for testing and evaluation. It has its own embedded
NATS server, SQLite datastore, and read-only environment secret provider.

| Variable | Default | Description |
| - | - | - |
| `INGESTION_ADDR` | `:8080` | Listen address for the API and web application |
| `NATS_STORE_DIR` | `<temporary directory>/filament-standalone` | Embedded JetStream storage directory |
| `STORE_PATH` | `<NATS_STORE_DIR>/filament.db` | SQLite database path |

Standalone also reads `LOG_LEVEL` and `NATS_TTL_SECONDS`. Its secret provider
maps a reference such as `postgres-creds/dsn` to `POSTGRES_CREDS_DSN`. It
cannot create, update, or delete secrets.

The public Go API also uses `INGESTION_ADDR`. See
[Embedded](/pages/guides/usage/embedded) for library configuration.

## Migrations

PostgreSQL migrations are embedded in the server image. The server's
`-migrate` flag waits up to five minutes for the database, applies pending
migrations, and exits:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
./server -migrate
```

The Helm chart runs this command in a post-install and post-upgrade hook. Use
the same command as a pre-deploy step on platforms such as Railway. SQLite
applies its migrations when the datastore opens.

The [Helm chart README](https://github.com/galaxy-io/filament/tree/main/charts/filament)
lists the chart values that produce these variables.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.