# Environment variable reference The public [Portainer stack](../compose.yml) needs **no environment variables**. Its image supplies the runtime defaults; use the first-run setup wizard to set the application URL, connect services and configure notifications. The normal stack does not need a Dockerfile, source checkout or `.env` file. This reference also covers advanced/manual deployments, compatibility aliases, image-build inputs and repository-only tooling. A variable being listed here does **not** mean that it belongs in the public Compose file. ## Managed installation defaults and precedence - The image defaults `MAGENT_MANAGED_SECRETS` to `auto`. With no manually supplied `JWT_SECRET`, startup generates independent signing, encryption and setup keys once, then reloads them from `/app/data/bootstrap-secrets.json`. An existing explicit signing key selects the legacy/manual path. Do not switch an existing installation's key management, volume or keys just to match a fresh template. - Managed installations fix `SQLITE_PATH` to `/app/data/magent.db` and `API_DOCS_ENABLED` to `false`; these are not setup choices. Preserve the entire `/app/data` volume, including the private keys. Startup fails rather than silently replacing missing keys beside an existing database. - Set the browser-facing application URL in setup. Managed CORS accepts the configured same origin; do not configure `*` or invent an external API origin. Before a URL is saved, only the token-authorized first-administrator setup can claim the initial origin; arbitrary public requests do not establish trust. HTTPS is required for public hosting. A private LAN can use explicit HTTP. - Source defaults below describe `backend/app/config.py` before managed bootstrap or saved configuration is applied. Saved, supported application settings take precedence over their environment fallback. Security/bootstrap settings are deployment controls, not ordinary editable settings. Container listener ports are fixed by its process supervisor, not by application settings. - For manual deployments, environment variables are read at process startup. Restart/recreate after changing them. A `.env` file is loaded by the relevant Compose template's `env_file`, not automatically discovered by the application. Keep manual credentials stable across upgrades and offline restores. Defaults use JSON notation: `null` means unset, `""` means an empty string, `true`/`false` are booleans, and `@BUILD_NUMBER`/`@CHANGELOG` are bundled build metadata. Do not literally enter `null` or the `@...` labels into Portainer. Aliases in one row refer to the same setting; if multiple aliases are present, the first listed alias wins. Use only one. Never place secrets into browser- visible `NEXT_PUBLIC_*` variables, URLs, screenshots or public support reports. ## Core, authentication and storage | Variable / aliases | Source default | Purpose and managed-install behaviour | | --- | --- | --- | | `APP_NAME` | `"Magent"` | Backend application name. | | `CORS_ALLOW_ORIGIN` | `"http://localhost:3000"` | Legacy exact allowed browser origin. Managed installs use the URL confirmed in setup automatically; no Compose override needed. | | `SQLITE_PATH` | `"data/magent.db"` | SQLite database file. Managed container path is fixed to `/app/data/magent.db`; manual source deployments retain their existing path. | | `SQLITE_JOURNAL_MODE` | `"DELETE"` | SQLite journal mode; retain the default unless deliberately configuring storage behaviour. | | `JWT_SECRET` | `""` | Secret signing key. Generated/persisted in managed mode; manual mode requires a strong non-default value of at least 32 characters. | | `JWT_EXP_MINUTES` | `120` | Authentication token lifetime in minutes. | | `JWT_ISSUER` | `"magent"` | Expected JWT issuer. Changing it invalidates existing tokens. | | `JWT_AUDIENCE` | `"magent-web"` | Expected JWT audience. Changing it invalidates existing tokens. | | `SETTINGS_ENCRYPTION_KEY` | `null` | Secret Fernet key for stored integration credentials. Generated/persisted in managed mode. Preserve an existing manual key (or the existing legacy signing-key-derived configuration). | | `API_DOCS_ENABLED` | `false` | OpenAPI/interactive API documentation. Forced off in managed mode; leave off for public deployment. | | `AUTH_RATE_LIMIT_WINDOW_SECONDS` | `60` | Login rate-limit window in seconds. | | `AUTH_RATE_LIMIT_MAX_ATTEMPTS_IP` | `15` | Login attempts allowed per client IP per window. | | `AUTH_RATE_LIMIT_MAX_ATTEMPTS_USER` | `5` | Login attempts allowed per user identifier per window. | | `PASSWORD_RESET_RATE_LIMIT_WINDOW_SECONDS` | `300` | Password-reset rate-limit window in seconds. | | `PASSWORD_RESET_RATE_LIMIT_MAX_ATTEMPTS_IP` | `6` | Password-reset attempts allowed per IP per window. | | `PASSWORD_RESET_RATE_LIMIT_MAX_ATTEMPTS_IDENTIFIER` | `3` | Password-reset attempts allowed per account identifier per window. | | `ADMIN_USERNAME` | `"admin"` | Legacy bootstrap username when supplying an initial administrator password. Wizard-created administrators choose their own name. | | `ADMIN_PASSWORD` | `""` | Optional manual first-administrator password, minimum 12 characters. Leave empty for token-protected setup; never use a shared default password. | | `SETUP_TOKEN` | `""` | Secret one-time administrator-creation credential. Generated in managed mode; retrieve using `python -m app.container_bootstrap setup-token` in the container console. Not shown once the first administrator exists/setup is complete. | | `AUTH_COOKIE_NAME` | `"magent_auth"` | HttpOnly session-cookie name. | | `AUTH_COOKIE_SECURE` | `false` | Legacy cookie Secure flag; public HTTPS deployments require `true`. Managed mode derives the correct behaviour from its confirmed application URL. | | `AUTH_COOKIE_SAMESITE` | `"strict"` | Authentication cookie SameSite policy; retain `strict` unless deliberately evaluating a different deployment model. | | `AUTH_COOKIE_DOMAIN` | `null` | Cookie domain override; unset creates safer host-only cookies. | | `AUTH_STATE_COOKIE_NAME` | `"magent_logged_in"` | Non-secret UI login-state marker. The frontend expects its normal default. | ## Logs, request cache and issue follow-up | Variable / aliases | Source default | Purpose | | --- | --- | --- | | `LOG_LEVEL` | `"INFO"` | Application log verbosity. | | `LOG_FORMAT` | `"text"` | `text` for readable logs or `json` for structured collection. | | `LOG_FILE` | `"data/magent.log"` | Rotating application log; resolves to `/app/data/magent.log` in the combined image. | | `LOG_FILE_MAX_BYTES` | `20000000` | Maximum active log size before rotation, in bytes. | | `LOG_FILE_BACKUP_COUNT` | `10` | Number of rotated log files to keep. | | `LOG_HTTP_CLIENT_LEVEL` | `"INFO"` | Outbound integration HTTP logging verbosity. | | `LOG_BACKGROUND_SYNC_LEVEL` | `"INFO"` | Scheduled background-sync log verbosity. | | `REQUESTS_SYNC_TTL_MINUTES` | `1440` | Request-cache freshness period in minutes. | | `REQUESTS_STAGE_REFRESH_MINUTES` | `15` | Background request-stage refresh interval, from 1 to 1440 minutes. Short intervals increase integration traffic. | | `REQUESTS_POLL_INTERVAL_SECONDS` | `300` | Interval for checking whether a full request sync is due. | | `REQUESTS_DELTA_SYNC_INTERVAL_MINUTES` | `5` | Incremental new/changed request polling interval. | | `REQUESTS_FULL_SYNC_TIME` | `"00:00"` | Daily full request-cache rebuild time, `HH:MM`. | | `REQUESTS_CLEANUP_TIME` | `"02:00"` | Daily request-history cleanup time, `HH:MM`. | | `REQUESTS_CLEANUP_DAYS` | `90` | Request-history retention period in days. | | `REQUESTS_DATA_SOURCE` | `"prefer_cache"` | Request data-source strategy; prefer cached results by default. | | `ISSUE_CONFIRMATION_CONTACT_ATTEMPTS` | `2` | Confirmation emails after an issue is fixed; `0` closes without sending these emails. | | `ISSUE_CONFIRMATION_INTERVAL_VALUE` | `3` | Time between confirmation attempts and final closure wait, in the unit below. | | `ISSUE_CONFIRMATION_INTERVAL_UNIT` | `"days"` | Follow-up interval unit: `days`, `weeks` or `months`. | | `ARTWORK_CACHE_MODE` | `"remote"` | Artwork delivery mode; remote sources by default, local caching when configured. | ## Site appearance and login | Variable / aliases | Source default | Purpose | | --- | --- | --- | | `SITE_BUILD_NUMBER` | `@BUILD_NUMBER` | Bundled release build number; normally leave unchanged. | | `SITE_CHANGELOG` | `@CHANGELOG` | Bundled release changelog; normally leave unchanged. | | `SITE_BANNER_ENABLED` | `false` | Enable the signed-in sitewide announcement banner. | | `SITE_BANNER_MESSAGE` | `null` | Banner message. | | `SITE_BANNER_TONE` | `"info"` | Banner preset tone when custom colours are unset. | | `SITE_BANNER_BACKGROUND_COLOR` | `null` | Optional six-digit hexadecimal banner background colour, e.g. `#123456`. | | `SITE_BANNER_BORDER_COLOR` | `null` | Optional six-digit hexadecimal banner border colour. | | `SITE_LOGIN_MESSAGE` | `null` | Separate message on the logged-out login page. | | `SITE_LOGIN_SHOW_JELLYFIN_LOGIN` | `true` | Show the Jellyfin login option. | | `SITE_LOGIN_SHOW_LOCAL_LOGIN` | `true` | Show local Magent login. | | `SITE_LOGIN_SHOW_FORGOT_PASSWORD` | `true` | Show password recovery. | | `SITE_LOGIN_SHOW_SIGNUP_LINK` | `true` | Show invite signup. | | `SITE_NAV_SHOW_REQUESTS` | `true` | Show requests navigation. | ## Application URLs, proxy and TLS Configure these supported settings in setup/admin rather than adding environment entries to the public stack. Do not assume these settings reconfigure Docker port mappings or the bundled supervisor: it listens on frontend `3000` and backend `8000`, with only `3000` published. Terminate public HTTPS at a reverse proxy. Only explicitly trusted proxy addresses may supply forwarded headers. | Variable / aliases | Source default | Purpose | | --- | --- | --- | | `MAGENT_APPLICATION_URL` | `null` | Canonical browser-facing origin used by links and request-origin protection. Confirm it in setup; no initial environment value is required in managed mode. | | `MAGENT_APPLICATION_PORT` | `3000` | Preferred application port metadata for direct/local deployments; does not change the image listener or host port mapping. | | `MAGENT_API_URL` | `null` | Optional canonical API URL metadata. Normal users access same-origin `/api`; do not expose backend port 8000 publicly. | | `MAGENT_API_PORT` | `8000` | Preferred backend port metadata; does not change the image listener. | | `MAGENT_BIND_HOST` | `"0.0.0.0"` | Direct/local-hosting bind configuration; container supervisor retains its configured listeners. | | `MAGENT_PROXY_ENABLED` | `false` | Enable configured proxy-aware URL handling. | | `MAGENT_PROXY_BASE_URL` | `null` | Optional configured reverse-proxy public base URL. | | `MAGENT_PROXY_TRUST_FORWARDED_HEADERS` | `true` | Permit forwarding metadata only from trusted proxies. | | `MAGENT_PROXY_TRUSTED_PROXIES` | `"127.0.0.1,::1"` | Comma-separated trusted proxy addresses/networks; loopback by default. Do not broadly trust arbitrary clients. | | `MAGENT_PROXY_FORWARDED_PREFIX` | `null` | Optional reverse-proxy path prefix metadata. This is not a promise that every root-based frontend asset supports arbitrary subpaths. | | `MAGENT_SSL_BIND_ENABLED` | `false` | Direct-hosting TLS configuration; does not replace the bundled image's external HTTPS proxy. | | `MAGENT_SSL_CERTIFICATE_PATH` | `null` | Direct-hosting TLS certificate PEM path. | | `MAGENT_SSL_PRIVATE_KEY_PATH` | `null` | Secret direct-hosting TLS private-key PEM path. | | `MAGENT_SSL_CERTIFICATE_PEM` | `null` | Direct-hosting certificate PEM content. | | `MAGENT_SSL_PRIVATE_KEY_PEM` | `null` | Secret direct-hosting private-key PEM content. | ## Notification services Provider credentials are secrets. Configure them in the authenticated setup/admin UI, where sensitive saved values are encrypted; do not share webhook URLs or bot tokens in support logs. The master switch and each provider switch both apply. | Variable / aliases | Source default | Purpose | | --- | --- | --- | | `MAGENT_NOTIFY_ENABLED` | `false` | Master notification switch. | | `MAGENT_NOTIFY_EMAIL_ENABLED` | `false` | Enable SMTP email notifications. | | `MAGENT_NOTIFY_EMAIL_SMTP_HOST` | `null` | SMTP hostname/address. | | `MAGENT_NOTIFY_EMAIL_SMTP_PORT` | `587` | SMTP port, commonly 587 with STARTTLS or 465 with implicit TLS. | | `MAGENT_NOTIFY_EMAIL_SMTP_USERNAME` | `null` | SMTP login username. | | `MAGENT_NOTIFY_EMAIL_SMTP_PASSWORD` | `null` | Secret SMTP password/app password. | | `MAGENT_NOTIFY_EMAIL_FROM_ADDRESS` | `null` | Sender email address. | | `MAGENT_NOTIFY_EMAIL_FROM_NAME` | `null` | Sender display name. | | `MAGENT_NOTIFY_EMAIL_USE_TLS` | `true` | Use SMTP STARTTLS. | | `MAGENT_NOTIFY_EMAIL_USE_SSL` | `false` | Use implicit SMTP TLS instead of STARTTLS. | | `MAGENT_NOTIFY_DISCORD_ENABLED` | `false` | Enable Discord notifications. | | `MAGENT_NOTIFY_DISCORD_WEBHOOK_URL` | `null` | Secret Discord webhook URL, also usable for feedback routing. | | `MAGENT_NOTIFY_TELEGRAM_ENABLED` | `false` | Enable Telegram notifications. | | `MAGENT_NOTIFY_TELEGRAM_BOT_TOKEN` | `null` | Secret Telegram bot token. | | `MAGENT_NOTIFY_TELEGRAM_CHAT_ID` | `null` | Telegram destination chat/group/user ID. | | `MAGENT_NOTIFY_PUSH_ENABLED` | `false` | Enable push-provider notifications. | | `MAGENT_NOTIFY_PUSH_PROVIDER` | `"ntfy"` | Provider selector such as `ntfy`, `gotify`, `pushover` or `webhook`. | | `MAGENT_NOTIFY_PUSH_BASE_URL` | `null` | Push-service base URL. | | `MAGENT_NOTIFY_PUSH_TOPIC` | `null` | Push topic/channel name. | | `MAGENT_NOTIFY_PUSH_TOKEN` | `null` | Secret push-service token/API key. | | `MAGENT_NOTIFY_PUSH_USER_KEY` | `null` | Provider recipient key, such as a Pushover user key. | | `MAGENT_NOTIFY_PUSH_DEVICE` | `null` | Optional target device selector. | | `MAGENT_NOTIFY_WEBHOOK_ENABLED` | `false` | Enable generic webhook notifications. | | `MAGENT_NOTIFY_WEBHOOK_URL` | `null` | Generic notification webhook URL; may contain secret credentials. | | `MAGENT_ALLOW_PRIVATE_NOTIFICATION_TARGETS` | `false` | Explicitly allow private-network notification destinations. Keep disabled unless deliberately trusting an internal endpoint. | | `DISCORD_WEBHOOK_URL` | `null` | Legacy Discord feedback webhook fallback. Prefer the notification provider setting above. | ## Media integrations URLs must be reachable from the Magent container. `localhost` names the Magent container itself, not another application or the Docker host. Configure these through setup/admin; API keys and passwords are secret. Aliases are retained for existing installations. | Variable / aliases | Source default | Purpose | | --- | --- | --- | | `JELLYSEERR_URL`, `JELLYSEERR_BASE_URL` | `null` | Seerr/Jellyseerr request-service base URL. | | `JELLYSEERR_API_KEY`, `JELLYSEERR_KEY` | `null` | Seerr API key. | | `JELLYSTAT_URL`, `JELLYSTAT_BASE_URL` | `null` | Jellystat statistics-service base URL, including its base path if used. | | `JELLYSTAT_API_KEY` | `null` | Jellystat API key. | | `JELLYFIN_URL`, `JELLYFIN_BASE_URL` | `null` | Jellyfin server URL for authentication, user sync and library lookups. | | `JELLYFIN_API_KEY`, `JELLYFIN_KEY` | `null` | Jellyfin administrative API key. | | `JELLYFIN_PUBLIC_URL` | `null` | Browser-facing Jellyfin URL for watch/open buttons. | | `JELLYFIN_SYNC_TO_ARR` | `true` | Automatically add existing Jellyfin items to Sonarr/Radarr tracking where supported. | | `SONARR_URL`, `SONARR_BASE_URL` | `null` | Sonarr TV-service base URL. | | `SONARR_API_KEY`, `SONARR_KEY` | `null` | Sonarr API key. | | `SONARR_QUALITY_PROFILE_ID` | `null` | Default Sonarr quality profile; requests use Seerr's default if Magent has none configured. | | `SONARR_ROOT_FOLDER` | `null` | Sonarr TV root folder. | | `SONARR_QBITTORRENT_CATEGORY` | `"sonarr"` | Legacy qBittorrent category setting, retained for compatibility and hidden from the ordinary settings UI. | | `RADARR_URL`, `RADARR_BASE_URL` | `null` | Radarr movie-service base URL. | | `RADARR_API_KEY`, `RADARR_KEY` | `null` | Radarr API key. | | `RADARR_QUALITY_PROFILE_ID` | `null` | Default Radarr quality profile; requests use Seerr's default if Magent has none configured. | | `RADARR_ROOT_FOLDER` | `null` | Radarr movie root folder. | | `RADARR_QBITTORRENT_CATEGORY` | `"radarr"` | Legacy qBittorrent category setting, retained for compatibility and hidden from the ordinary settings UI. | | `BAZARR_URL`, `BAZARR_BASE_URL` | `null` | Bazarr subtitle-service base URL. | | `BAZARR_API_KEY`, `BAZARR_KEY` | `null` | Bazarr API key. | | `BAZARR_DEFAULT_LANGUAGE` | `"en"` | Default subtitle search language code. | | `PROWLARR_URL`, `PROWLARR_BASE_URL` | `null` | Prowlarr indexer-service base URL. | | `PROWLARR_API_KEY`, `PROWLARR_KEY` | `null` | Prowlarr API key. | | `QBIT_URL`, `QBITTORRENT_URL`, `QBITTORRENT_BASE_URL` | `null` | qBittorrent base URL for download status. | | `QBIT_USERNAME`, `QBITTORRENT_USERNAME` | `null` | qBittorrent login username. | | `QBIT_PASSWORD`, `QBITTORRENT_PASSWORD` | `null` | Secret qBittorrent password. | ## Additional runtime and image controls These variables are read outside `Settings`. Defaults below identify their actual consumer; builder values and supervisor values are not user-editable app settings. | Variable | Default / scope | Purpose | | --- | --- | --- | | `MAGENT_MANAGED_SECRETS` | Image: `auto` | Automatically use persistent generated secrets when no manual signing key is supplied. `true` explicitly opts in; `false` retains manual management. Existing keys must be preserved. | | `MAGENT_RUNTIME_MANAGED` | Internal bootstrap output: `1` for managed mode | Internal marker set by bootstrap for backend/frontend origin and cookie handling. It is not a supported user override; do not set it in Compose. | | `BACKGROUND_TASKS_ENABLED` | `true` | Run background schedulers/workers. `false` is useful for isolated tests, not normal service operation. | | `BRANDING_SOURCE` | `bundled` | Use bundled logo/favicon; `data` prefers custom assets under persistent data. | | `MAGENT_METRICS_ENABLED` | Disabled (empty) | `true` enables the separate Prometheus metrics listener. Do not expose it publicly. | | `MAGENT_METRICS_PORT` | `9108` | Metrics listener port when enabled. | | `MAGENT_METRICS_BIND` | `127.0.0.1` | Metrics listener bind address when enabled. | | `MAGENT_COMING_SOON` | Disabled (unset) | Frontend root-route holding page enabled only by the exact value `true`. | | `BACKEND_INTERNAL_URL` | Build/supervisor: `http://127.0.0.1:8000`; source fallback: `http://backend:8000` | Next.js internal API/branding rewrite destination, baked when building its configuration. Runtime overrides do not rebuild a published image's rewrites. | | `NEXT_PUBLIC_API_BASE` | `/api` | Browser API prefix. Public frontend values are baked at build time; never place credentials here. | | `NODE_ENV` | Image: `production` | Node/Next runtime mode. Development allows development-only CSP eval; do not override in public production. | | `NEXT_TELEMETRY_DISABLED` | Image/builder: `1` | Disable Next.js telemetry. | | `HOSTNAME` | Supervisor: `0.0.0.0` | Bundled standalone frontend listen address, explicitly set by supervisor. | | `PORT` | Supervisor: `3000` | Bundled standalone frontend port, explicitly set by supervisor. | | `PYTHONDONTWRITEBYTECODE` | Image: `1` | Do not write Python bytecode into the read-only image. | | `PYTHONUNBUFFERED` | Image: `1` | Flush Python stdout/stderr without buffering. | | `MAGENT_UID` | Build argument: `1000` | Image runtime user's UID. Not a runtime environment switch; rebuilding with a different UID also requires matching volume/tmpfs ownership. | | `MAGENT_GID` | Build argument: `1000` | Image runtime user's GID; same ownership caveat as UID. | ## Manual Compose and test tooling These optional variables belong to the advanced manual template or isolated verification tools, not the zero-input public Compose install. | Variable | Default / scope | Purpose | | --- | --- | --- | | `MAGENT_IMAGE` | Required by `docker-compose.hub.yml` | Explicit published image tag/digest for manual-secret installations. | | `MAGENT_BIND_ADDRESS` | `127.0.0.1` | Manual template frontend bind address. | | `MAGENT_HTTP_PORT` | `3000` | Manual template frontend host port. | | `PYTHON_BIN` | `python3` | Interpreter used by the backend quality gate. | | `MAGENT_IMAGE_MAX_MB` | `350` | Container smoke-test unpacked image size budget in MiB. | | `MAGENT_SMOKE_MANAGED` | `false` | Test generated managed secrets when true, or synthetic manual keys when false. | | `GITHUB_RUN_ID` | `local` | Optional CI identifier for disposable smoke-test resources. | ## Keeping this reference complete Run `python scripts/check_environment_docs.py`. The dependency-free check parses the Settings AST (including every alias and source default), scans explicit runtime environment reads, Docker build/runtime declarations, Compose variables and repository tooling. It never imports application settings, reads `.env`, contacts a service or prints secret values. Backend unit tests run the same check so newly declared variables and changed Settings defaults require documentation. This is the inventory of variables explicitly consumed/declared by Magent's source, not an enumeration of all knobs understood by Python, Node, Docker, OpenSSL or third-party libraries. Unsupported third-party/internal flags should not be used to bypass the packaged deployment defaults.