Files
ntfy-matrix-bridge/README.md
2026-06-17 22:24:58 -04:00

3.1 KiB

ntfy → Matrix bridge

A small daemon that watches a set of ntfy topics and forwards every notification to a Matrix room. Define which topics go where in a simple YAML config.

It is built to run unattended:

  • one streaming connection per mapping, with exponential-backoff reconnect
  • resume via ntfy's since=<message_id>, so nothing is lost across reconnects or restarts (the last-forwarded id is persisted to state.json)
  • a single Matrix sender that retries on failure; the resume cursor only advances once the homeserver has accepted the message (at-least-once delivery)

Unencrypted rooms only. The target Matrix room must not be end-to-end encrypted. Supporting E2EE would require a persistent crypto store, a stable device id, and a sync loop — deliberately out of scope here.

Setup

1. Create a bot account and get an access token

Create a normal user on your homeserver for the bot (e.g. @ntfybot:example.org), then run the helper to log in and print an access token:

python login.py

Copy the printed access_token (and optionally device_id) for the next step.

2. Configure

cp config.example.yaml config.yaml

Edit config.yaml. The token is best supplied via the environment rather than written into the file — ${VAR} in any value is expanded from the environment:

export MATRIX_ACCESS_TOKEN="syt_...."

Each entry under mappings ties a set of topics on one ntfy server to one Matrix room. Use the room's internal id (!abcd...:example.org, found under room settings → Advanced), not its human alias. Make sure the bot has joined each target room.

3. Run

python bridge.py --config config.yaml

You should see a subscribed line per mapping. Publish a test message:

curl -d "hello from ntfy" https://ntfy.sh/your-topic

Running as a service (systemd)

sudo useradd --system --home /opt/ntfy-matrix-bridge ntfybridge
sudo cp -r . /opt/ntfy-matrix-bridge
sudo python3 -m venv /opt/ntfy-matrix-bridge/venv
sudo /opt/ntfy-matrix-bridge/venv/bin/pip install -r /opt/ntfy-matrix-bridge/requirements.txt
sudo cp ntfy-matrix-bridge.service /etc/systemd/system/
# edit the unit to set MATRIX_ACCESS_TOKEN (or point EnvironmentFile at a secrets file)
sudo systemctl daemon-reload
sudo systemctl enable --now ntfy-matrix-bridge
journalctl -u ntfy-matrix-bridge -f

Notes

  • Formatting. Title is bold, the body follows, recognised ntfy tags become emoji (others are listed as text), and click/attachment URLs become links. Priority 4/5 get a coloured marker.
  • msgtype. m.text (default) triggers notifications in clients; switch a mapping to m.notice if you want it quieter.
  • priority_min. Optionally drop low-priority messages per mapping.
  • State. Delete state.json to forget the resume position; on the next start each mapping begins live (no historical replay).
  • ntfy.sh caches messages for a few hours, so short outages are recoverable; a self-hosted server needs caching enabled for resume to work across restarts.