Skip to content

Environment Variables

The environment variables you set to run a Broch server.

BROCH_MASTER_KEY, API__WILDCARDHOSTNAME and a database connection are required: the server won’t start without them. Your identity provider is also a boot input: the server starts without it, but no one can sign in until it’s set. The license isn’t a boot input. It’s activated in the app on first sign-in. See Licensing & Billing.

To check a configuration without starting the server, run the image with --check-config. It lists every configuration problem in the environment; on Docker Compose, docker compose run --rm --no-deps broch --check-config.

Variable Description Default Secret
ASPNETCORE_ENVIRONMENT ASP.NET Core environment name Production No
ASPNETCORE_URLS HTTP listener binding (TLS terminated at ingress) — (the image listens on 8080) No
BROCH_MASTER_KEY At-rest encryption root, at least 32 bytes. Wraps the Data Protection key ring. Generated at provision time or by you, depending on platform — see below — Yes
API__WILDCARDHOSTNAME Wildcard hostname for tunnel subdomains (e.g., broch.{your-domain}) — No

BROCH_MASTER_KEY is the customer-owned root of Broch’s at-rest encryption. It derives the key-encryption key that wraps the ASP.NET Data Protection key ring, which in turn protects the encrypted IdP refresh tokens, the persisted license token, and usage counters stored in your database. The server will not start without it.

  • Generated in your environment. The broch-deploy Terraform modules generate the value: the AWS and Azure modules at provision time, into Secrets Manager or Key Vault; the DigitalOcean module on the Droplet at first boot, into its root-only .env, with a copy on the data volume. On Docker Compose and the Azure and AWS appliances, you generate it once with openssl rand -base64 48 and supply it at deploy time. Docker Compose keeps it in your env file; the appliances store it in Key Vault or Secrets Manager. Either way it stays in your environment, and Broch never receives a copy. See Architecture & Security.
  • Treat it like a database master password. Keep it in your secret store and back it up there. Together with your database connection, these are the secrets the server strictly requires to start.
  • Rotation / loss is recoverable, not catastrophic. If the key is changed or lost, previously wrapped state becomes unreadable; Broch detects this, mints a fresh key ring, and the affected paths self-heal — users re-authenticate, the license token re-activates on the next refresh, and usage counters reset. No instance is ever bricked. Rotating the key therefore forces a one-time re-authentication for signed-in users.
  • Unchanged across upgrades. Supply the same BROCH_MASTER_KEY when you upgrade — it lives in your secret store, so this is automatic. The key ring stays readable and nobody re-authenticates. Changing it during an upgrade is what triggers the one-time re-auth above, not the upgrade itself. See Upgrading & Rollback.

.env feeds the compose file, not Broch directly, and the compose file passes Broch only the variables it lists, some under Compose names: see Startup Settings and the rows below. To set any other variable, add it to the broch service’s environment: block or a docker-compose.override.yml, then run docker compose up -d; restart doesn’t apply environment changes.

Required — The application will not start without a database connection.

Variable Description Default Secret
DATABASE__PROVIDER Database provider (only PostgreSQL is supported) PostgreSQL No
ConnectionStrings__BrochConnection PostgreSQL connection string — Yes

Example: Host=localhost;Database=broch;Username=postgres;Password=secret

Part of the boot floor. Configure your identity provider here. The server starts without it, but no one can sign in until it’s set — there is no in-app bootstrap; the first admin authenticates through the IdP, and admin access is granted by a role in AUTHENTICATION__ADMINROLES. Once any of AUTHENTICATION__PROVIDER, CLIENTID, CLIENTSECRET, TENANTID or DOMAIN is set, Broch refuses to start until the provider, client ID, client secret and the provider’s own values below are all set. It checks after migrating the database, except for an unknown provider, which it refuses at once.

Variable Description Default Secret
AUTHENTICATION__PROVIDER Identity provider type: AzureAd, EntraExternalId, Auth0, Okta, or Oidc (any standards-compliant OIDC issuer — set AUTHENTICATION__AUTHORITY) — No
AUTHENTICATION__CLIENTID OAuth client ID from your IdP — No
AUTHENTICATION__CLIENTSECRET OAuth client secret from your IdP — Yes
AUTHENTICATION__ADMINROLES Comma-separated role names that grant admin access — No
BROCH_AUTH_CONFIG_RESET Break-glass: clears the persisted in-app IdP configuration at boot so the environment values above apply again. Set, restart, recover, then remove — see Recovering From a Broken IdP Configuration — No

Entra ID (AzureAd and EntraExternalId):

Variable Description Default
AUTHENTICATION__TENANTID Azure tenant ID. Required unless AUTHENTICATION__AUTHORITY is set. —
AUTHENTICATION__INSTANCE Login endpoint: https://login.microsoftonline.com/ for AzureAd, https://<tenant>.ciamlogin.com/ for EntraExternalId. Required unless AUTHENTICATION__AUTHORITY is set. —

Auth0:

Variable Description Default
AUTHENTICATION__DOMAIN Auth0 domain (e.g., {your-tenant}.auth0.com). Required unless AUTHENTICATION__AUTHORITY is set. —
AUTHENTICATION__AUDIENCE Required. Identifier of the Auth0 API your Broch application has User Access to. The server refuses to start without it. See Auth0. —
AUTHENTICATION__SCOPES Additional OAuth scopes, appended to the always-requested openid,profile,email,offline_access —

Okta:

Variable Description Default
AUTHENTICATION__DOMAIN Okta organization domain (e.g., {your-org}.okta.com). Required unless AUTHENTICATION__AUTHORITY is set. —
AUTHENTICATION__SCOPES Additional OAuth scopes, appended to the always-requested openid,profile,email,offline_access —

