Configuration
Full values reference for self-hosted Dreadnode — data stores, TLS, sandboxes, email, OAuth, and tuning.
Helm CLI customers configure Dreadnode through a values overlay passed to helm install.
Admin Console customers (Embedded Cluster / KOTS) configure through the config screen.
Both paths set the same underlying chart values — this page documents the full surface.
Values live at two levels:
global.*— umbrella chart. Domain, scheme, TLS, ingress, resource preset.dreadnode-api.config.*— API subchart. Data stores, sandbox provider, email, OAuth, logging, auth policy, worker tuning.
The Helm Install page covers the minimum viable overlay
(global.domain + optional TLS). This page covers everything else.
Domain and scheme
Section titled “Domain and scheme”global: domain: dreadnode.example.com # REQUIRED — chart fails without it scheme: https # http (default) or httpsThe domain appears in every URL the platform generates — OAuth redirects, presigned S3
URLs, password reset links. scheme controls whether those URLs use http:// or
https://. Set both correctly before first use; changing them later requires a redeploy.
Admin Console: Identity → Domain, URL Scheme.
global: tls: secretName: dreadnode-tls # kubernetes.io/tls Secret in the install namespace skipCheck: false # set true when TLS terminates upstreamSee Helm Install — TLS for the full setup walkthrough.
Admin Console: Networking & TLS → TLS Certificate Secret Name.
Ingress
Section titled “Ingress”global: ingress: className: traefik # match your ingress controller annotations: {} # controller-specific annotationsAnnotations cascade to every subchart ingress (API, frontend, MinIO). Per-subchart
overrides are available at dreadnode-api.ingress.annotations, etc.
Admin Console: Networking & TLS → Ingress Class Name.
Resource sizing
Section titled “Resource sizing”global: resourcesPreset: small # small | medium | largeApplied to every subchart. Preset values for the API pod:
- small — 250m/512Mi requests, 500m/1Gi limits
- medium — 500m/1Gi requests, 1000m/2Gi limits
- large — 1000m/2Gi requests, 4000m/8Gi limits
Override per-subchart with explicit resources: blocks when presets don’t fit.
Admin Console: Resource Sizing.
PostgreSQL
Section titled “PostgreSQL”In-cluster by default. Switch to external to point at RDS or another managed service.
In-cluster (default)
Section titled “In-cluster (default)”No configuration needed. The chart deploys a single-replica PostgreSQL StatefulSet with auto-generated credentials.
External database
Section titled “External database”dreadnode-api: endpoints: database: external: my-rds-instance.region.rds.amazonaws.com credentials: database: source: externalSecret secretName: dreadnode-external-pg # KOTS creates this; Helm customers pre-create it config: database: port: 5432 name: platform user: admin useSsl: true # recommended for all managed Postgres useIamAuth: false # set true for RDS IAM auth (no static password)
dreadnode-base: postgresql: enabled: false # disable the in-cluster StatefulSetFor Helm CLI customers, pre-create the Secret:
kubectl -n <namespace> create secret generic dreadnode-external-pg \ --from-literal=password='<db-password>'For IAM auth (useIamAuth: true), the API pod’s service account needs an IAM role with
rds-db:connect permission. Configure IRSA via:
dreadnode-api: serviceAccount: annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/dreadnode-apiAdmin Console: Data Stores → PostgreSQL → “Connect to an external database”, then fill in host, port, database, user, password, SSL, and IAM auth fields.
ClickHouse
Section titled “ClickHouse”In-cluster by default. Switch to external for managed ClickHouse.
External ClickHouse
Section titled “External ClickHouse”dreadnode-api: endpoints: clickhouse: external: my-clickhouse.example.com credentials: clickhouse: source: externalSecret secretName: dreadnode-external-ch config: clickhouse: protocol: https # http (default) or https port: 8443 # adjust for your service database: default user: admin
dreadnode-base: clickhouse: enabled: falsePre-create the Secret:
kubectl -n <namespace> create secret generic dreadnode-external-ch \ --from-literal=admin-password='<ch-password>'Admin Console: Data Stores → ClickHouse → “Connect to an external service.”
S3 / MinIO
Section titled “S3 / MinIO”In-cluster MinIO by default. Switch to external for AWS S3 or another S3-compatible service.
External S3
Section titled “External S3”dreadnode-api: endpoints: s3: internal: '' # leave empty for AWS S3 (uses default endpoint) external: https://s3.us-east-1.amazonaws.com credentials: s3: source: static # static | iam | minio accessKeyId: AKIA... secretAccessKey: <secret> config: s3: region: us-east-1 buckets: pythonPackages: my-packages-bucket orgData: my-org-data-bucket userDataLogs: my-logs-bucket sdk: userDataRoleArn: arn:aws:iam::123456789012:role/dreadnode-user-data stsDurationSeconds: 3600
dreadnode-base: minio: enabled: falseFor IAM-based credentials (source: iam), omit accessKeyId and secretAccessKey
and configure IRSA on the API service account instead.
The userDataRoleArn is the IAM role the API assumes when minting scoped workspace
credentials via STS. It must trust the API pod’s identity and have s3:* on the
orgData bucket.
Admin Console: Data Stores → S3/MinIO → “Connect to an external service.”
Sandbox provider
Section titled “Sandbox provider”dreadnode-api: config: sandboxProvider: opensandbox # opensandbox (default) or e2bOpenSandbox (default) runs sandboxes on-cluster using the dreadnode-sandbox-controller
and dreadnode-sandbox-server subcharts. No additional configuration needed.
E2B offloads sandboxes to E2B’s cloud. Requires outbound internet and an API key:
dreadnode-api: config: sandboxProvider: e2b extraEnv: - name: E2B_API_KEY value: <your-e2b-key>
# Optionally disable the on-cluster sandbox subcharts to reclaim resourcesdreadnode-sandbox-controller: enabled: falsedreadnode-sandbox-server: enabled: falseAdmin Console: Sandbox Runtime → OpenSandbox or E2B.
The default is no email — verification URLs are logged at WARNING level by the API pod, and an operator copies them out. This is the expected path for most enterprise installs.
To wire an SMTP relay:
dreadnode-api: config: email: provider: smtp fromAddress: noreply@example.com fromName: Dreadnode smtp: host: smtp.example.com port: 587 user: apikey useTls: true existingSecret: dreadnode-smtp-password passwordKey: passwordPre-create the SMTP password Secret:
kubectl -n <namespace> create secret generic dreadnode-smtp-password \ --from-literal=password='<smtp-password>'Admin Console: Not exposed on the config screen. Helm-only via
dreadnode-api.config.email.*.
Local password auth is the default. GitHub and Google login can be added independently.
GitHub
Section titled “GitHub”dreadnode-api: config: oauth: github: clientId: <github-client-id> existingSecret: dreadnode-github-oauth clientSecretKey: clientSecretdreadnode-api: config: oauth: google: clientId: <google-client-id> existingSecret: dreadnode-google-oauth clientSecretKey: clientSecretPre-create the corresponding Secret for each provider. The chart does not create or manage OAuth client secrets.
Admin Console: Not exposed on the config screen. Helm-only via
dreadnode-api.config.oauth.*.
Logging
Section titled “Logging”dreadnode-api: config: logging: level: info # trace | debug | info | warning | error | critical structured: false # true = JSON logs for aggregators (Splunk, Datadog, ELK)debug is the right choice during an incident. trace is extremely verbose — only
useful for framework-level debugging.
Admin Console: Logging → Log Level, Structured JSON.
Auth policy
Section titled “Auth policy”dreadnode-api: config: auth: minPasswordLength: 12 # default: 8 emailRegexes: - '^.*@example\.com$' # restrict signups to a domainAdmin Console: Not exposed on the config screen. Helm-only.
Worker concurrency
Section titled “Worker concurrency”Each API pod runs in-process workers for evaluations, Worlds jobs, training, and optimization. Default concurrency is 1 per worker type per pod.
dreadnode-api: config: workers: concurrency: evaluation: 2 worlds: 2 training: 1 optimization: 1Raise these when a queue is backing up and the API pod has CPU/memory headroom. This is the primary scaling lever before adding more API replicas.
Admin Console: Not exposed on the config screen. Helm-only.
Extra environment variables
Section titled “Extra environment variables”For configuration not covered by the values schema, inject env vars directly:
dreadnode-api: extraEnv: - name: SOME_FEATURE_FLAG value: 'true' extraEnvFrom: - secretRef: name: my-extra-secretsThe repo expects configuration to be centralized under platform/envs/. The most important values
for a self-hosted deployment are:
Core app settings
Section titled “Core app settings”| Variable | Purpose |
|---|---|
ENVIRONMENT | Selects the environment profile such as local, dev, staging, or prod |
DEPLOYMENT_MODE | Chooses saas or enterprise behavior |
CORS_ORIGINS | Explicit origin allow-list for browser clients |
FRONTEND_URL_OVERRIDE | Forces the frontend base URL when it should not be derived from PROTOCOL and TLD |
SECRET_KEY | Core app secret for signing and internal security flows |
JWT_SECRET_KEY | Access-token signing secret |
Database and analytics
Section titled “Database and analytics”| Variable | Purpose |
|---|---|
DATABASE_HOST | PostgreSQL host |
DATABASE_PORT | PostgreSQL port |
DATABASE_NAME | PostgreSQL database name |
DATABASE_USER | PostgreSQL username |
DATABASE_PASSWORD | PostgreSQL password unless IAM auth is enabled |
DATABASE_USE_IAM_AUTH | Switches database auth to IAM token mode for RDS proxy style deployments |
RO_READER_DB_PASSWORD | Password used by Alembic migrations to provision/update the ro_reader PostgreSQL role |
CLICKHOUSE_USER | ClickHouse user |
CLICKHOUSE_DATABASE | ClickHouse database |
USE_DUCKDB | Development toggle for alternate local analytics storage paths; ClickHouse remains the recommended default |
USE_SHARED_MERGE_TREE_OVERRIDE | Force self-hosted ClickHouse away from cloud-only SharedMergeTree behavior |
Object storage
Section titled “Object storage”| Variable | Purpose |
|---|---|
S3_AWS_ENDPOINT_URL | Internal S3 or MinIO endpoint |
S3_AWS_ACCESS_KEY_ID | Object-storage access key |
S3_AWS_SECRET_ACCESS_KEY | Object-storage secret |
ORG_DATA_BUCKET_NAME | Main organization data bucket |
Integrations and platform features
Section titled “Integrations and platform features”| Variable | Purpose |
|---|---|
RECAPTCHA_ENABLED | Enables or disables Recaptcha validation |
RECAPTCHA_PUBLIC_KEY | Browser-side Recaptcha key when enabled |
RECAPTCHA_SECRET_KEY | Server-side Recaptcha verification key |
LITELLM_ENABLED | Enables LiteLLM key provisioning, admin routes, and sandbox env injection |
LITELLM_INTERNAL_URL | API-to-LiteLLM URL for admin APIs |
LITELLM_PUBLIC_URL | OpenAI-compatible LiteLLM base URL injected into sandboxes and TUI sessions |
LITELLM_MASTER_KEY | Shared auth key for LiteLLM proxy access |
LITELLM_SALT_KEY | Stable root secret for encrypted LiteLLM runtime credentials |
LITELLM_DATABASE_URL | LiteLLM Prisma database URL, usually with ?schema=litellm |
LITELLM_TUI_KEY_DURATION_SECONDS | TTL for TUI inference keys |
LITELLM_BUDGET_FLOAT_BUFFER_USD | SaaS-only budget headroom used when syncing credits to LiteLLM team budgets |
STRIPE_SECRET_KEY | Stripe API key for SaaS billing |
STRIPE_WEBHOOK_SECRET | Stripe webhook verification secret |
STRIPE_PRICE_ID | Stripe price identifier for credit purchases |
How the env files are organized
Section titled “How the env files are organized”Use platform/envs/ as the source of truth:
platform/envs/local.envfor local developmentplatform/envs/{env}.envfor committed non-secret configurationplatform/envs/{env}.secrets.encfor encrypted secrets
That split keeps non-sensitive settings in version control while preserving encrypted secrets for deployed environments.
Database authentication flags
Section titled “Database authentication flags”The API supports two database authentication modes:
DATABASE_USE_IAM_AUTH=false(default): password-based authentication usingDATABASE_PASSWORDDATABASE_USE_IAM_AUTH=true: IAM auth token injection for RDS Proxy connections (no static DB password required at runtime)
For migration-time role provisioning, set LITELLM_DB_PASSWORD and
RO_READER_DB_PASSWORD in deployment environments. Local development can omit
them.
Defaults and derived values
Section titled “Defaults and derived values”CORS_ORIGINSfalls back to the derived frontend URL if you do not override it explicitly.- In local development,
platform/envs/local.example.envdefaults toenterprisemode. If you switch tosaasmode, mock Stripe values are provided so the app can boot without a live billing integration — but inference key provisioning will require a credit balance. - For self-hosted ClickHouse, keep
USE_SHARED_MERGE_TREE_OVERRIDE=falseunless you know you are on a compatible managed ClickHouse setup. - In dev environments,
TAILNET_IDcan help deriveLITELLM_PUBLIC_URLwhen you do not want to hardcode it. - If
LITELLM_DATABASE_URLpoints at the app Postgres database, include?schema=litellmso LiteLLM’s Prisma tables stay separate from the app’spublicschema.
Workspace storage credential duration
Section titled “Workspace storage credential duration”The API issues temporary STS credentials for workspace S3 mounts.
STS_CREDENTIAL_DURATION_SECONDS(default:3600) controls the assumed-role session duration.- Values above
3600are rejected. - This limit aligns with AWS’s 1-hour role-chaining ceiling for assumed-role sessions.
- Ensure the IAM role referenced by
USER_DATA_ROLE_ARNhas aMaxSessionDurationat least as large as this value.
Practical guidance
Section titled “Practical guidance”- Keep local development on the repo defaults in
platform/envs/local.envunless you have a clear reason to diverge. The default isDEPLOYMENT_MODE=enterprise, which disables credit billing. - If you need SaaS mode, set
DEPLOYMENT_MODE=saasexplicitly. Stripe settings are then required by the config validator for billing to activate correctly. - In Enterprise mode, you can usually disable billing-specific values and focus on auth, storage, and analytics connectivity.
- If
RECAPTCHA_ENABLED=true, both Recaptcha keys must be present. - If
LITELLM_ENABLED=true, provideLITELLM_MASTER_KEY, keepLITELLM_SALT_KEYstable, and make sureLITELLM_PUBLIC_URLis resolvable from sandboxes. - When changing config, update
packages/api/app/core/config.pyand the matching files inplatform/envs/together so the docs, schema, and runtime stay aligned.