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 mongodb service)
  • 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

  1. Copy apps/dashboard/.env.example to .env at the repo root (or merge into your vault export).
  2. Rotate every secret from the example placeholders.
  3. Confirm NEXT_PUBLIC_WEBSITE_URL matches how users reach Traefik (or your edge).
  4. 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)