Generic OIDC (Oidc): for any standards-compliant issuer not listed above.

Variable Description Default
AUTHENTICATION__AUTHORITY Issuer URL — the base that serves /.well-known/openid-configuration. Required for Oidc. —
AUTHENTICATION__SCOPES Additional OAuth scopes, appended to the always-requested openid,profile,email,offline_access —
Variable Description Default Required
API__PUBLICIP The public IP advertised for automatic DNS records. Empty means the server detects its own egress IP; the appliances set it. Docker Compose: BROCH_PUBLIC_IP. — No
API__MAXTUNNELS Maximum concurrent tunnels. Empty or 0 means unlimited. — No
API__TRUSTEDPROXYCIDRS Trusted reverse-proxy ranges, seeded into the admin setting on first boot. An invalid value is logged and the whole seed skipped. Docker Compose: BROCH_TRUSTED_PROXY_CIDRS. See Configuration → Reverse Proxy Loopback only No

The SSH host key for tunnel transport is generated by the server and stored encrypted in your database; it needs no configuration.

Variable Description Default Required
CENTRALSERVER__VALIDATIONTIMEOUTSECONDS Timeout for license activation/refresh requests (seconds) 30 No

Structured JSON always goes to stdout — collect it with your container platform’s log driver. A provider is an additional off-box sink, never a replacement for stdout. These variables seed the setting on first boot; after that, Configuration → Logging in the admin app wins.

Variable Description Default Required
BROCHLOGGING__PROVIDER Additional log sink: DataDog, Seq, OpenTelemetry — (stdout only) No
BROCHLOGGING__MINIMUMLEVEL Minimum log level: Verbose, Debug, Information, Warning, Error, Fatal Information No
Variable Description Default
BROCHLOGGING__DATADOG__APIKEY DataDog API key —
BROCHLOGGING__DATADOG__SERVICENAME DataDog service name tag broch-server
BROCHLOGGING__DATADOG__ENVIRONMENT DataDog environment tag production
BROCHLOGGING__DATADOG__SITE DataDog site: datadoghq.com (US) or datadoghq.eu (EU) datadoghq.com
Variable Description Default
BROCHLOGGING__SEQ__SERVERURL Seq server URL http://localhost:5341

Routes structured logs to any OTLP-compatible collector — the vendor-neutral path into your SIEM or observability stack.

Variable Description Default
BROCHLOGGING__OTLP__ENDPOINT OTLP collector endpoint (e.g., http://collector:4317 for gRPC, http://collector:4318/v1/logs for HTTP) —
BROCHLOGGING__OTLP__PROTOCOL OTLP transport: grpc or httpprotobuf grpc
BROCHLOGGING__OTLP__HEADERS Comma-separated Key=Value headers sent with every export, for collectors that require authentication (e.g., Authorization=Bearer <token>). Treat as a secret —

Minimal Docker Compose .env (Bundled Database)

Section titled “Minimal Docker Compose .env (Bundled Database)”

The with-postgres variant’s .env, using its Compose names (see On Docker Compose):

BROCH_MASTER_KEY=<openssl rand -base64 48>
BROCH_WILDCARD_HOSTNAME=broch.{your-domain}
CADDY_ACME_EMAIL=<your-email>
CLOUDFLARE_API_TOKEN=<zone-dns-token>
POSTGRES_PASSWORD=<openssl rand -base64 32>
AUTHENTICATION__PROVIDER=AzureAd
AUTHENTICATION__CLIENTID=<your-client-id>
AUTHENTICATION__CLIENTSECRET=<your-client-secret>
AUTHENTICATION__TENANTID=<your-tenant-id>
AUTHENTICATION__INSTANCE=https://login.microsoftonline.com/
AUTHENTICATION__ADMINROLES=broch_admin

The server’s own names, for a container you configure directly. The RDS certificate authority isn’t in the system trust store, so mount its bundle and name it in the connection string.

# Core
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://+:8080
BROCH_MASTER_KEY=<generated-value>
API__WILDCARDHOSTNAME=broch.{your-domain}
# Database (Managed)
DATABASE__PROVIDER=PostgreSQL
ConnectionStrings__BrochConnection=Host=<rds-endpoint>;Database=broch;Username=<user>;Password=<password>;SSL Mode=VerifyFull;Root Certificate=/etc/broch/db-ca/rds-global-bundle.pem
# Auth
AUTHENTICATION__PROVIDER=Okta
AUTHENTICATION__DOMAIN={your-org}.okta.com
AUTHENTICATION__CLIENTID=<your-client-id>
AUTHENTICATION__CLIENTSECRET=<your-client-secret>
AUTHENTICATION__ADMINROLES=broch_admin
# Logging
BROCHLOGGING__PROVIDER=DataDog
BROCHLOGGING__DATADOG__APIKEY=<your-api-key>
BROCHLOGGING__DATADOG__SERVICENAME=broch-prod
BROCHLOGGING__DATADOG__ENVIRONMENT=production

Never commit secrets (license keys, client secrets, connection strings, API keys) to version control. Use your platform’s secure secret storage:

  • Docker Compose: the .env next to docker-compose.yml, mode 600, never committed. Broch reads environment variables only, not Docker secrets files.
  • Kubernetes: Kubernetes secrets
  • Azure: Azure Key Vault
  • AWS: AWS Secrets Manager
  • DigitalOcean: the Droplet’s root-only .env

Contact Broch at [email protected] for configuration questions or deployment guidance.