Skip to content

Deployment

The Apprise API is designed to run as a containerized service.
This page explains how to deploy and operate it, not how to use the API endpoints.

If you are looking to:

  • send notifications, see API Usage
  • integrate with the CLI or Python library, see Integration
  • understand keys, storage, or locking, see Configuration

Choose one deployment method below to get Apprise API running quickly.

The self-hosted examples publish port 8000 normally so trusted devices on your home or internal network can connect without extra proxy configuration. They use normal mode. Do not expose them directly to the Internet. Use the Deployment Behind a Proxy tab for a public server with HTTPS, authentication, strict routing, and a loopback-only container port.

Terminal window
docker run --name apprise \
-p 8000:8000 \
-v ./config:/config \
-v ./attach:/attach \
-e APPRISE_STATEFUL_MODE=simple \
-e APPRISE_WORKER_COUNT=1 \
-e APPRISE_DEFAULT_FORMAT=text \
-d caronc/apprise:latest

The following will set the same container up but leverage health check monitoring:

Terminal window
docker run --name apprise \
-p 8000:8000 \
-v ./config:/config \
-v ./attach:/attach \
-e APPRISE_STATEFUL_MODE=simple \
-e APPRISE_WORKER_COUNT=1 \
-e APPRISE_DEFAULT_FORMAT=text \
--health-cmd='curl -fsS http://127.0.0.1:8000/status >/dev/null || exit 1' \
--health-interval=30s \
--health-timeout=5s \
--health-retries=3 \
--health-start-period=20s \
-d caronc/apprise:latest

To try the built-in administrator login locally, stop the earlier quick-start container first; both examples use port 8000. This one keeps the configuration list available to admin:

Terminal window
docker run --name apprise-auth \
-p 127.0.0.1:8000:8000 \
-v ./config:/config \
-v ./attach:/attach \
-e APPRISE_STATEFUL_MODE=simple \
-e APPRISE_AUTH_REQUIRED=yes \
-e APPRISE_USER=admin \
-e APPRISE_PASSWORD=changeme \
-e APPRISE_WEB_AUTH_SECRET="$(openssl rand -hex 32)" \
-e APPRISE_WORKER_COUNT=1 \
-e APPRISE_DEFAULT_FORMAT=text \
-d caronc/apprise:latest

Open http://127.0.0.1:8000/cfg and sign in as admin with password changeme. The list works because stateful storage is in simple mode; the configuration list is shown by default.

Once deployed, the API and optional web interface are available at:

http://localhost:8000/

Apprise API supports persistent storage for:

  • saved configurations
  • cached authentication metadata
  • uploaded attachments

The container expects the following writable paths:

PathPurpose
/configSaved configurations and internal state
/attachUploaded attachments
/pluginOptional custom plugins
/tmpRuntime files (sockets, buffers, temp data)

For most deployments, mounting only /config and /attach is sufficient.

Persistent features follow the server mode, configuration lock, and current login:

StateConfiguration ListMove / DeleteConfiguration LoginConfiguration Content
Stateful mode disabledUnavailableUnavailableUnavailableUnavailable
Authentication off, configuration unlockedAvailable with APPRISE_STATEFUL_MODE=simple unless APPRISE_ADMIN=noAllowedUnavailableAvailable
Authentication off, configuration lockedHidden and deniedDeniedUnavailableHidden; saved notifications still work
Configuration user, unlockedDeniedMay move their ID or clear its contentMay update their own passwordAvailable for their ID
Configuration user, lockedDeniedDeniedMay update their own passwordHidden; saved notifications still work
Administrator, unlockedAvailable with APPRISE_STATEFUL_MODE=simple unless APPRISE_ADMIN=noAllowed for any IDMay manage any loginAvailable
Administrator, lockedAvailable with APPRISE_STATEFUL_MODE=simple unless APPRISE_ADMIN=noAllowed for any IDMay manage any loginAvailable

When configuration content is locked, the Web notification form asks for at least one tag because it cannot display the saved destinations.

An authenticated administrator retains full configuration access while locking is enabled. Configuration users and unauthenticated callers cannot add, retrieve, inspect, list, move, or delete configuration. A user account may still make authenticated stateful and stateless notifications, while a locked account is limited to tagged stateful notifications.

Global mode switches always win. Even an administrator cannot send a stateful or stateless notification when its global mode is disabled. Administrator credentials bypass per-configuration access and the configuration lock only.

