Files
apprise/AI.md
casjay 76ded16884
Some checks failed
apprise / release-apprise (push) Failing after 9m31s
🔧 Update configuration files 🔧
AI.md
Dockerfile
.env.scripts
IDEA.md
rootfs/root/docker/setup/00-init.sh
rootfs/root/docker/setup/01-system.sh
rootfs/root/docker/setup/02-packages.sh
rootfs/root/docker/setup/03-files.sh
rootfs/root/docker/setup/06-post.sh
rootfs/root/docker/setup/07-cleanup.sh
rootfs/usr/local/bin/entrypoint.sh
rootfs/usr/local/etc/docker/functions/entrypoint.sh
rootfs/usr/local/etc/docker/init.d/99-apprise.sh
TODO.AI.md
2026-05-18 15:38:17 -04:00

6.4 KiB

AI context — apprise

Build flow

  1. FROM casjaysdev/alpine:latest (build stage) with gosu sidecar.
  2. COPY ./rootfs/. / — ships all configs, scripts, and pre-bundled source tarball early.
  3. pkmgr install bash → switch to /bin/bash shell.
  4. Run 00-init.sh (sanity setup, usually a no-op stub).
  5. Run 01-system.sh (timezone, system-level tweaks).
  6. pkmgr install $PACK_LIST — installs nginx, python3, gunicorn, gevent, Django and all Alpine-packaged Python deps.
  7. Run 02-packages.sh (stub).
  8. Run 03-files.sh — auto-installs rootfs/tmp/etc/nginx//etc/nginx/, stages copies under template-files/config/.
  9. Run 04-users.sh — creates apprise system user/group via addgroup -S / adduser -S.
  10. Run 05-custom.sh — the critical build step:
    • Wipes /etc/nginx/* and replaces with our optimized config (preserving mime.types).
    • Unpacks the pre-bundled apprise-api source tarball from /tmp/apprise-src/ into /usr/local/share/apprise-api/.
    • Patches gunicorn.conf.py to use /run/apprise/gunicorn.sock instead of upstream's /tmp/ path.
    • pip install apprise PGPy slixmpp smpplib gntp (deps Alpine does not package).
    • Creates runtime directories and drops apprise.yml.sample into the template-files config seed.
  11. Run 06-post.sh (stub — late permission/symlink tweaks).
  12. Run 07-cleanup.sh (stub — per-service cache cleanup).
  13. Generic cleanup (pkmgr clean, rm -Rf /usr/share/doc/* /var/tmp/* ...).
  14. FROM scratch final stage: COPY --from=build /. /; sets ENVs, LABELs, VOLUME, EXPOSE, ENTRYPOINT/HEALTHCHECK.

Services wired

Component Binary/path Role
tini /usr/bin/tini PID 1 / reaper
entrypoint /usr/local/bin/entrypoint.sh Framework orchestrator
init.d /usr/local/etc/docker/init.d/99-apprise.sh Service configuration + launch
start-apprise /usr/local/etc/docker/bin/start-apprise Wrapper: gunicorn bg + nginx fg
gunicorn /usr/bin/gunicorn (via py3-gunicorn) WSGI server (gevent workers)
nginx /usr/sbin/nginx HTTP reverse proxy (port 8000)

init.d behavior (99-apprise.sh)

The script is sourced by entrypoint.sh via __start_init_scripts. It:

  1. Checks APPRISE_ENABLED — exits silently if set to no.
  2. Checks for the /run/.start_init_scripts.pid sentinel (prevents double-run on healthcheck invocations).
  3. Cleans up stale PID files from prior crashes.
  4. Calls framework hooks in order:
    • __run_precopy__execute_prerun (creates runtime dirs /run/apprise, /tmp/apprise, /data/logs/apprise, /config/apprise/{store,attach,plugin,conf.d})
    • __initialize_system_etc (seeds /config/nginx/ from template-files on first run)
    • __run_pre_execute_checks (runs nginx -t to validate the config before starting)
    • __update_conf_files (token replacement: REPLACE_TZ${TZ:-UTC} in nginx.conf)
    • __pre_execute (final last-mile actions)
    • __run_start_script (checks that nginx is not already running, then calls start-apprise)
    • __post_execute (background: copies apprise.yml.sample into /config/apprise/ on first run)

Config paths

Path Purpose
/etc/nginx/nginx.conf Active nginx config (wipe-and-replace from our copy)
/config/nginx/ User-editable nginx config (seeded on first run)
/config/apprise/store/ Apprise persistent config profiles (<key>.yml)
/config/apprise/attach/ Attachment staging area
/config/apprise/plugin/ Custom Apprise plugins
/config/apprise/conf.d/ Optional nginx location overrides (included optionally)
/data/logs/apprise/ nginx access/error logs + gunicorn log
/run/apprise/gunicorn.sock Unix socket between nginx and gunicorn
/usr/local/share/apprise-api/webapp/ Django app root (manage.py, core/, api/, gunicorn.conf.py)

Environment variables (runtime)

Variable Default Used by
APPRISE_ENABLED yes 99-apprise.sh
APPRISE_CONFIG_DIR /config/apprise/store gunicorn / Django
APPRISE_ATTACH_DIR /config/apprise/attach gunicorn / Django
APPRISE_PLUGIN_PATHS /config/apprise/plugin gunicorn / Django
TZ America/New_York nginx, Python logging

start-apprise wrapper

/usr/local/etc/docker/bin/start-apprise:

  1. Creates /run/apprise, /tmp/apprise, log dirs.
  2. Exports APPRISE_* env defaults if not already set.
  3. Starts gunicorn in background: cd /usr/local/share/apprise-api/webapp && gunicorn -c gunicorn.conf.py --worker-tmp-dir /dev/shm core.wsgi >> /data/logs/apprise/gunicorn.log 2>&1 &
  4. Polls (up to 15s) for /run/apprise/gunicorn.sock to appear.
  5. exec /usr/sbin/nginx -c /etc/nginx/nginx.conf — nginx runs in the foreground with daemon off;.

File layout key

rootfs/
  usr/local/bin/entrypoint.sh          # SHARED: framework orchestrator (CONTAINER_NAME="apprise")
  usr/local/bin/pkmgr                  # SHARED: apk/apt/dnf wrapper
  usr/local/etc/docker/
    functions/entrypoint.sh            # SHARED: framework function library
    init.d/99-apprise.sh               # PER-REPO: service init + launch
    bin/start-apprise                  # PER-REPO: gunicorn+nginx launch wrapper
  tmp/etc/nginx/nginx.conf             # PER-REPO: optimized nginx config
  tmp/etc/nginx/mime.types             # PER-REPO: mime types (preserved from Alpine pkg)
  root/docker/setup/
    04-users.sh                        # PER-REPO: creates apprise system user
    05-custom.sh                       # PER-REPO: wipe-replace configs + pip install