# Push notifications (APNs/FCM) — XEP-0357 vs UnifiedPush (2026-08-29) Status in /opt/icq: **deferred** (no real need). Verified facts + two working paths for when it becomes needed. The key gotcha: our container is **Prosody 0.11.9**, and that version pins which push modules can load. ## How XMPP push works (mental model — it is "inverted") - **XEP-0357 "Push Notifications"** is the standard. The server does NOT send to APNs/FCM itself. Instead: the mobile client, on going background, registers "push service + token" with the XMPP server; when an offline message arrives the server pokes that push service, which then delivers via APNs/FCM. - Native clients Conversations (Android) and Monal (iOS) use their **own public push gateways** (conversations.im, push.monal.im). For them you only need the XEP-0357 modules enabled on the server — you do NOT run your own APNs/FCM bridge. A self-built APNs bridge is the heavy path (Apple dev account, .p8 token, a daemon that receives Prosody callbacks) — only worth it for a strict "no third parties" goal. ## Version-compatibility MATRIX (the important part) | Module / source | Prosody 0.11.9 (our container) | Notes | |-----------------|-------------------------------|-------| | `mod_unified_push` (in **apt** prosody-modules) | **WILL NOT LOAD** | requires `util.jwt` = Prosody **0.12+** API. Fails: `modulemanager error: module 'util.jwt' not found`. UnifiedPush ≠ XEP-0357. | | `mod_push` / `mod_push_offline` / `mod_push_muc` (XEP-0357) | works on 0.11 | **NOT in Debian/Ubuntu apt prosody-modules package.** Get from official repo `https://hg.prosody.im/prosody-modules/` (Mercurial — git clone of `hg.prosody.im` returns 400; there is no official git mirror). Drop into `./modules`, add `"push"; "push_offline";` to `modules_enabled` (+`"push_muc"` for MUC rooms). | | `mod_unified_push` | works | only after upgrading Prosody to 0.12 (then `util.jwt` exists). | Bottom line: - **Roadmap option 1 (recommended, works on 0.11):** XEP-0357 `mod_push` + `mod_push_offline` (+`mod_push_muc`) from hg.prosody.im → native Conversations/Monal push via their public gateways. - **Roadmap option 2:** upgrade Prosody to 0.12 → then apt's `mod_unified_push` (UnifiedPush) works. ## Probe I used (and the failure it surfaced) Enabled `mod_unified_push` (copied from apt into ./modules, added to modules_enabled), `prosodyctl check config` passed, then `docker compose restart prosody`, then: ```bash grep -iE 'unified_push|Error initializing|error' /opt/icq/logs/prosody.log /opt/icq/logs/prosody.err # → modulemanager error: module 'util.jwt' not found ``` Server stayed UP (module failed to load but did not take the whole process down), so this kind of error is easy to miss in a quick health check — grep the file logs specifically for `Error initializing module`. Clean-up after discovering an incompatible module: remove from `modules_enabled`, `rm -rf ./modules/`, restart, re-grep for `Error initializing` (should be empty).