# ntfy → Matrix bridge A small daemon that watches a set of [ntfy](https://ntfy.sh) 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=`, 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: ```bash python login.py ``` Copy the printed `access_token` (and optionally `device_id`) for the next step. ### 2. Configure ```bash 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: ```bash 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 ```bash python bridge.py --config config.yaml ``` You should see a `subscribed` line per mapping. Publish a test message: ```bash curl -d "hello from ntfy" https://ntfy.sh/your-topic ``` ## Running as a service (systemd) ```bash 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.