Environment Variables
The Apprise API container is highly configurable via environment variables.
Runtime Configuration
Section titled “Runtime Configuration”| Variable | Default | Description |
|---|---|---|
APPRISE_STATEFUL_MODE | hash | Controls the persistent storage backend.simple: Saves configs as human-readable files (/config/{KEY}.yaml). Recommended for most users.hash: Saves configs as indexed hashes. Efficient for high-volume.disabled: Disables persistent storage entirely (stateless only). Values are case-insensitive. |
APPRISE_STATELESS_MODE | enabled | Controls stateless /notify/ calls.enabled: Accept requests.disabled: Reject requests. If both notification modes are disabled, /status reports degraded. |
APPRISE_WORKER_COUNT | (Auto) | Number of Gunicorn workers. Defaults to (2 * CPUs) + 1. Set to 1 for low-resource environments. |
APPRISE_WORKER_MAX_REQUESTS | 1000 | Number of requests a worker handles before being recycled. Recycling releases accumulated memory. Lower this (e.g., 100) if workers are long-lived and memory growth is a concern. |
APPRISE_WORKER_MAX_REQUESTS_JITTER | 50 | Random offset added to APPRISE_WORKER_MAX_REQUESTS so workers do not restart together. |
APPRISE_WORKER_TIMEOUT | 300 | Worker timeout in seconds. |
APPRISE_BASE_URL | (None) | Set this if running behind a reverse proxy under a subpath (e.g., /apprise). |
APPRISE_ADMIN | yes | Lists all saved keys through /cfg and the Web UI. This works only when APPRISE_STATEFUL_MODE is simple. Set to no to hide the list. |
Security & Access
Section titled “Security & Access”| Variable | Default | Description |
|---|---|---|
STRICT_MODE | no | Container only. Allows known Apprise routes, returns 404 for unknown routes and 405 for unsupported methods, and applies tighter authentication rate limits that return 429 with Retry-After. |
APPRISE_CONFIG_LOCK | no | Hides configuration content and management from regular users. New accounts default to locked, and saved user access behaves as locked without being rewritten. Saved public access remains public because it already hides configuration content. |
APPRISE_AUTH_REQUIRED | no | Set to yes to enable authentication. When disabled, administrator settings and saved configuration logins are ignored. See Authentication and Access Control. |
APPRISE_USER | (None) | Optional administrator username used only when APPRISE_AUTH_REQUIRED=yes. It requires APPRISE_PASSWORD; colons are not allowed. |
APPRISE_PASSWORD | (None) | Optional administrator password used only when APPRISE_AUTH_REQUIRED=yes. It may be used without a username. Leave it unset to allow only existing configuration logins. |
APPRISE_BASIC_AUTH_REALM | Apprise API | Name shown in Basic Auth login prompts. It does not change the credentials. Use a different name for each instance sharing a host. |
APPRISE_WEB_AUTH_SECRET | (Generated) | Optional key that signs browser logins. When unset, a random key is created once and saved as .web_auth_secret in the configuration directory. Changing it signs browsers out without moving hash-mode configurations. |
APPRISE_TRUSTED_ORIGINS | (None) | Public addresses allowed to make browser changes, separated by commas. Use the full scheme://host[:port], such as https://apprise.example.com. Direct API clients such as curl are unaffected. |
ALLOWED_HOSTS | * | Space-delimited list of allowed Host headers. |
APPRISE_DENY_SERVICES | (Default List) | Comma-separated list of schemas to block (e.g., dbus, windows, macosx, gnome, syslog are blocked by default in Docker). |
APPRISE_ALLOW_SERVICES | (All) | Comma-separated list of allowed schemas. If set, only these services will work. |
Memory Impact of Service Filtering
Section titled “Memory Impact of Service Filtering”APPRISE_ALLOW_SERVICES and APPRISE_DENY_SERVICES do more than toggle which schemas are active. The Apprise API automatically evicts optional libraries from memory when every plugin that depends on them is disabled.
Each notification plugin that requires a heavy optional dependency declares it internally. When the last plugin using a given library is disabled, that library is removed from the Python runtime (sys.modules), freeing its associated objects. This happens at startup, before the first request is served.
The libraries subject to eviction and their estimated savings:
| Library | Used By | Freed Memory |
|---|---|---|
slixmpp | xmpp:// | ~20 MB |
paho | mqtt:// | ~4 MB |
gntp | growl:// | ~2 MB |
smpplib | smpp://, smpps:// | ~2 MB |
hid | blink1:// | ~2 MB |
pgpy | mailto://, mailtos:// (PGP only) | ~10 MB |
cryptography | simplepush://, fcm://, vapid:// | partial† |
†cryptography links against OpenSSL natively. The Python wrapper objects are
released, but the underlying shared library remains mapped by the OS for the
process lifetime.
Example: a deployment that only needs Telegram and NTFY:
APPRISE_ALLOW_SERVICES=tgram,ntfyThis disables every other plugin, causing slixmpp, paho, gntp, smpplib, and the cryptography wrappers to be evicted. Combined with APPRISE_WORKER_COUNT=1, this brings a single-worker container from the typical ~180 MB baseline down to approximately ~145 MB.
For a full guide on reducing container memory and RAM usage, see Resource Usage.
Storage & Limits
Section titled “Storage & Limits”| Variable | Default | Description |
|---|---|---|
APPRISE_ATTACH_SIZE | 200 | Maximum attachment size in MB. Set to 0 to disable attachments. |
APPRISE_UPLOAD_MAX_MEMORY_SIZE | 3 | Maximum size (MB) of request body kept in memory before spilling to disk. |
APPRISE_CONFIG_MAX_LENGTH | 512 | Maximum configuration payload size in KB. Cannot exceed APPRISE_UPLOAD_MAX_MEMORY_SIZE. |
APPRISE_STREAM_MEMORY_SIZE | 2 | Stream and result logs kept in memory before temporary disk storage, in MB. |
APPRISE_STREAM_DISK_SIZE | 256 | Temporary disk allowance for each live stream and result, in MB. |
APPRISE_STREAM_WORKER_COUNT | 4 | Active streams per Gunicorn worker process. The effective server-wide total is APPRISE_WORKER_COUNT * 4. |
APPRISE_STREAM_QUEUE_SIZE | 8 | Additional live streams allowed to queue per Gunicorn worker process. |
APPRISE_RECURSION_MAX | 1 | Max recursion depth for apprise:// calls to other servers. |
APPRISE_ALLOW_TEMPLATES | yes | Let a stored YAML configuration use a template: section and fill in ${NAME} markers. See the note below. |
APPRISE_TEMPLATE_<NAME> | Fills ${NAME} in stored YAML when no default exists. Blank values are ignored. |
Network
Section titled “Network”| Variable | Default | Description |
|---|---|---|
HTTP_PORT | 8000 | Internal container port. |
APPRISE_CONNECTION_TIMEOUT | 600 | How long the container waits for live-stream activity, in seconds (30–3600). |
PUID | 1000 | User ID to run the service as. |
PGID | 1000 | Group ID to run the service as. |
IPV4_ONLY | no | Force IPv4 only. |
IPV6_ONLY | no | Force IPv6 only. |
Additional Apprise API Settings
Section titled “Additional Apprise API Settings”The container also supports the following variables, which map directly to the server settings.
| Variable | Default | Description |
|---|---|---|
APPRISE_DEFAULT_CONFIG_ID | apprise | Default configuration key used by the web UI. |
APPRISE_WEBHOOK_URL | (Empty) | Optional webhook that receives a POST payload after each notification attempt. |
APPRISE_CONFIG_DIR | <BASE_DIR>/var/config | Directory storing configurations. Relative to <BASE_DIR> unless an absolute path is given. |
APPRISE_STORAGE_DIR | <APPRISE_CONFIG_DIR>/store | Directory storing persistent storage. |
APPRISE_STORAGE_MODE | auto | Persistent storage mode. Values: memory, auto, flush. Values are case-insensitive; m, a, and f are accepted as shorthand. |
APPRISE_STORAGE_PRUNE_DAYS | 30 | Age in days before storeprune removes persistent notification state. See Pruning. |
APPRISE_STORAGE_UID_LENGTH | 8 | Default URL id length used by persistent storage. |
APPRISE_AUTH_PRUNE_SECONDS | 2592000 | Age in seconds before authprune removes a lock without configuration. Locks with configuration remain. |
APPRISE_PRUNE_INTERVAL_SECONDS | 86400 | How often the container prunes persistent state and unused authentication locks. |
APPRISE_PRUNE_TIMEOUT_SECONDS | 28800 | Maximum time allowed for an automatic prune run. |
APPRISE_PRUNE_ENABLED | yes | Set to no to stop scheduled pruning. Manual commands remain available. |
APPRISE_ATTACH_DIR | <BASE_DIR>/var/attach | Directory storing uploaded attachments. Relative to <BASE_DIR> unless an absolute path is given. |
APPRISE_ATTACH_SIZE | 200 | Maximum attachment size in MB. Set to 0 to disable attachments. |
APPRISE_CONFIG_MAX_LENGTH | 512 | Maximum configuration payload size in KB accepted by form and API configuration updates. Independent of the upload body limit. Cannot exceed APPRISE_UPLOAD_MAX_MEMORY_SIZE. |
APPRISE_STREAM_MEMORY_SIZE | 2 | Stream and result logs kept in memory before temporary disk storage is used, in MB. Set to 0 to write directly to disk. |
APPRISE_STREAM_DISK_SIZE | 256 | Maximum temporary disk space used by each live stream and notification result, in MB. Set to 0 for unbounded memory-only storage. Setting both stream sizes to 0 disables live-stream backlog retention. |
APPRISE_STREAM_WORKER_COUNT | 4 | Active streamed notifications per Gunicorn worker process. The effective server-wide default is APPRISE_WORKER_COUNT * 4. Work continuing after a client disconnects still occupies its slot. |
APPRISE_STREAM_QUEUE_SIZE | 8 | Additional live streams allowed to remain connected per Gunicorn worker process while waiting for an active slot or finishing their responses. Further streams receive 503 with a Retry-After header. Set to 0 to allow no additional streams. |
APPRISE_MAX_ATTACHMENTS | 6 | Maximum number of attachments per request. Set to 0 to disable the limit. |
APPRISE_WEBHOOK_MAPPING_MAX_DEPTH | 5 | Maximum traversal depth for nested field mapping rules. Depth counts every individual step: each dict-key lookup and each array-index dereference ([N]). For example, items[0].objectURI is 3 steps and a[0][1][2].value[3] is 6 steps. See Payload Mapping Hooks. |
APPRISE_ATTACH_ALLOW_URL | * | Allow list for remote attachment URLs. |
APPRISE_ATTACH_REJECT_URL | 127.0.* localhost* | Deny list for remote attachment URLs, checked before the allow list above. Supports wildcards (*, ?). Add the special keyword internal to also block any destination that resolves to a private or internal address (LAN devices, cloud metadata, etc.), not just hosts spelled like 127.0.*/localhost*. It’s off by default since it also blocks your own LAN. See File Attachments. |
APPRISE_STATELESS_URLS | (Empty) | Default URLs used by stateless /notify/ requests when no urls are supplied. |
APPRISE_STATELESS_STORAGE | no | Allow stateless requests to use persistent storage when enabled. |
APPRISE_DENY_SERVICES | (Platform list) | Comma-separated list of schemas to disable. |
APPRISE_ALLOW_SERVICES | (Empty) | Exclusive allow list. If set, anything not in this list is disabled. |
APPRISE_PLUGIN_PATHS | <BASE_DIR>/var/plugin | Comma-separated list of plugin paths to scan. Relative to <BASE_DIR> unless absolute paths are given. |
APPRISE_API_ONLY | no | Disable the web UI and allow only the API endpoints. |
APPRISE_DEFAULT_THEME | light | Default theme for the web UI. Values: light, dark. Values are case-insensitive; l and d are accepted as shorthand. |
APPRISE_INTERPRET_EMOJIS | (Unset) | If set, overrides emoji interpretation. Values: yes or no. |
APPRISE_HTTP_REDIRECTS | yes | Follow HTTP redirects by default. Set to no to stop following them for all services; individual URLs can override this with ?redirect=yes or ?redirect=no. |
APPRISE_DEFAULT_FORMAT | (Unset) | Default input format when an API request omits format. Accepts text, html, or markdown (case-insensitive). Unset by default, so no automatic conversion occurs. A blank or null request field also skips conversion. The Web UI always sends a format. |
Django and Logging
Section titled “Django and Logging”| Variable | Default | Description |
|---|---|---|
SECRET_KEY | (Bundled default) | Django secret key. Always override this in production. |
DEBUG | no | Enable debug mode. Supports yes, 1, true, and similar. |
LOG_LEVEL | INFO | Default level for Django logs, console output, and notification logs. X-Apprise-Log-Level can request a different level for one notification without changing console output. Stateful debug and trace require administrator privileges or user access; locked, public, and disabled access is limited to info. |
TZ | Etc/UTC | Timezone for all log timestamps. Accepts any IANA timezone name (e.g. America/New_York, Europe/London). See the tz database time zones for valid values. Every process in the container (Python logging, nginx, etc.) inherits TZ directly, so timestamps are always consistent regardless of whether the container runs as root or non-root. Bind-mounting /etc/localtime or /etc/timezone without setting TZ is no longer supported. Set TZ to the desired zone name instead. |
ALLOWED_HOSTS | * | Space-delimited allowed host list. |
APPRISE_UPLOAD_MAX_MEMORY_SIZE | 3 | Maximum request body size (MB) stored in memory before Django raises RequestDataTooBig. |
Questions or Feedback?
Technical Issues
Having trouble with the code? Open an issue on GitHub: