Files
2026-09-06 13:51:11 +00:00

3.0 KiB

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:

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/<name>, restart, re-grep for Error initializing (should be empty).