Zum Inhalt springen
SONOYA.com
Web & Code

Push-Benachrichtigungen selbst hosten mit ntfy

ntfy mit Docker und Caddy selbst hosten, absichern und Meldungen von Skripten, Uptime Kuma und Home Assistant aufs iPhone und Android-Handy schicken.

Von

Glocken-Symbol auf dunkelgrünem Verlauf für einen selbst gehosteten ntfy-Server, der Push-Benachrichtigungen aufs Handy schickt

Früher oder später will jeder Selfhoster vom eigenen Server benachrichtigt werden: wenn das Backup fehlschlägt, eine Website nicht mehr antwortet oder die Waschmaschine fertig ist. Die üblichen Wege haben alle einen Haken. Telegram-Bots laufen über die Server eines Messengers, E-Mails gehen in der Flut unter, und die Push-Funktion der Home-Assistant-App hilft nur bei Meldungen aus Home Assistant.

ntfy ist ein schlanker Dienst, der genau eine Sache gut macht: Er nimmt eine Nachricht per einfachem HTTP-Aufruf entgegen und schickt sie als Push-Benachrichtigung an Dein Handy. Ein Skript braucht dafür nur eine Zeile curl. Es gibt Apps für Android und iOS, und Uptime Kuma und Home Assistant können ntfy direkt ansprechen.

Den öffentlichen Dienst ntfy.sh kannst Du sofort nutzen, aber jeder, der Deinen Kanalnamen errät, liest mit. Diese Anleitung zeigt deshalb, wie Du ntfy selbst hostest, mit Benutzern absicherst und Deine Dienste anbindest. Stand ist ntfy 2.37 vom November 2026. Grundlage ist die offizielle ntfy-Dokumentation.

Was Du brauchst

  • Einen Linux-Server mit Docker, der aus dem Internet erreichbar ist. Ein kleines Droplet bei DigitalOcean mit 1 GB RAM reicht völlig aus. Wenn Du noch kein Konto hast, bekommst Du über diesen Link zu DigitalOcean (Affiliate Link) Startguthaben zum Ausprobieren.
  • Eine Subdomain wie ntfy.example.com, deren DNS-Eintrag auf die IP-Adresse des Servers zeigt.
  • Die Ports 80 und 443 müssen in der Firewall offen sein, damit Caddy ein HTTPS-Zertifikat holen kann.

Läuft auf Deinem Server bereits Coolify oder ein anderer Reverse Proxy, lässt Du den Caddy-Teil weg und trägst die Domain stattdessen dort ein.

ntfy mit Docker Compose starten

Lege einen Ordner für ntfy an und wechsle hinein:

Code
mkdir -p ~/ntfy
cd ~/ntfy

Erstelle darin die Datei compose.yml mit nano compose.yml und diesem Inhalt:

Code
services:
  ntfy:
    image: binwiederhier/ntfy
    command: serve
    restart: unless-stopped
    environment:
      NTFY_BASE_URL: https://ntfy.example.com
      NTFY_CACHE_FILE: /var/lib/ntfy/cache.db
      NTFY_AUTH_FILE: /var/lib/ntfy/auth.db
      NTFY_AUTH_DEFAULT_ACCESS: deny-all
      NTFY_BEHIND_PROXY: "true"
      NTFY_ENABLE_LOGIN: "true"
      NTFY_UPSTREAM_BASE_URL: https://ntfy.sh
    volumes:
      - ./data:/var/lib/ntfy

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./caddy-data:/data

Die wichtigsten Zeilen im Überblick:

  • NTFY_BASE_URL ist die Adresse, unter der Dein Server erreichbar ist. Ersetze ntfy.example.com durch Deine Subdomain.
  • NTFY_AUTH_FILE schaltet die Benutzerverwaltung ein, und NTFY_AUTH_DEFAULT_ACCESS: deny-all sorgt dafür, dass ohne Anmeldung niemand lesen oder senden darf. Ohne diese Zeile wäre jeder Kanal offen.
  • NTFY_CACHE_FILE speichert Nachrichten eine Weile zwischen, damit ein Handy, das kurz offline war, sie nachträglich abholt.
  • NTFY_UPSTREAM_BASE_URL ist für iPhones nötig. Apple erlaubt Apps keine dauerhafte Verbindung im Hintergrund, deshalb schickt Dein Server bei jeder Nachricht einen inhaltslosen Weckruf über ntfy.sh. Die iOS-App holt den eigentlichen Text dann direkt von Deinem Server. Ohne diese Zeile kommen Nachrichten auf dem iPhone teils mit großer Verzögerung an.

Lege dann die Datei Caddyfile mit nano Caddyfile an:

Code
ntfy.example.com {
    reverse_proxy ntfy:80
}

Caddy holt für die Domain automatisch ein Zertifikat von Let’s Encrypt und leitet alle Anfragen an den ntfy-Container weiter. Starte beide Container:

Code
docker compose up -d

Öffne nach etwa einer Minute https://ntfy.example.com im Browser. Du siehst die Weboberfläche von ntfy mit einem Anmeldeknopf.

Benutzer und Zugangstoken anlegen

Lege zuerst einen Administrator an. Der Befehl fragt zweimal nach einem Passwort:

Code
docker compose exec ntfy ntfy user add --role=admin nathan

Ersetze nathan durch Deinen Benutzernamen. Ein Administrator darf alle Kanäle lesen und beschreiben, damit meldest Du Dich in den Apps an.

Skripte sollen sich nicht mit Deinem Passwort anmelden. Dafür gibt es Zugangstoken, die Du jederzeit einzeln widerrufen kannst:

