From 934967b9df93ab9f880b3d18e78aa7247164e1fe Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Sat, 25 Jul 2026 17:46:12 +0200 Subject: [PATCH] docs: document remaining env vars in env templates --- .env.dev.example | 10 +++ .env.example | 159 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) diff --git a/.env.dev.example b/.env.dev.example index efc75a09..d26b9f14 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -39,6 +39,16 @@ SETTINGS_SYNC_ENABLED=true LOG_FORMAT=text LOG_LEVEL=debug +# ============================================================================= +# Plugin Development +# ============================================================================= + +# Load plugins from a directory on disk instead of installing them as ZIPs. +# Each immediate subfolder is one plugin and needs a manifest.json. When the +# manifest's entrypoint exists under src/, it's bundled on demand with esbuild, +# so you can edit sources and just refresh the browser. +# PLUGIN_DEV_DIR=../my-plugins + # ============================================================================= # Login Page Customization (optional) # ============================================================================= diff --git a/.env.example b/.env.example index 2d47077f..065c9f92 100644 --- a/.env.example +++ b/.env.example @@ -19,6 +19,16 @@ JMAP_SERVER_URL=https://your-jmap-server.com # Access-Control-Allow-Origin header, or browser requests will be blocked. # ALLOW_CUSTOM_JMAP_ENDPOINT=true +# Offer several JMAP servers on the login form. JSON array; each entry needs +# id, label, and url. "domains" and a per-server "oauth" block are optional. +# Prefer configuring this from the admin dashboard - the env form exists for +# stateless deployments. +# JMAP_SERVERS=[{"id":"eu","label":"Europe","url":"https://eu.example.com","domains":["example.com"]},{"id":"us","label":"US","url":"https://us.example.com","oauth":{"clientId":"webmail-us"}}] + +# Pick the server automatically from the domain of the address the user types, +# matching against each entry's "domains" list. Default: false. +# JMAP_SERVER_AUTO_PICK_BY_DOMAIN=true + # ============================================================================= # Stalwart Mail Server Integration # ============================================================================= @@ -59,6 +69,19 @@ JMAP_SERVER_URL=https://your-jmap-server.com # OAuth issuer's public hostname resolves to an internal IP from this server. # OAUTH_ALLOW_PRIVATE_ENDPOINTS=true +# Replace the scopes requested at authorization. Space-separated. Leave unset +# to use the defaults the client already asks for. +# OAUTH_SCOPES=openid email profile offline_access + +# Append scopes instead of replacing them. Use this when your IdP needs one +# extra scope and you don't want to restate the defaults. +# OAUTH_EXTRA_SCOPES=groups + +# Send the user straight to the identity provider, skipping the login form. +# Intended for embedded deployments where the parent app already authenticated +# them. Default: false. +# AUTO_SSO_ENABLED=true + # ============================================================================= # Session & Security # ============================================================================= @@ -132,6 +155,17 @@ JMAP_SERVER_URL=https://your-jmap-server.com # so the instance id and consent choice survive upgrades. # TELEMETRY_DATA_DIR=./data/telemetry +# Legacy kill switch, honoured only when BULWARK_TELEMETRY is unset. +# BULWARK_TELEMETRY_DISABLED=1 + +# Let heartbeats reach a private/loopback address. Off by default as an SSRF +# guard; only useful when running a collector locally during development. +# BULWARK_TELEMETRY_ALLOW_PRIVATE=1 + +# Report a fixed Stalwart version instead of probing the JMAP server's Server +# header. Useful when a proxy strips that header. +# STALWART_VERSION=0.16.0 + # ============================================================================= # Server Listen Address # ============================================================================= @@ -197,6 +231,12 @@ JMAP_SERVER_URL=https://your-jmap-server.com # Should match your app's main background color. Default: #ffffff # PWA_BACKGROUND_COLOR=#ffffff +# Screenshots shown in the browser's install prompt. Absolute URLs or paths +# relative to public/. Both are optional; per-domain overrides are available +# through DOMAIN_BRANDING. +# PWA_SCREENSHOT_MOBILE_URL=/branding/screenshot-mobile.png +# PWA_SCREENSHOT_DESKTOP_URL=/branding/screenshot-desktop.png + # --------------------------------------------------------------------------- # Logos # --------------------------------------------------------------------------- @@ -234,6 +274,23 @@ LOGIN_COMPANY_NAME=Bulwark Webmail # URL for the company website link on the login page. LOGIN_WEBSITE_URL=https://bulwarkmail.org +# Cap the login logo's rendered size. Any CSS length ("120px", "8rem"). +# Unset means the logo renders at its natural size. +# LOGIN_LOGO_MAX_HEIGHT=96px +# LOGIN_LOGO_MAX_WIDTH=320px + +# Hide parts of the login page. All default to true. +# Turn the heading and subtitle off when the logo already reads as the brand. +# LOGIN_SHOW_HEADING=false +# LOGIN_SHOW_SUBTITLE=false +# +# Hide the optional TOTP field. A server that requires TOTP (totp_required) +# still shows it regardless of this setting. +# LOGIN_SHOW_TOTP=false +# +# Hide the version number, so it isn't disclosed to unauthenticated visitors. +# LOGIN_SHOW_VERSION=false + # --------------------------------------------------------------------------- # Per-domain branding overrides (optional) # --------------------------------------------------------------------------- @@ -266,6 +323,108 @@ LOGIN_WEBSITE_URL=https://bulwarkmail.org # your own directory (e.g. http://localhost:3001 for local development). # EXTENSION_DIRECTORY_URL=https://extensions.bulwarkmail.org +# ============================================================================= +# Admin Dashboard Access +# ============================================================================= + +# Bootstrap password for the admin dashboard. Read only when admin.json does +# not already exist; the app hashes it, writes admin.json, and logs a warning +# telling you to remove this variable. Without it (and without the setup +# wizard) the admin dashboard stays disabled. +# Accepts a plaintext password or an existing hash. +# ADMIN_PASSWORD=change-me + +# Admin session lifetime in seconds. Default: 3600 (1 hour). +# ADMIN_SESSION_TTL=3600 + +# How many trusted reverse proxies sit in front of the app. The client IP is +# taken that many entries from the right of X-Forwarded-For, so an attacker +# can't spoof it by prepending values. Default: 1. +# TRUSTED_PROXY_DEPTH=2 + +# Allow search engines to index the app (robots.txt / noindex). Default: false. +# SEARCH_ENGINE_INDEXING=true + +# ============================================================================= +# Cookies, Embedding & Reverse Proxies +# ============================================================================= + +# SameSite attribute for session cookies: lax (default), strict, or none. +# Embedding the app cross-origin in an iframe requires "none". +# COOKIE_SAME_SITE=none + +# Force the Secure flag on cookies. Defaults to on when NODE_ENV=production or +# COOKIE_SAME_SITE=none. Set to false only for local HTTP development. +# COOKIE_SECURE=false + +# Who may frame the app, as a CSP frame-ancestors value. Defaults to 'none', +# which blocks all framing. Space-separate multiple origins. +# ALLOWED_FRAME_ANCESTORS=https://portal.example.com + +# Origin of the parent page when embedded, used for postMessage handshakes. +# NEXT_PUBLIC_PARENT_ORIGIN=https://portal.example.com + +# ============================================================================= +# Update Check +# ============================================================================= + +# The app periodically checks for new releases and shows a notice. Set to +# "off" (or false/0/no) to disable the check entirely. +# BULWARK_UPDATE_CHECK=off + +# Override the endpoint it checks. Takes priority over the on-disk state file. +# An explicit empty value also disables the check. +# BULWARK_UPDATE_CHECK_URL=https://updates.example.com/bulwark.json + +# Where the check stores its state. Default: ./data/version-check +# VERSION_CHECK_DATA_DIR=./data/version-check + +# ============================================================================= +# Translation Proxy (optional) +# ============================================================================= + +# /api/translate defaults to the public MyMemory API, which needs no setup. +# Point it at a LibreTranslate instance instead to keep message text on +# infrastructure you control. LibreTranslate also auto-detects the source +# language natively. +# LIBRETRANSLATE_URL=https://libretranslate.example.com +# LIBRETRANSLATE_API_KEY= + +# ============================================================================= +# Web Push +# ============================================================================= + +# Push notifications go through a hosted relay so self-hosters don't need +# their own VAPID keys and Firebase project. Point this at your own relay to +# avoid the default. Build-time variable. +# Default: https://notifications.relay.bulwarkmail.org +# NEXT_PUBLIC_PUSH_RELAY_URL=https://push.example.com + +# ============================================================================= +# Demo Mode +# ============================================================================= + +# Serve fixture data instead of talking to a mail server. Default: false. +# DEMO_MODE=true + +# ============================================================================= +# Stalwart Impersonation (advanced) +# ============================================================================= + +# Lets a trusted platform mint a JWT that logs a user in without their +# password, using a Stalwart master account. Intended for embedded +# deployments where an outer platform already authenticated the user. +# +# SECURITY: this grants sign-in as any mailbox on the server. The endpoint +# returns 404 unless all three required variables below are set, so leaving +# them unset keeps the feature fully off. Treat the secret and the master +# password as you would a root credential. +# +# BULWARK_JWT_AUTH_SECRET= # required, >= 32 characters +# BULWARK_STALWART_MASTER_USER= # required, e.g. master@example.com +# BULWARK_STALWART_MASTER_PASSWORD= # required +# BULWARK_JWT_AUTH_ISSUER= # optional, default "platform-api/webmail" + # ============================================================================= # Internationalization # =============================================================================