Environment configuration
Environment variables and secrets for the self-hosted control plane (Compose, URLs, integrations).
Written By Zoro
Last updated 3 days ago
Operators supply configuration through a root .env file (or your secret store mapped into Compose). The dashboard image validates variables at runtime; see DOCKER.md and apps/dashboard/.env.example for a commented template. Do not commit real secrets.
1. Minimum required for the app container
These are enforced when the dFlow process starts (see packages/core/src/env.ts in the repo):
Variable | Purpose
- DATABASE_URI β MongoDB connection string (Compose often points at the
mongodbservice) - REDIS_URI β Redis connection string
- PAYLOAD_SECRET β Payload CMS signing secret (long random string)
- NEXT_PUBLIC_WEBSITE_URL β Public URL users type to reach your dashboard (scheme + host, no trailing path noise)
2. MongoDB service (Compose)
When using the stock mongodb service, set root credentials and database name:
- MONGO_INITDB_ROOT_USERNAME β Root user for the container
- MONGO_INITDB_ROOT_PASSWORD β Root password
- MONGO_DB_NAME β Application database name (must match the path inside
DATABASE_URI)
docker-compose.yml wires DATABASE_URI from these values; keep them in sync if you change passwords.
3. Tailscale (control plane)
Used when the app manages tailnet integration (see Tailscale and networking):
- TAILSCALE_AUTH_KEY β Auth key for nodes or automation
- TAILSCALE_OAUTH_CLIENT_SECRET β OAuth client secret for Tailscale API flows
- TAILSCALE_TAILNET β Tailnet name / identifier
The payload-app service uses NET_ADMIN and /dev/net/tun in the reference Compose file so userspace networking can work; do not drop those caps unless you know you do not need tailnet features.
4. Email (Resend)
- RESEND_API_KEY β API key for outbound mail
- RESEND_SENDER_EMAIL β From address (must be allowed in Resend)
- RESEND_SENDER_NAME β Display name
Without a working provider, invite and verification email flows fail; see Email and outgoing services.
5. Proxy and public URLs
- NEXT_PUBLIC_PROXY_DOMAIN_URL β Public base used for proxy links in the UI
- NEXT_PUBLIC_PROXY_CNAME β CNAME target the product documents for customers
6. Config generator service
The config-generator container in docker-compose.yml expects at least:
- JWT_TOKEN β Shared token between generator and consumers
- WILD_CARD_DOMAIN β Wildcard or base domain the proxy stack serves
- PROXY_PORT β Port the generator targets (match Traefik / internal routing)
7. Traefik and ACME (optional DNS)
If traefik uses Cloudflare (or similar) for DNS challenge:
- CF_DNS_API_TOKEN β DNS API token (as referenced in Compose)
You still need valid traefik.yaml, acme.json permissions, and dynamic/ layout on disk next to Compose. Paths are relative to the compose file location.
8. Object storage (S3-compatible)
Compose passes through:
- S3_ENDPOINT β API endpoint
- S3_REGION β Region string
- S3_ACCESS_KEY_ID β Access key
- S3_SECRET_ACCESS_KEY β Secret key
Fill these if your build enables uploads or media that expect object storage.
9. Observability and optional UI
- NEXT_PUBLIC_BETTER_STACK_SOURCE_TOKEN β Client log source token
- NEXT_PUBLIC_BETTER_STACK_INGESTING_URL β Ingest URL
- NEXT_PUBLIC_DISCORD_INVITE_URL β Support or community link in product chrome
- NEXT_PUBLIC_TURNSTILE_SITE_KEY β Cloudflare Turnstile (if used)
- TURNSTILE_SECRET_KEY β Server-side Turnstile secret
10. Beszel (monitoring stack in Compose)
The reference beszel-agent service ships with placeholder KEY and TOKEN in docker-compose.yml. Replace them with real values from your Beszel hub before production, or remove the agent service if you do not use that monitoring path.
11. Dokku-style deploy (alternative to Compose)
If you follow SELF_HOSTING.md instead of Compose, dokku config:set carries the same conceptual groups (database, Redis, Tailscale, Resend, proxy URLs, S3, Beszel). Link commands there set DATABASE_URI and REDIS_URI; verify they match your actual databases.
Checklist before first boot
- Copy apps/dashboard/.env.example to .env at the repo root (or merge into your vault export).
- Rotate every secret from the example placeholders.
- Confirm NEXT_PUBLIC_WEBSITE_URL matches how users reach Traefik (or your edge).
- Run docker compose up -d and read container logs if validation fails.
Related
- [Install with Docker / Docker Compose](/docs/self-hosting-dflow/install-with-docker-docker-compose)
- [Tailscale and networking](/docs/self-hosting-dflow/tailscale-and-networking)
- [Self-hosting troubleshooting](/docs/self-hosting-dflow/self-hosting-troubleshooting)
- [Troubleshooting overview](/docs/troubleshooting/troubleshooting-overview)