Code
docker compose exec ntfy ntfy token add --label=server nathan

ntfy gibt einen Token aus, der mit tk_ beginnt. Kopiere ihn, er erscheint später nur noch gekürzt in der Liste. Für Dienste wie Home Assistant kannst Du zusätzlich eigene Benutzer anlegen, die nur auf bestimmte Kanäle zugreifen dürfen:

Code
docker compose exec ntfy ntfy user add homeassistant
docker compose exec ntfy ntfy access homeassistant 'haus' read-write

Die Apps einrichten

Installiere die ntfy-App aus dem App Store oder aus Google Play. In der iOS-App tippst Du auf Settings, fügst unter Users Deinen Server mit Benutzername und Passwort hinzu und legst danach mit dem Plus-Symbol ein Abo an. Gib als Kanal zum Beispiel server ein, aktiviere Use another server und trage https://ntfy.example.com ein. In der Android-App funktioniert es genauso. Dort kannst Du Deinen Server zusätzlich in den Einstellungen als Standard festlegen.

Ein Kanal heißt bei ntfy Topic und entsteht in dem Moment, in dem Du ihn abonnierst oder die erste Nachricht hineinschickst. Sinnvoll ist eine Aufteilung nach Herkunft, etwa server für Backups und Systemmeldungen, monitoring für Uptime Kuma und haus für Home Assistant. In der App kannst Du dann je Kanal festlegen, wie laut er sich melden darf.

Die erste Nachricht senden

Probiere es direkt im Terminal aus. Ersetze den Token durch Deinen:

Code
curl -H "Authorization: Bearer tk_DEIN_TOKEN" -H "Title: Test" -d "Hallo vom Server" https://ntfy.example.com/server

Nach ein, zwei Sekunden muss die Nachricht auf dem Handy erscheinen. Mit weiteren Kopfzeilen steuerst Du das Aussehen: -H "Priority: high" lässt das Handy auch bei leisem Kanal deutlich klingeln, und -H "Tags: warning" setzt ein Warnsymbol vor den Titel.

Skripte, Uptime Kuma und Home Assistant anbinden

Shell-Skripte. Am nützlichsten ist eine Meldung, wenn ein Skript fehlschlägt. In einem Bash-Skript mit set -e reicht dafür eine Zeile am Anfang, die bei jedem Fehler feuert:

Code
trap 'curl -s -H "Authorization: Bearer tk_DEIN_TOKEN" -H "Priority: high" -H "Title: Backup fehlgeschlagen" -d "Das Backup auf $(hostname) ist fehlgeschlagen" https://ntfy.example.com/server' ERR

Genau so lässt sich das Backup-Skript aus der Anleitung Backups mit restic: verschlüsselt auf S3 und Spaces ergänzen, damit Du von einem fehlgeschlagenen Backup sofort erfährst.

Uptime Kuma. Öffne in Uptime Kuma Einstellungen > Benachrichtigungen > Benachrichtigung einrichten und wähle als Typ Ntfy. Trage die Server-Adresse und den Kanal monitoring ein, wähle als Anmeldung den Zugangstoken und füge ihn ein. Über Testen prüfst Du, ob die Nachricht ankommt. Wenn Du Uptime Kuma auch nutzt, um Geräte per Heartbeat zu überwachen, wie in Android-Handy per Heartbeat in Uptime Kuma überwachen beschrieben, landen die Ausfälle damit ebenfalls bei ntfy.

Home Assistant. Seit 2025 gibt es eine eingebaute ntfy-Integration. Füge sie unter Einstellungen > Geräte & Dienste > Integration hinzufügen hinzu, trage Deine Server-Adresse sowie den Benutzer homeassistant mit Passwort ein und lege danach über Topic hinzufügen den Kanal haus an. Home Assistant erzeugt daraus eine Benachrichtigungs-Entität. In einer Automation verwendest Du sie so:

Code
action: notify.send_message
target:
  entity_id: notify.ntfy_haus
data:
  title: Waschmaschine
  message: Die Wäsche ist fertig.

Den genauen Namen der Entität findest Du unter Einstellungen > Geräte & Dienste > ntfy.

Typische Fehler und ihre Lösung

Die Weboberfläche ist nicht erreichbar. Prüfe mit docker compose logs caddy, ob Caddy ein Zertifikat bekommen hat. Meist zeigt der DNS-Eintrag noch nicht auf den Server, oder Port 80 ist in der Firewall gesperrt.

curl meldet forbidden. Der Token gehört zu einem Benutzer ohne Schreibrecht auf diesen Kanal, oder er ist falsch kopiert. Mit docker compose exec ntfy ntfy token list siehst Du alle Token, mit docker compose exec ntfy ntfy access alle Rechte.

Auf dem iPhone kommen Nachrichten erst Minuten später an. Prüfe, ob NTFY_UPSTREAM_BASE_URL gesetzt ist und ob Dein Server ntfy.sh erreichen kann. Und prüfe in den iOS-Einstellungen unter Mitteilungen > ntfy, ob Mitteilungen erlaubt sind.

Was Du davon hast

Mit zwei Containern und zehn Minuten Arbeit hast Du einen eigenen Push-Dienst, den jedes Skript, jeder Monitor und Home Assistant mit einer Zeile ansprechen können. Die Nachrichten bleiben auf Deinem Server, nur der inhaltslose Weckruf für iPhones geht über ntfy.sh. Am meisten lohnt es sich bei den Meldungen, die Du sonst nie bekommen würdest: dem Backup, das nachts still scheitert, und dem Dienst, der seit Stunden nicht mehr antwortet.

Weiterlesen.