bambuddy/.env.example
Marian 77c9bdd694 fix(oidc): reject an unrecognized boolean instead of guessing
_env_bool returned the default for anything outside {true,1,yes}, so
BAMBUDDY_OIDC_REQUIRE_EMAIL_VERIFIED=on silently read as OFF and
BAMBUDDY_OIDC_ENABLED=on silently disabled the provider -- the exact
opposite of what .env.example claimed. Unrecognized values now raise
EnvOIDCConfigError, caught in _apply_env_oidc_provider the same way a
bad DEFAULT_GROUP or a ValidationError already is: logged and left
running, never released on a typo.

Also promotes _env_bool to env_bool now that it has a call site in
auth.py, and corrects the boolean-parsing sentence in .env.example.
2026-08-01 09:17:33 +00:00

129 lines
6.3 KiB
Text

# BambuTrack Environment Configuration
# Copy this file to .env and adjust values as needed
# Debug mode (true = DEBUG logging, false = production with INFO logging)
DEBUG=true
# Log level (only used when DEBUG=false)
# Options: DEBUG, INFO, WARNING, ERROR
LOG_LEVEL=INFO
# Enable file logging (logs written to logs/bambutrack.log)
LOG_TO_FILE=true
# Home Assistant Integration (for HA Add-on deployments)
# When both HA_URL and HA_TOKEN are set, Home Assistant integration is automatically enabled
# and these values override any database settings (read-only in UI)
# HA_URL=http://supervisor/core
# HA_TOKEN=your-long-lived-access-token
# Trusted iframe origins (#1191) — comma-separated list of scheme://host[:port]
# origins permitted to embed Bambuddy via <iframe>. Defaults to empty (strict:
# only same-origin embedding allowed). Set this to your Home Assistant origin
# when using the HA Webpage dashboard panel, since HA on port 8123 and Bambuddy
# on port 8000 are different origins to the browser. Wildcards, paths, and
# non-http(s) schemes are rejected at startup with a warning.
# TRUSTED_FRAME_ORIGINS=http://homeassistant.local:8123
# MFA at-rest encryption key (#1219) — Fernet, base64-encoded 32 bytes.
# Auto-generated and stored in DATA_DIR/.mfa_encryption_key on first startup
# if unset. Set explicitly to manage the key out-of-band (e.g. via a secret
# manager).
# Generate with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
#
# NOTE: Local backups (.zip) include the auto-generated key file, so a backup
# is self-contained. If you set this variable explicitly, ensure your backups
# also store the value separately (otherwise an encrypted backup cannot be
# restored after key loss).
# MFA_ENCRYPTION_KEY=
# External library folders (GHSA-r2qv follow-up) — colon-separated list of
# host paths that users are permitted to register as external library
# folders via Settings → Library → "Add external folder".
#
# Empty (the default) means the external-folder feature is DISABLED:
# attempts to register one return HTTP 400. Set this to one or more
# absolute paths to opt in. Paths that fall inside Bambuddy's own
# DATA_DIR / LOG_DIR / static dir are always rejected regardless of
# this value.
#
# Example for a single NAS mount:
# BAMBUDDY_EXTERNAL_ROOTS=/mnt/nas/3d-prints
# Example for two roots:
# BAMBUDDY_EXTERNAL_ROOTS=/mnt/nas/3d-prints:/srv/library
#
# In Docker, also bind-mount the host path into the container at the same
# location (see docker-compose.yml for the matching volume snippet).
# BAMBUDDY_EXTERNAL_ROOTS=
# Local-login recovery bypass (#1589) — set to "true" / "1" / "yes" to
# accept username + password credentials on /auth/login (and to allow the
# /auth/forgot-password flow) even when the in-app setting "Disable local
# login" is turned on. This is the documented "SSO is broken, let me back
# in" path for an operator whose only normal sign-in route is via OIDC.
# /auth/advanced-auth/status also reports local_login_enabled=true while
# this is set, so the login page shows the credentials form to match.
# LDAP is governed by its own ldap_enabled toggle and is not affected.
# Leave unset for normal operation.
# BAMBUDDY_LOCAL_LOGIN=true
# --- OIDC provider from the environment (#2593) ------------------------------
# Defines ONE OIDC provider declaratively, for deployments that are managed by
# compose files or GitOps and never touch the settings UI. Providers created in
# the UI are unaffected and keep working alongside this one.
#
# Activates only when all four required vars below are set; an empty value
# counts as unset. The provider is written on startup and re-applied on every
# boot, so the UI shows it as read-only and the API refuses to change it -- an
# edit there would be reverted at the next restart anyway.
#
# Removing the vars DISABLES the provider rather than deleting it: accounts
# linked to it would otherwise lose their link permanently. Re-adding the vars
# enables it again with those links intact.
#
# If you lock yourself out, BAMBUDDY_LOCAL_LOGIN=true above is the way back in.
#
# Required:
# BAMBUDDY_OIDC_NAME=Keycloak
# BAMBUDDY_OIDC_ISSUER_URL=https://sso.example.com/realms/main
# BAMBUDDY_OIDC_CLIENT_ID=bambuddy
# BAMBUDDY_OIDC_CLIENT_SECRET=your-client-secret
#
# Optional, shown with their defaults:
# BAMBUDDY_OIDC_SCOPES=openid email profile
# BAMBUDDY_OIDC_ENABLED=true
# BAMBUDDY_OIDC_AUTO_CREATE_USERS=false
# BAMBUDDY_OIDC_AUTO_LINK_EXISTING=false
# BAMBUDDY_OIDC_EMAIL_CLAIM=email
# BAMBUDDY_OIDC_REQUIRE_EMAIL_VERIFIED=true
# BAMBUDDY_OIDC_ICON_URL=
# BAMBUDDY_OIDC_AUTOLOGIN=false
# BAMBUDDY_OIDC_DEFAULT_GROUP=
#
# Booleans accept true/1/yes or false/0/no (case-insensitive). Blank or unset
# uses the default; any other value is rejected and the provider is skipped.
#
# DEFAULT_GROUP is the group new users land in when AUTO_CREATE_USERS is on;
# without it they get Viewers. It matches a group NAME exactly (case-sensitive)
# -- group ids are assigned per install, so the same compose file would point at
# a different group on every deployment. A name that matches no group is
# refused: the provider is left as it was and the reason is logged, rather than
# quietly creating under-privileged users the locked UI could not correct. On a
# FIRST boot that means no provider is created at all and no SSO button appears
# -- create the group first. Removing the variable clears the group again.
#
# AUTO_LINK_EXISTING binds an OIDC identity to an existing local account with
# the same email address. With EMAIL_CLAIM=email it is refused unless
# REQUIRE_EMAIL_VERIFIED=true, because an identity provider that does not
# verify addresses would let anyone claim someone else's account. The whole
# config is then skipped and logged; the app still starts.
#
# ISSUER_URL must be https:// and publicly reachable -- private, loopback,
# link-local, numeric-encoded and IPv4-mapped hosts are rejected. An in-cluster
# URL like http://keycloak:8080 is refused with a single log line and no SSO
# button; use the externally-reachable HTTPS issuer URL instead.
#
# NAME is matched against the existing providers on every boot: setting it to
# the name of one you already created in the UI ADOPTS and OVERWRITES it (its
# issuer, client id and secret are replaced and it becomes read-only). Pick a
# name that doesn't collide unless that takeover is intended.