Self-hosted push notifications in 2026: revisit ntfy, Gotify and Apprise before you wire another alert to a chat webhook

Most teams send alerts the same way. A cron job fails, a backup does not finish, a disk fills up, and a script posts a message to a chat webhook. It works until the chat channel becomes noisy, the webhook URL leaks into a public repository, or the chat vendor changes its limits. This post revisits three self-hosted options for push notifications, ntfy, Gotify and Apprise, and looks at what each one does, how it is licensed and what it costs to run.

This is not a ranking. The notes below come from the projects’ own GitHub repositories, documentation, licence files and release pages, checked on 5 November 2026. No hands-on benchmark was run for this post, so no speed or capacity numbers are quoted.

Why revisit push notifications now

  • Alerts are spread across many sources: CI pipelines, backup jobs, home lab servers, monitoring tools and small internal scripts. Each one often has its own chat webhook.
  • Chat webhooks are secrets that are easy to leak. Anyone with the URL can post into your channel.
  • Important alerts get lost between normal chat messages. A separate notification path with priorities helps people notice what matters.
  • All three projects are actively maintained. ntfy released v2.37.2 on 4 November 2026, Apprise released v2.1.0 on 24 October 2026 and the Gotify server released v3.1.1 on 15 September 2026, according to their GitHub release pages.

Shared concepts before you choose

Topics and publish/subscribe

ntfy and Gotify are both message servers. A script publishes a message with a simple HTTP request, and phones, browsers or other clients subscribe and receive it. In ntfy the unit is a topic: you publish to a topic name and anyone subscribed to that topic gets the message. In Gotify the unit is an application: each sending application gets its own token, and messages are grouped by application for a user.

Apprise is different. It is not a server that holds messages. It is a library, a command line tool and an optional API service that takes one message and delivers it to many existing services, such as Telegram, Discord, Slack, email, Amazon SNS, and also ntfy and Gotify. Think of it as a translator, not a mailbox.

Mobile push: FCM and APNs versus self-run

This is the part most people miss. On Android, the Google approved way to wake a phone is Firebase Cloud Messaging (FCM). On iOS, it is Apple Push Notification service (APNs). A self-hosted server cannot use these without an account and app keys tied to the app publisher.

  • ntfy’s documentation says FCM for a self-hosted server only works if you modify and build your own Android app, and suggests that most self-hosters do not bother. The Android app can instead keep its own connection to your server.
  • For iOS, ntfy’s documentation explains that iOS restricts background work so much that instant push is not possible without a central server. A self-hosted ntfy can set upstream-base-url so that it sends a small poll request through ntfy.sh, and the iOS app then fetches the real message from your server. The upstream only sees a generic “New message” text and a message ID, not your content.
  • Gotify receives messages on its clients over a WebSocket connection, and the project ships an Android app. It does not rely on FCM, so the phone app keeps a connection open itself. Check the current docs for iOS options before you promise iPhone users anything.

The trade-off is simple: a self-run connection keeps your data off third-party push services but may cost some battery and depends on the phone not killing the app in the background.

Authentication

  • ntfy is open to everyone by default. Its documentation says that out of the box anyone can read and write any topic, which is how the public ntfy.sh is configured. For a private server you set auth-default-access to deny-all and create users and access rules (read, write or read-write per topic).
  • Gotify uses user accounts plus tokens. Each application gets a token for sending, and each client gets a token for receiving.
  • Apprise itself holds credentials for every service you send to, usually inside service URLs. That makes its configuration a secret store in practice.

ntfy: simple HTTP pub/sub for phones and scripts

ntfy was started by Philipp Heckel; the GitHub repository binwiederhier/ntfy was created in October 2021. It is written in Go. A message can be sent with a single curl command to a topic URL, and the same server provides a web app, Android and iOS apps, and Web Push support.

What it does well

  • Very low effort to send: one HTTP PUT or POST with a plain text body is enough, so it fits shell scripts, cron jobs and CI steps.
  • Topic based model that works well for many small alert streams.
  • Priorities, tags, attachments and scheduled delivery are described in the docs.
  • Fine grained access control per user and per topic once you switch to deny-all.
  • A documented path for iOS through an upstream server, with only a poll request leaving your network.
  • Licence: dual licensed under Apache License 2.0 and GPLv2, as stated in the README.

What to check before you commit

  • History: a younger project than Gotify, with a single main maintainer. Check the release pace and issue activity yourself.
  • Default access is open. If you forget to set deny-all, anyone who guesses a topic name can read it or post to it.
  • iOS instant delivery depends on the upstream server, by default ntfy.sh. Decide whether that is acceptable for your organisation.
  • Operations: plan the message cache, attachment storage limits and a reverse proxy with TLS. The config generator in the docs is a good starting point.

Gotify: a small server with its own apps

Gotify’s server repository gotify/server was created in January 2018. It is written in Go. The README says the team wanted a simple self-hosted server for sending and receiving messages in real time over WebSocket, because most existing open source options were abandoned.

What it does well

  • Clear separation of applications (senders) and clients (receivers), each with its own token.
  • REST API for sending and WebSocket for receiving, both documented.
  • A web UI and an Android app maintained by the same project.
  • Plugin support for extending the server.
  • Licence: MIT for the server (LICENSE file, copyright 2018 jmattheis) and MIT for the Android app.