Apprise API also supports process and filesystem hardening. This protects the container itself, but it does not add HTTPS, authentication, or strict routing. For a public or multi-tenant server, combine these controls with the Deployment Behind a Proxy setup above.

Example hardened container configuration:

services:
apprise:
image: caronc/apprise:latest
container_name: apprise
user: "1000:1000"
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
ports:
- "8000:8000"
environment:
APPRISE_STATEFUL_MODE: simple
APPRISE_WORKER_COUNT: 1
APPRISE_DEFAULT_FORMAT: "text"
volumes:
- ./config:/config
- ./attach:/attach
tmpfs:
- /tmp

Important Notes:

  • /tmp must remain writable
  • No files are written under /var/log
  • All logs are written to stdout and stderr

If you deploy in Kubernetes, see Quick Start -> Kubernetes -> Hardened (rootless + read-only) for a ready-to-apply example that:

  • runs as a non-root user
  • drops all Linux capabilities
  • disables privilege escalation
  • uses a read only root filesystem
  • mounts /tmp as an in-memory emptyDir

Apprise API exposes a health endpoint:

GET /status
  • Returns HTTP 200 when healthy
  • Returns HTTP 417 if a blocking issue is detected

Example:

Terminal window
curl http://localhost:8000/status

This endpoint is suitable for:

  • Docker health checks
  • Kubernetes liveness probes
  • external monitoring systems

If Apprise API is hosted behind a reverse proxy or served under a subpath, set APPRISE_BASE_URL to accommodate this.

For a complete HTTPS proxy example with loopback-only container access, see Quick Start -> Docker + External Nginx above.

Example:

Terminal window
APPRISE_BASE_URL=/apprise

This ensures:

  • correct URL generation
  • correct web UI routing
  • correct OpenAPI links

Apprise API does not require authentication by default. Set APPRISE_AUTH_REQUIRED=yes to protect its endpoints with HTTP Basic Auth. Only Config IDs explicitly made public can bypass it, and only for tagged notifications.

ModeSettingsResult
DisabledAPPRISE_AUTH_REQUIRED=noRequests remain open. Administrator settings and saved configuration logins are ignored.
Administrator enabledAPPRISE_AUTH_REQUIRED=yes with APPRISE_PASSWORDThe administrator can access every key and manage configuration logins. APPRISE_USER is optional.
Administrator disabledAPPRISE_AUTH_REQUIRED=yes without APPRISE_PASSWORDExisting configuration users can access only their own keys. New logins cannot be created until an administrator password is configured.

APPRISE_USER without APPRISE_PASSWORD produces a startup warning and leaves the administrator account disabled. See Environment Variables.

APPRISE_BASIC_AUTH_REALM names the server in login prompts. It does not change any credentials. The default is Apprise API; use a different name for each hosted instance.

Use HTTPS/TLS. Basic Auth does not encrypt credentials. HTTPS is required outside localhost or a trusted network.

API clients send Basic Auth with every request. The server briefly remembers successful checks to make repeated requests faster. It does not store the credentials or create an API session.

Browser pages use a signed login so Logout can end the session. JSON and plain-text API calls cannot use this browser login.

Stateful clients can keep using paths such as /notify/{KEY}. Supported endpoints also accept X-Apprise-Config-ID, which keeps the key out of the URL.

The packaged Nginx configurations explicitly expose GET /qr, /qr/{KEY}, and /qr/@ for Apprise Mobile setup. They reject other methods, discard request bodies, disable proxy buffering, and mark responses no-store. Strict mode also applies its protected-route rate limit to these requests.

The Apprise CLI’s apprise:// plugin sends this header in its default version 2 mode. Use ?v=1 only with older servers that require /notify/{KEY}.

Browser logins expire after 24 hours without activity. Each authenticated request renews that period. Changing APPRISE_WEB_AUTH_SECRET signs out every browser.

The Config ID field can open another configuration without showing its ID in the address bar. Users must log in when they switch to an ID with different credentials. Administrators can also choose or generate an ID from New Configuration.

Each Config ID uses one access mode:

AccessNotification useConfiguration use
userRequires its credentials. Tags are optional.The user may view, edit, clear, and replace their configuration.
lockedRequires credentials and a specific tag, never all.Hides content. The user may change their password and move the Config ID.
publicRequires only the Config ID and a specific tag.Hides content. Saved credentials, when present, keep the locked abilities.
disabledRejects configuration-user notifications.Freezes user access while preserving configuration and credentials.

