# Environment Variables WireBuddy reads configuration from process environment variables. Local starts through `python run.py` also load `.env`; the configuration loader retains `settings.env` as a lower-precedence compatibility source. Docker Compose uses the root `.env` file explicitly in the documented commands. Most reverse-proxy and origin-dependent behavior (CSRF, passkeys, Host-header validation, secure cookies) auto-derives from a single `WIREBUDDY_PUBLIC_ORIGIN` setting. Configure that first; only add the more specific variables below if you have a concrete reason to override the derived default. ## Quick Configuration ```bash cp .env-example .env python3 -c "import secrets; print(secrets.token_urlsafe(32))" ``` Store the generated value in `.env`: ```bash WIREBUDDY_SECRET_KEY= LOG_LEVEL=INFO TZ=Etc/UTC ``` Start the supplied Docker deployment with: ```bash docker compose --env-file .env -f docker/docker-compose.yml up -d ``` ## Core Application ### `WIREBUDDY_SECRET_KEY` Required in master mode. It encrypts WireGuard private keys, preshared keys, OTP secrets, and other sensitive values and must contain at least 32 UTF-8 bytes. ```bash WIREBUDDY_SECRET_KEY= ``` Generate it with either: ```bash openssl rand -base64 32 python3 -c "import secrets; print(secrets.token_urlsafe(32))" ``` !!! danger Never commit, rotate casually, or lose this key. Existing encrypted data cannot be recovered with a different key. The key is not required in node mode because enrolled nodes authenticate with their node credentials. ### `SERVER_MODE` Selects the process role: - `master`: web UI, API, database, DNS, scheduling, and node management - `node`: remote WireGuard node daemon without the web UI Default: `master`. ### `LOG_LEVEL` Accepted values: `CRITICAL`, `ERROR`, `WARNING`, `INFO`, and `DEBUG`. Default: `INFO`. Invalid values fall back to `INFO`. ### `TZ` IANA time-zone name used by scheduled tasks and UI formatting. ```bash TZ=Europe/Berlin ``` Docker default: `Etc/UTC`. ### `WIREBUDDY_DATA_DIR` Base directory for persistent data. The database, TSDB, DNS files, certificates, and GeoIP databases live below it. - Local default: `/data` - Supplied Docker Compose value: `/app/data` ### `WIREBUDDY_DEV_RELOAD` Set to `true`, `1`, or `yes` to enable Uvicorn reload when starting through `python run.py`. Development only. ## Web Server ### `WIREBUDDY_HOST` Docker-entrypoint override for the web bind address. Without this override, the entrypoint reads **Only listen on Localhost** from the database and otherwise listens on `0.0.0.0` for a fresh installation. ```bash WIREBUDDY_HOST=127.0.0.1 ``` ### `WIREBUDDY_PORT` Docker-entrypoint override for the GUI port. Valid range: `1`–`65535`. Without this override, the entrypoint uses the database setting **HTTP Port (GUI)**. Fresh-installation default: `8000`. The supplied Compose file always sets `WIREBUDDY_PORT`, so there the database setting has no effect. ```bash WIREBUDDY_PORT=8080 ``` `HOST` and `PORT` are not WireBuddy configuration variables. ### `UVICORN_GRACEFUL_SHUTDOWN_TIMEOUT` Docker Uvicorn graceful-shutdown timeout in seconds. Accepted range: `1`–`300`. Default: `8`. !!! note The web server is single-worker only and this is not configurable. The job queue, rate limiter, and session/MFA caches live in process memory, so a second worker would make that state diverge between processes. ## Reverse Proxy and Origin Handling ### `WIREBUDDY_PUBLIC_ORIGIN` Canonical public URL of this instance, e.g. `https://vpn.example.com`. Configuring this alone derives: - CSRF allowed origins - The passkey/WebAuthn relying-party ID and expected origin - The Host-header allowlist (`TrustedHostMiddleware`), unless `WIREBUDDY_ALLOWED_HOSTS` is set explicitly - Secure cookie flags and HSTS — enabled automatically for `https://` origins ```bash WIREBUDDY_PUBLIC_ORIGIN=https://vpn.example.com ``` ### `WIREBUDDY_TRUSTED_PROXIES` Comma-separated reverse-proxy IPs/CIDRs. This single variable is used for: - Uvicorn's `--forwarded-allow-ips` (which peers may set `X-Forwarded-*`) - Application-level client-IP extraction and HTTPS-cookie detection - The node mTLS client-certificate fingerprint header (master side) Default: `127.0.0.0/8,::1/128` for cookie/HTTPS detection and Uvicorn's forwarded-header trust (a local reverse proxy on the same host just works). The public `/status` page and node mTLS fingerprint trust are more sensitive and default to trusting **nothing** beyond loopback until this is set explicitly — see [Status Page](status-page.md). ```bash WIREBUDDY_TRUSTED_PROXIES=192.168.1.10/32 ``` `*` is rejected by the Docker entrypoint. ### `WIREBUDDY_CSRF_ALLOWED_ORIGINS` Comma-separated additional origins accepted by CSRF origin validation, beyond `WIREBUDDY_PUBLIC_ORIGIN`. Only needed when serving under multiple hostnames. ```bash WIREBUDDY_CSRF_ALLOWED_ORIGINS=https://vpn2.example.com ``` ### `WIREBUDDY_ALLOWED_HOSTS` Optional comma-separated Host-header allowlist. Derived automatically from the hostname in `WIREBUDDY_PUBLIC_ORIGIN` when unset. Set this explicitly only to accept additional hostnames or when no public origin is configured. If neither is set, Host-header validation is off and startup logs a warning, or only an informational message when the listener is bound to loopback. ```bash WIREBUDDY_ALLOWED_HOSTS=vpn.example.com,localhost ``` ### `FORCE_HTTPS_COOKIES` Forces the `Secure` attribute on authentication and CSRF cookies even when HTTPS is not otherwise detected. Secure cookies and HSTS are already enabled automatically when `WIREBUDDY_PUBLIC_ORIGIN` uses `https://`; this override is only needed for edge cases such as a TLS-terminating load balancer without a configured public origin. Default: disabled (except when derived from `WIREBUDDY_PUBLIC_ORIGIN`). !!! note Not needed when **Settings → General → Serve GUI over HTTPS** is enabled. WireBuddy then terminates TLS itself, so the request scheme is already `https` and cookies are marked `Secure` without an override. See [Built-in HTTPS Listener](security.md#built-in-https-listener). ### `WIREBUDDY_FORCE_HSTS` Always emits HSTS even when TLS terminates at a proxy and the upstream request appears as HTTP. Default: disabled. HSTS is otherwise emitted automatically when `WIREBUDDY_PUBLIC_ORIGIN` uses `https://`, or when the request is detected as HTTPS. ## Passkeys ### `PASSKEY_RP_ID` Optional WebAuthn relying-party ID override. Derived automatically from `WIREBUDDY_PUBLIC_ORIGIN` when unset; falls back to the request host for localhost development. ### `PASSKEY_RP_NAME` WebAuthn relying-party display name. Default: `WireBuddy`. ### `MAX_PASSKEYS_PER_USER` Maximum registered passkeys per account. Values are clamped to `1`–`100`. Default: `20`. ## Node Mode ### `WIREBUDDY_ENROLLMENT_TOKEN` Required for first node enrollment. Create it from the master's **Nodes** page. The token contains the master URL, node ID, and bootstrap API secret. ### `WIREBUDDY_ENROLLMENT_VERIFY_KEY` HMAC key used to verify the enrollment token locally. Required for normal first enrollment and generated alongside the enrollment token. ### `WIREBUDDY_MASTER_CA_FILE` Optional path to a custom CA file used to verify the master's HTTPS certificate. System CAs are used when unset. ```bash WIREBUDDY_MASTER_CA_FILE=/app/data/certs/master-ca.pem ``` ### `WIREBUDDY_NODE_SYNC_INTERVAL` Normal synchronization interval in seconds. Minimum: `5`; default: `30`. ### `WIREBUDDY_NODE_SYNC_INTERVAL_FAST` Fallback interval while SSE is disconnected. Minimum: `1`; default: `5`. ### `WIREBUDDY_ENROLLMENT_RETRY_ATTEMPTS` Enrollment retries after transient failures. Minimum: `1`; default: `3`. ### `WIREBUDDY_NO_FIREWALL_FIX` Disables the node's automatic DNS-related firewall correction when set to `1`, `true`, or `yes`. Default: disabled, so the correction is active. ### Node Development Overrides The following switches weaken enrollment or transport validation and are for isolated development/migration scenarios only: - `WIREBUDDY_ALLOW_INSECURE_MASTER_HTTP=1` - `WIREBUDDY_ALLOW_UNVERIFIED_ENROLLMENT_TOKEN=1` - `WIREBUDDY_ALLOW_LEGACY_NODE_SECRET=1` Do not enable them in production. `WIREBUDDY_MASTER_URL` is not read by the current node daemon; the master URL is carried in the enrollment token and then persisted in node state. ## GeoIP GeoIP database paths and download URLs auto-resolve under `WIREBUDDY_DATA_DIR` with a built-in download source; overriding them is only needed for air-gapped installs or mirrored downloads. ### `WIREBUDDY_GEOIP_DB_PATH` Explicit GeoLite2 City database path. Default: `/geolite2/GeoLite2-City.mmdb`. ### `WIREBUDDY_ASN_DB_PATH` Explicit GeoLite2 ASN database path. Default: `/geolite2/GeoLite2-ASN.mmdb`. ### `WIREBUDDY_GEOIP_CITY_DOWNLOAD_URL` Optional HTTPS download URL for the City database. ### `WIREBUDDY_GEOIP_ASN_DOWNLOAD_URL` Optional HTTPS download URL for the ASN database. ### `WIREBUDDY_GEOIP_ALLOWED_HOSTS` Additional comma-separated HTTPS hosts allowed for custom GeoIP URLs and redirects. The built-in GitHub hosts remain allowed. ### `WIREBUDDY_GEOIP_CACHE_SIZE` In-memory GeoIP lookup cache size, clamped to `128`–`65536`. Default: `4096`. ## Security and Runtime Tuning ### `WIREBUDDY_CLEANUP_STALE_INTERFACES` Opt-in cleanup of active WireBuddy-managed WireGuard interfaces that no longer have matching configuration files. Disabled by default because cleanup is destructive. ### `WIREBUDDY_MANAGE_RESOLV_CONF` Allows WireBuddy to point `/etc/resolv.conf` at its managed Unbound resolver. Default: disabled. ### `WIREBUDDY_REQUIRE_HTTPS_AUTH` Opt-in. Set to `true`, `1`, or `yes` to reject authentication over plaintext HTTP. When enabled, password logins and node bearer/enrollment authentication are refused unless the request arrives over HTTPS. A single implicit exception applies to loopback peers, so local HTTP development keeps working. Default: disabled. With the flag off and the built-in HTTPS listener off, plaintext authentication is allowed but logs a warning, preserving the historical behaviour for documented plain-HTTP LAN installs. This flag is independent of **Settings → General → Serve GUI over HTTPS**: enabling the built-in HTTPS listener already forces the same rejection, and this variable additionally enforces it when the listener is off (for example behind a TLS-terminating reverse proxy). See [Security Configuration](security.md). ### `WIREBUDDY_RATE_LIMIT_UI_HEAVY` Rate limit string (`N/second|minute|hour|day`) for expensive UI routes; an invalid value stops startup. Default: `60/minute`. ### Login Lockout Tuning Login lockouts use three policies. Defaults are: | Variable | Default | |---|---:| | `WIREBUDDY_LOGIN_IP_MIN_FAILURES` | `5` | | `WIREBUDDY_LOGIN_IP_BASE_LOCKOUT_SECONDS` | `30` | | `WIREBUDDY_LOGIN_IP_MAX_LOCKOUT_SECONDS` | `86400` | | `WIREBUDDY_LOGIN_USER_IP_MIN_FAILURES` | `3` | | `WIREBUDDY_LOGIN_USER_IP_BASE_LOCKOUT_SECONDS` | `30` | | `WIREBUDDY_LOGIN_USER_IP_MAX_LOCKOUT_SECONDS` | `3600` | | `WIREBUDDY_LOGIN_USERNAME_MIN_FAILURES` | `20` | | `WIREBUDDY_LOGIN_USERNAME_BASE_LOCKOUT_SECONDS` | `60` | | `WIREBUDDY_LOGIN_USERNAME_MAX_LOCKOUT_SECONDS` | `300` | These values must be positive integers. Route-level request limits remain defined by the application. ### `WIREBUDDY_PBKDF2_ITERATIONS` PBKDF2 work factor used by vault key derivation. Default: `480000`; values are clamped to `310000`–`2000000`. Changing this value after encrypted data has been written can prevent existing vault values from being decrypted. Treat it as an immutable deployment choice. ### `WIREBUDDY_DEPLOYMENT_ID` Optional deployment-specific vault derivation context. Changing or removing it after encrypted values exist makes those values unreadable. ### `WIREBUDDY_RUNTIME_DIR` Directory for the process banner lock. Default: `/run/wirebuddy`. ## Development and CI ### `WIREBUDDY_SKIP_APPLICATION_LOCK` Set to `1`, `true`, or `yes` to skip the exclusive lock on the data directory. The lock makes a second control plane on the same data directory fail at startup. Use this only on a filesystem without `flock` support (some network filesystems) and only if you can guarantee that a single instance runs; WireBuddy logs a warning and cannot detect a second instance when it is set. ### `WIREBUDDY_SKIP_NETWORK_CHECK` Skips Docker host-network verification. Use only in tests or CI; production Compose does not set it. ### `WIREBUDDY_TEST_MODE` and `WIREBUDDY_MIN_GEOIP_SIZE` Relax GeoIP fixture size checks for tests. They are not production settings and should only be set by the test suite itself, never in `.env`. ### `TESTING` Used by test helpers and passkey test paths. Do not enable in production. ## Settings Managed in the UI The following are database settings, not environment variables: - GUI port and localhost-only binding (unless overridden by `WIREBUDDY_PORT`/`WIREBUDDY_HOST` in Docker) - Swagger enablement - public status-page enablement - WireGuard, DNS, speed-test, backup, and retention settings Variables such as `SWAGGER_ENABLED`, `SESSION_COOKIE_*`, `RATELIMIT_*`, `CORS_ORIGINS`, `HOST`, `PORT`, and `WORKERS` are not read by the current application. ## Precedence ### Local `python run.py` 1. Existing process environment 2. Root `.env` 3. Compatibility `settings.env` 4. Application defaults and database settings ### Docker Compose 1. Compose `environment` entries 2. Values interpolated from the file supplied with `--env-file` 3. Image/entrypoint defaults and database settings ## Verifying Effective Configuration ```bash docker compose --env-file .env -f docker/docker-compose.yml config docker compose --env-file .env -f docker/docker-compose.yml exec wirebuddy env | sort ``` Be careful when sharing this output because it contains the secret key and possibly enrollment credentials. ## Related - [Docker Setup](../getting-started/docker.md) - [Security Configuration](security.md) - [Multi-Node Deployment](../features/multi-node.md)