The problem: too many monitoring tools, too many notification channels
Uptime Kuma monitors your services, Beszel monitors your VPS metrics, Changedetection.io monitors your web pages, and your cron jobs go silent at night — except when they fail. Each has its own notification channel: Slack, email, webhook, Telegram. The result: five different integrations to maintain and no unified view when something breaks at 3 AM. ntfy solves this from the other direction: you host the notification hub, and every tool or script sends alerts to it over plain HTTP.
What ntfy gives you out of the box
- Send a notification with a plain curl —
curl -d "Build failed" http://your-vps/ci-alerts— zero SDK, zero library. - Receive notifications on Android (F-Droid / Play Store), iOS (App Store), desktop browser and the ntfy web UI — all subscribe to the same topic via WebSocket or SSE.
- Notification actions — buttons in the push notification that trigger HTTP callbacks, open URLs or run commands on the subscriber device.
- Scheduled notifications — delayed delivery (
X-Delay: 30min) to schedule reminders from scripts. - Priority levels (min / low / default / high / urgent) with DND bypass on mobile for urgent alerts.
- Attachments — images or files up to 15 MB via the
X-Attachheader or multipart upload. - Access control — add users, passwords and per-topic ACLs via
ntfy userandntfy accessCLI. - < 30 MB RAM, SQLite, single container — the lightest self-hosted push notification server in its class.
Architecture: single-container HTTP pub/sub
ntfy is a Go binary that runs in a single Docker container. It exposes a simple HTTP interface: PUT or POST to /your-topic publishes a message; any client listening to that topic (via WebSocket, SSE or the mobile app) receives it instantly. Messages are cached in SQLite (/var/lib/ntfy/cache.db) with configurable retention (12 hours by default). NTFY_BEHIND_PROXY=true tells ntfy it is behind a reverse proxy (nginx) and should read the real client IP from X-Forwarded-For.
Deploy and use ntfy in 5 steps
Logging in for the first time
ntfy starts WITHOUT any account or password: the URL opens straight onto the interface, and anyone who knows the address can read AND publish on any topic. If your server is reachable from the internet, enable authentication before using it in earnest.
Tip: use topic names as namespaces
Organise your alerts by source: ci-builds for GitHub Actions/GitLab CI, server-alerts for Uptime Kuma/Beszel, cron-jobs for batch scripts. The ntfy app lets you mute specific topics at night (e.g., cron-jobs) while keeping server-alerts at maximum priority. No server-side configuration — just the topic name in the curl command.