Public access applies only to stateful POST /notify/{KEY} calls. Other endpoints still require valid credentials. Attachments remain supported.

For stateless POST /notify, administrators can authenticate directly. A configuration user must provide explicit urls, matching credentials, and X-Apprise-Config-ID; the configuration must use user access. Without urls, the v2 header form remains a stateful send through the saved configuration.

The user and locked accounts may retrieve /status and /details with their credentials and Config ID. A disabled account cannot. Administrators may include a valid X-Apprise-Config-ID for client convenience, but do not need one.

To set access, open a configuration and select its lock icon or Authentication. Choose the access mode, enter credentials when required, then select Save. Administrators can use Randomize for either credential.

The Config ID and credentials are separate values. Share the Config ID and configured credentials with the user. A username is optional; saved passwords are not displayed again.

API clients manage access with POST /auth/{KEY}. The access field accepts user, locked, public, or disabled. A new record defaults to user, or to locked while APPRISE_CONFIG_LOCK=yes. Saved user access then behaves as locked without being rewritten. Saved public access remains public because it already hides configuration content. A configuration user may change only their password and must repeat their username. See API Endpoints.

Per-key locks are ignored while APPRISE_AUTH_REQUIRED is disabled, restoring the original open behavior. Their files remain and take effect again when authentication is enabled.

Logout ends the signed browser login. Credentials cached by the browser cannot silently restore it.

Old locks without configuration are removed after APPRISE_AUTH_PRUNE_SECONDS (30 days by default). When a user clears their configuration, their credentials remain and this grace period restarts so they can save a replacement. Locks with configuration remain. See Pruning.

Browsers add an Origin header when a page changes data. Apprise API checks this header and rejects changes sent from another website. Requests from the same site are allowed.

Apprise API does not require Django’s CSRF token exchange. Direct calls from curl, mobile apps, and other programs normally omit Origin and continue to work.

For an HTTPS site behind a reverse proxy, set APPRISE_TRUSTED_ORIGINS to the full public address, such as https://apprise.example.com. Separate multiple addresses with commas.

For defense in depth, you can add controls outside the application:

  • exposing the container only through a trusted reverse proxy
  • adding authentication at the proxy or ingress layer
  • restricting access with firewall or network policy rules

Nginx override files may also be mounted into the container for specialized access-control requirements.

A Kubernetes example that uses a Secret (basic auth .htpasswd) and a ConfigMap (nginx location-override.conf) is available under Quick Start -> Kubernetes -> Full example.

The packaged container runs one low-priority cleanup cycle each day. It covers both areas below and has a time limit:

AreaWhat it prunesRetention setting
Persistent stateApprise’s notification-state storage (APPRISE_STORAGE_DIR).APPRISE_STORAGE_PRUNE_DAYS (default 30 days)
AuthenticationPer-key Basic Auth locks without configuration.APPRISE_AUTH_PRUNE_SECONDS (default 2592000, or 30 days)

APPRISE_PRUNE_INTERVAL_SECONDS controls the schedule. Set APPRISE_PRUNE_ENABLED=no to disable scheduled cleanup. APPRISE_PRUNE_TIMEOUT_SECONDS changes the 8-hour time limit. The combined or individual commands may still run manually:

Terminal window
docker exec -it apprise python manage.py prune
docker exec -it apprise python manage.py storeprune --days 30
docker exec -it apprise python manage.py authprune --seconds 2592000
  • All logs are emitted to stdout and stderr
  • No log files are written to disk
  • Prometheus metrics are available at /metrics
  • Successful /status, /metrics, favicon, and robots probes are omitted from access logs; failures and rate-limit responses remain visible

For local development, the repository includes Docker Compose overrides that:

  • mount the local source tree
  • reload UI and template changes without rebuilding
  • expose the API on port 8000

This mode is intended for development only and is not recommended for production.

Once deployed, you can:

  • save configuration keys using the web UI or API
  • send notifications using /notify or /notify/{KEY}
  • integrate external systems using HTTP or the Apprise CLI
Questions or Feedback?

Documentation

Notice a typo or an error?

Technical Issues

Having trouble with the code? Open an issue on GitHub:

Made with love from Canada