What to check before you commit

  • History: older and stable, with a smaller feature surface than ntfy. That is a strength for some teams and a limit for others.
  • Mobile: the Android app keeps its own connection; confirm battery behaviour on the phones your team actually uses. iOS support is not part of the core project, so check before you depend on it.
  • Plugins are compiled Go plugins and must match the server version; check this before every upgrade.
  • Operations: a single binary or container with a database (SQLite by default); back up that database and the uploaded images.

Apprise: one interface for many destinations

Apprise was created by Chris Caron; the repository caronc/apprise was created in November 2017. It is written in Python. The README describes one consistent URL format for sending notifications to a very large number of services, through the CLI, the Python library or the separate Apprise API service.

What it does well

  • One notification call can fan out to many services at once, such as chat, email, SMS gateways, ntfy and Gotify.
  • Easy to add to existing Python tools, and the CLI fits shell scripts.
  • Supports attachments and images for services that accept them.
  • Configuration files let you group destinations with tags, so a script can say “notify ops” without knowing the targets.
  • Licence: BSD 2-Clause for the core library; the separate apprise-api project is MIT.

What to check before you commit

  • It does not store or deliver messages to phones by itself. You still need a destination service, which can be ntfy or Gotify.
  • Service URLs contain tokens and passwords. Protect the configuration file like any secret store.
  • Each external service can change its API. Apprise keeps up, but pin versions and test after upgrades.
  • If you run the Apprise API as a shared service, put authentication in front of it; do not expose it openly.

Security notes for any notification setup

  • Treat every sending token, topic name and service URL as a secret. Keep them in a secrets manager or CI variables, not in the repository.
  • Never put customer data, passwords or full stack traces in a notification. Send a short message with a link to the dashboard or log instead.
  • Use TLS everywhere, including between internal scripts and the server.
  • For ntfy, set deny-all and give write access only to the accounts that send. For Gotify, use one application token per source so you can revoke one without breaking others.
  • Rotate tokens when people leave, and log who can publish.
  • Remember that phone lock screens show message previews. Keep sensitive text out of titles.

When to pick which

  • Pick ntfy when you want the lowest effort to send from scripts, topic based subscriptions, and phone apps on both Android and iOS, and you are comfortable configuring access control carefully.
  • Pick Gotify when you want a small, mature, MIT licensed server with clear application and client tokens, and your team mostly uses Android or the web UI.
  • Pick Apprise when the problem is too many destinations rather than no destination. It sits in front of ntfy, Gotify, chat and email, so your scripts call one thing.
  • Many teams will combine them: Apprise as the sending layer and ntfy or Gotify as the self-hosted receiving layer.

An example: a small team in Coimbatore

The following is an invented example, not a real company. A four-person IT team at a textile exporter in Coimbatore runs backups, a Tally server, a few Linux VMs and a small GitLab. Today, every script posts to one group chat, and the backup failure alert from last month was missed because it arrived between festival greetings.

The team sets up ntfy on an existing VM behind their reverse proxy, with deny-all access, one writer account for scripts and read access for the four team members. Topics are split as backups, servers and gitlab. Because two members use iPhones, they accept the upstream poll request through ntfy.sh after checking that only a generic text leaves their network. They install Apprise on the backup host so that a failed backup goes to ntfy and also sends an email to the owner. Chat is kept for discussion, not alerts. After a month, they review which topics are noisy and lower the priority of routine success messages.

Practical checklist

  • List every current alert source and where it sends today.
  • Decide which alerts need a phone push and which can stay as email or chat.
  • Choose ntfy or Gotify as the receiving server, and decide whether Apprise is needed in front.
  • Check the licence files yourself: ntfy Apache-2.0 or GPLv2, Gotify MIT, Apprise BSD 2-Clause, Apprise API MIT.
  • Confirm mobile behaviour on your actual phones, especially iOS and phones with aggressive battery saving.
  • Lock down access: deny-all for ntfy, separate tokens for Gotify, protected config for Apprise.
  • Put the server behind TLS and back up its data.
  • Keep sensitive data out of message text.
  • Pin versions and read release notes before upgrades.
  • Review noise after a few weeks and adjust priorities.

Closing thought

A notification is only useful if someone sees it and trusts it. Moving alerts out of a busy chat channel into a small self-hosted server is not a big project, but it does need some care around access, mobile push and secrets. Start with one noisy alert source, move it, and learn from that before you move the rest.

comments powered by Disqus

Releted Posts

Self-hosted code search in 2026: revisit Zoekt, OpenGrok and Hound before you clone another fifty repos to find one function

Every growing engineering team reaches the same moment. Someone asks “where else do we call this function?”, and the honest answer is to clone fifty repositories and run grep across them.

Read more

Self-hosted notes in 2026: revisit Joplin, Trilium Notes and Memos before you paste another runbook into a hosted notes app

Notes are where engineers keep the small things that matter: the command that fixed last month’s outage, the half-written design idea, the client’s odd network rule.

Read more

Self-hosted invoicing in 2026: revisit Invoice Ninja, Akaunting and SolidInvoice before you send another invoice from a spreadsheet

Most small teams start invoicing the same way. Someone copies last month’s invoice in a spreadsheet, changes the number and the date, exports a PDF and emails it.

Read more