Blog / Tutorials / Boop selbst hosten: Benachrichtigungs-Inbox für Entwickler
(last updated: )

Boop selbst hosten: Benachrichtigungs-Inbox für Entwickler

Boop ist eine selbst gehostete Benachrichtigungs-Inbox, die Ereignisse aus deinen Apps an dein iPhone sendet. Diese Anleitung zeigt die Bereitstellung auf einem VPS mit Docker, Apple-Push-Benachrichtigungen, die Kopplung deines iPhones und das erste Ereignis.

12 Min. Lesezeit
Self=hosting Boop

Kurz gesagt. Boop ist eine selbst gehostete Benachrichtigungs-Inbox, die Ereignisse aus deinen Apps an dein iPhone sendet. Sie läuft als einzelne Go-Binärdatei mit einer SQLite-Datenbank, wird mit docker compose up -d --build bereitgestellt und lauscht auf Port 8080. Pushs gehen ohne gehosteten Relay-Dienst direkt von deinem Server an die APNs von Apple. Du brauchst einen Apple-Developer-Account, um die iOS-App selbst zu bauen und zu signieren.

Bei den meisten Fehler-Trackern musst du dich registrieren, deine Stacktraces an deren Cloud senden und pro Nutzer zahlen, sobald der kostenlose Plan endet. Boop geht einen anderen Weg. Eine selbst gehostete Benachrichtigungs-Inbox ist ein kleiner Server, den du selbst betreibst. Er nimmt Ereignisse aus deinen Anwendungen an und leitet sie ohne Drittanbieter als Push-Benachrichtigungen an dein iPhone weiter.

Boop steht unter der MIT-Lizenz, ist in Go geschrieben und speichert alles in einer einzigen SQLite-Datei. Ein praktisches Beispiel: Dein nächtlicher pg_dump-Job endet, ein einzeiliger curl-Befehl sendet das Ergebnis an Boop und eine Sekunde später meldet dein iPhone „Backup abgeschlossen“. Diese Anleitung zeigt dir, wie du Boop auf einem VPS bereitstellst, mit Apple-Push-Benachrichtigungen verbindest und dein erstes Ereignis sendest.

Was du vor dem Start brauchst

Die Serverseite stellt geringe Anforderungen: Du brauchst einen Docker-Host mit einem öffentlichen Hostnamen. Die Apple-Seite nimmt den Großteil der Einrichtung in Anspruch, weil du die iOS-App selbst baust und signierst.

  • Einen Linux-Server mit Docker Engine und dem Docker-Compose-Plug-in. Der Boop-Server ist klein. Laut Projektentwickler belegt er auf dessen Rechner etwa 8 MB Arbeitsspeicher.
  • Eine Domain oder Subdomain, die auf diesen Server zeigt und per HTTPS erreichbar ist. Dein iPhone ruft die vollständigen Ereignisdetails direkt vom Server ab, daher muss dieser von außerhalb deines Netzwerks erreichbar sein.
  • Einen Apple-Developer-Account, einen Mac mit Xcode und ein iPhone mit iOS 26. Die iOS-App von Boop ist Open Source; du baust und signierst sie selbst.
  • Root- oder sudo-Zugriff per SSH und etwa 30 Minuten Zeit.

Schritt 1: Boop mit Docker starten

Nach dem Klonen startest du Boop mit einem Compose-Befehl auf Port 8080. Häufig wird dabei das Datenverzeichnis vergessen:

git clone https://github.com/chrisgreg/boop && cd boop
cp .env.example .env
mkdir -p data && chown 1000:1000 data
docker compose up -d --build

Die Zeile chown 1000:1000 ist auf Linux-Hosts nötig. Das Image läuft mit der UID 1000. Wenn root das per Bind-Mount eingebundene Verzeichnis erstellt hat, kann SQLite nicht in /data/boop.db schreiben.

Prüfe, ob der Server läuft:

curl http://localhost:8080/health

Ein funktionierender Server gibt {"status":"ok"} zurück. Die Weboberfläche lauscht auf Port 8080, doch auf einem VPS gibt es keinen Desktop, über den du sie öffnen könntest. Leite den Port deshalb per SSH an deinen Rechner weiter:

ssh -L 8080:localhost:8080 you@your-server

Lass diese Sitzung geöffnet und rufe http://localhost:8080 im Browser deines Laptops auf. Der Einrichtungsassistent führt dich durch Serverprüfung, APNs-Konfiguration, Kopplung, dein erstes Projekt und eine Testbenachrichtigung.

Nutze den Tunnel, statt Port 8080 im Internet freizugeben. Das ist über die bequemere Einrichtung hinaus relevant: Du hast noch keine Admin-Zugangsdaten festgelegt. Bis du das in Schritt 2 erledigst, kann jeder, der den Host findet, auf sämtliche Admin-Endpunkte dieses Ports zugreifen. Mit dem Tunnel bleibt die Weboberfläche während der Ersteinrichtung vom öffentlichen Internet getrennt. Alternativ bindest du den veröffentlichten Port an die Loopback-Adresse. Ändere dazu den Compose-Eintrag ports in 127.0.0.1:8080:8080 und greife nach Schritt 2 über den Reverse Proxy auf die Weboberfläche zu.

APNs-Zugangsdaten sind zu diesem Zeitpunkt optional. Ohne sie speichert Boop die Ereignisse und zeigt sie in der Weboberfläche an, überspringt aber die Pushs. So kannst du deine Integrationen testen, bevor du das Apple-Developer-Portal konfigurierst.

Wenn du Docker nicht verwenden möchtest, gibt es eine Alternative: Jedes Release enthält eine statische Binärdatei ohne externe Abhängigkeiten für Linux auf amd64 und arm64. Die Weboberfläche ist bereits eingebettet. Lege für BOOP_DATABASE_PATH einen beschreibbaren Pfad fest, da die Variable standardmäßig auf /data/boop.db zeigt:

BOOP_DATABASE_PATH=./boop.db ./boop

Schritt 2: Boop per HTTPS absichern und die Admin-Oberfläche schützen

Lege BOOP_ADMIN_USER und BOOP_ADMIN_PASSWORD fest, bevor der Server aus dem Internet erreichbar ist. Bleiben beide Variablen leer, kann jeder, der den Host findet, auf sämtliche Admin-Endpunkte zugreifen. Für den Betrieb hinter Tailscale oder einem VPN ist das bewusst so vorgesehen. Auf einer öffentlichen IP ist es eine riskante Standardeinstellung.

Trage in .env Folgendes ein:

BOOP_BASE_URL=https://boop.example.com
BOOP_ADMIN_USER=you
BOOP_ADMIN_PASSWORD=a-long-password-here

BOOP_BASE_URL ist wichtiger, als es zunächst wirkt. Diese URL wird in den QR-Code für die Kopplung geschrieben. Zeigt sie noch auf localhost, scannt dein iPhone einen Code, der auf das iPhone selbst verweist.

Schalte einen Reverse Proxy mit gültigem Zertifikat vor den Server. Nginx und Caddy eignen sich beide. Der Proxy muss den Traffic lediglich an Port 8080 weiterleiten. Starte den Dienst neu, damit die Änderungen greifen:

docker compose up -d

Admin-Sitzungen sind 30 Tage gültig und liegen im Arbeitsspeicher. Ein Serverneustart meldet dich deshalb ab. Projekt- und Gerätezugangsdaten werden an Admin-Endpunkten abgelehnt. Ein geleakter API-Schlüssel aus einer deiner Apps gewährt somit keine Admin-Rechte.

Schritt 3: Apple-Push-Benachrichtigungen einrichten

Für APNs brauchst du vier Angaben aus dem Apple-Developer-Portal: deine Team-ID, die Schlüssel-ID eines APNs-Authentifizierungsschlüssels, die Bundle-ID deines Boop-Builds und die zugehörige .p8-Schlüsseldatei.

  1. Erstelle eine App-ID für deinen Boop-iOS-Build und aktiviere Push Notifications.
  2. Erstelle unter Keys einen APNs-Authentifizierungsschlüssel und lade die .p8-Datei herunter. Apple erlaubt den Download nur einmal.
  3. Notiere die Schlüssel-ID und deine Team-ID oben rechts im Portal.

Speichere den Schlüssel auf dem Server unter ./secrets/apns.p8, entferne in docker-compose.yml die Auskommentierung des Secrets-Volumes und ergänze .env:

APNS_TEAM_ID=XXXXXXXXXX
APNS_KEY_ID=XXXXXXXXXX
APNS_BUNDLE_ID=com.example.boop
APNS_PRIVATE_KEY_PATH=/run/secrets/apns.p8
APNS_ENVIRONMENT=production

Starte Boop mit docker compose up -d neu. Auf der Einstellungsseite sollte APNs anschließend als konfiguriert angezeigt werden. Falls nicht, lies den Abschnitt zur Fehlerbehebung weiter unten, bevor du neue Schlüssel erzeugst.

Schritt 4: iOS-App bauen und dein iPhone koppeln

Die iOS-App von Boop ist nicht im App Store erhältlich, daher baust und signierst du sie selbst in Xcode. Öffne ios/Boop.xcodeproj, wähle dein Entwicklungsteam und trage dieselbe Bundle-ID ein, die du unter APNS_BUNDLE_ID angegeben hast. Installiere den Build danach auf deinem iPhone. Die App ist für iOS 26 ausgelegt und enthält eine Notification Service Extension.

Für die Kopplung verwendet Boop einen einmalig nutzbaren QR-Code. Öffne in der Weboberfläche Devices, wähle Pair iPhone und scanne den Code mit der App. Die Nutzlast ist klein:

{"version": 1, "server": "https://boop.example.com", "token": "pair_..."}

Das Token ist zehn Minuten gültig, funktioniert einmal und lässt sich widerrufen. Die App tauscht es gegen Gerätezugangsdaten, registriert sich bei APNs und sendet ihr Token an den Server zurück. Prüfe unter Settings die gesamte Verbindung und wähle anschließend Send test notification. Vibriert dein iPhone, funktioniert die komplette Übertragungskette.

Schritt 5: Dein erstes Ereignis senden

Für die gesamte Integration reicht eine POST-Anfrage an /api/v1/events mit einem Projekt-API-Schlüssel. Erstelle in der Weboberfläche ein Projekt und kopiere den einmalig angezeigten Schlüssel:

curl https://boop.example.com/api/v1/events \
  -H "Authorization: Bearer boop_proj_..." \
  -H "Content-Type: application/json" \
  -d '{"title": "Deploy complete", "level": "success"}'

Ein erfolgreicher Aufruf gibt {id, created_at} zurück. Als Stufen stehen info, success, warning, error und critical zur Verfügung.

Ereignisse können auch strukturierte Daten enthalten. Boop stellt bekannte Bereiche wie exception, stacktrace, tags, context und breadcrumbs passend dar. Alle anderen Daten bleiben nach der Schwärzung unverändert:

curl https://boop.example.com/api/v1/events \
  -H "Authorization: Bearer boop_proj_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "KeyError", "body": "key :can_palette? not found",
    "level": "error", "source": "error_tracker", "fingerprint": "uini-keyerror",
    "data": {
      "exception": {"type": "KeyError", "message": "key :can_palette? not found"},
      "tags": {"environment": "production"}
    }
  }'

Als Shell-Funktion kannst du den Aufruf aus jedem Cronjob oder Deployment-Skript verwenden:

boop() { curl -fsS "$BOOP_URL/api/v1/events" -H "Authorization: Bearer $BOOP_API_KEY" \
  -H "Content-Type: application/json" -d "{\"title\": \"$1\", \"body\": \"${2:-}\", \"level\": \"${3:-info}\"}"; }

pg_dump mydb > backup.sql && boop "Backup complete" "" success || boop "Backup failed" "$(tail -1 backup.log)" error

Clientbibliotheken gibt es für Elixir und Node.js, außerdem steht ein von der Community gepflegtes Laravel-Paket bereit. Boop unterstützt auch das Sentry-Ingest-Protokoll. Ein serverseitiges Sentry SDK kann deshalb Ereignisse an Boop melden, wenn SENTRY_DSN auf deinen Boop-Host zeigt und ein Projekt-API-Schlüssel als öffentlicher Schlüssel dient. Behalte diese DSN auf dem Server. Anders als ein echter öffentlicher Sentry-Schlüssel kann ein Boop-Projektschlüssel Ereignisse schreiben.

Konfiguration für den ersten Tag

Vier Einstellungen ersparen dir später Arbeit: Aufbewahrung, Schwärzung, Aktionen und Stummschaltungen.

Aufbewahrung. BOOP_RETENTION_DAYS steht standardmäßig auf 90. Mit 0 bewahrst du Ereignisse dauerhaft auf. Die Umgebungsvariable überschreibt bei jedem Start den in der Weboberfläche gespeicherten Wert. Lass sie daher leer, wenn du die Aufbewahrungsdauer unter Settings verwalten möchtest.

Schwärzung. Werte unter Schlüsseln wie password, secret, token, api_key, authorization und private_key werden vor dem Speichern durch [REDACTED] ersetzt. Beim Abgleich spielt die Groß- und Kleinschreibung keine Rolle; - und _ werden gleich behandelt. Eigene Schlüssel kannst du unter Settings ergänzen.

Aktionen. Ein Ereignis kann bis zu drei Schaltflächen enthalten, die eine URL öffnen. Sie erscheinen in der Benachrichtigung und in den Ereignisdetails. Beschriftungen dürfen höchstens 40 Zeichen lang sein, URLs müssen absolut sein. Mit einer Schaltfläche „In Stripe öffnen“ erreichst du einen Zahlungsvorgang direkt aus der Benachrichtigung.

Stummschaltungen. Ein bekannt fehleranfälliger Job muss dich nicht wecken. Klicke bei einem Ereignis auf Silence events like this und gleiche Fingerprint, Titel oder Quelle für ein einzelnes oder alle Projekte ab. Passende Ereignisse landen weiterhin als stummgeschaltet in der Inbox, lösen aber keinen Push aus.

Die Gruppierung funktioniert parallel zu Stummschaltungen. Sende für dasselbe Problem immer denselben fingerprint. Die Inbox fasst es dann in einer Zeile zusammen: KeyError ×47 · First seen 09:31 · Last seen 10:42. Jede Instanz wird weiterhin gespeichert und als Push gesendet. Die Gruppierung räumt also nur die Anzeige auf, nicht die Benachrichtigungen.

Der passende Server für Boop

Ein kleiner VPS ist der passende Ort für Boop. Die Last besteht aus einem einzelnen Go-Prozess, der in eine SQLite-Datei schreibt, sowie gelegentlichen ausgehenden TLS-Verbindungen zu Apple. CPU- und Arbeitsspeicherbedarf fallen daher kaum ins Gewicht. Wichtiger sind eine stabile öffentliche Adresse und gute Uptime, weil dein iPhone bei jedem Öffnen einer Benachrichtigung die vollständigen Ereignisdetails vom Server abruft.

Core VPS ist die kostenoptimierte Reihe bei Contabo und für gleichmäßige Workloads mit geringen Anforderungen wie diesen ausgelegt. Cloud VPS 4 bietet 8 GB RAM. Das ist deutlich mehr, als Boop benötigt, und lässt genügend Reserve für deinen Reverse Proxy und weitere selbst gehostete Dienste auf demselben Server.

Sichere data/boop.db mit einem konsistenten Snapshot statt mit einer einfachen Dateikopie:

sqlite3 data/boop.db ".backup backup.db"

Sichere den .p8-Schlüssel getrennt von der Datenbank. Geht er verloren, musst du einen neuen APNs-Schlüssel erzeugen und deine Geräte erneut koppeln.

Fehlerbehebung: vier häufige Probleme

Die meisten Probleme mit Boop gehen auf die Konfiguration zurück. Vier Fehler verursachen den Großteil der gemeldeten Fälle.

APNs wird nach dem Deployment weiterhin als nicht konfiguriert angezeigt. Ursache: APNS_PRIVATE_KEY_PATH enthält einen Wert, aber unter diesem Pfad liegt keine Datei. Das passiert, wenn du .env.example vollständig kopierst und zusätzlich APNS_PRIVATE_KEY direkt einträgst. Der Pfad hat immer Vorrang vor dem direkt angegebenen Schlüssel. Lösung: Verwende nur eine Variante und lass die ungenutzte Variable vollständig leer.

SQLite kann nicht in /data/boop.db schreiben. Ursache: Das per Bind-Mount eingebundene Verzeichnis ./data gehört root, während das Image mit der UID 1000 läuft. Lösung: Führe chown 1000:1000 data aus oder verwende ein benanntes Volume. Nutze bei Dokploy docker-compose.dokploy.yml. Diese Datei richtet das Volume entsprechend ein und entfernt den veröffentlichten Port, damit der Server nur über deinen HTTPS-Proxy erreichbar ist.

Der QR-Code lässt sich scannen, aber das iPhone kann keine Verbindung herstellen. Ursache: BOOP_BASE_URL ist leer oder zeigt auf localhost. Die QR-Nutzlast verweist das iPhone dadurch auf eine Adresse, die aus seinem Netzwerk nicht erreichbar ist. Lösung: Setze BOOP_BASE_URL auf die öffentliche HTTPS-URL und erzeuge ein neues Kopplungstoken.

Von einem Xcode-Debug-Build kommen keine Pushs an. Ursache: APNS_ENVIRONMENT steht standardmäßig auf production, während sich ein Debug-Build am Sandbox-Gateway registriert. Lösung: Verwende während der Entwicklung APNS_ENVIRONMENT=sandbox und wechsle vor der Veröffentlichung zurück.

FAQ

Funktioniert Boop unter Android?

Nein. Boop sendet Pushs über die APNs von Apple. Der einzige Client ist eine quelloffene iOS-App, die du selbst baust, daher brauchst du derzeit ein iPhone mit iOS 26. Im Projekt-Repository ist ein nativer Desktop-Client als geplant aufgeführt. Ereignisse sind unabhängig von der Plattform immer in der eingebetteten Weboberfläche sichtbar. Android-Nutzer können die Inbox deshalb ohne Push-Benachrichtigungen im Browser lesen.

Brauche ich einen kostenpflichtigen Apple-Developer-Account?

In der Praxis ja. Zum Erstellen eines APNs-Authentifizierungsschlüssels musst du den Bereich Keys unter Certificates, Identifiers and Profiles verwenden. Dafür brauchst du in einem registrierten Team die Rolle Account Holder oder Admin. Ein kostenloses Bereitstellungsprofil läuft außerdem nach sieben Tagen ab. Du müsstest die App daher jede Woche neu bauen und installieren. Plane die jährliche Mitgliedschaft ein, wenn du Boop dauerhaft nutzen möchtest.

Welche Serverressourcen braucht Boop?

Sehr wenige. Laut Projektentwickler belegt der Server auf dessen Rechner etwa 8 MB Arbeitsspeicher. Die Datenbank besteht aus einer einzelnen SQLite-Datei, deren Größe von deinem Ereignisvolumen und der Aufbewahrungsdauer abhängt. Die praktische Untergrenze ergibt sich aus den Anforderungen deines Reverse Proxys und Betriebssystems. Jeder Einstiegs-VPS mit mindestens 1 GB RAM reicht aus; zwischen Ereignissen ist die CPU praktisch inaktiv.

Kann ich Boop mit einem vorhandenen Sentry SDK verwenden?

Ja. Boop implementiert den Envelope-Endpunkt des Sentry SDK. Daher kann jedes aktuelle serverseitige Sentry SDK an Boop melden, wenn <code>SENTRY_DSN</code> auf deinen Boop-Host zeigt und ein Projekt-API-Schlüssel als öffentlicher Schlüssel dient. Ausnahmen werden zu Boop-Ereignissen, deren Titel aus Typ und Wert besteht. Sentry-Gruppierungs-Fingerprints bleiben erhalten. Transaktionen und Sitzungen werden angenommen und ignoriert.

Was passiert mit Ereignissen, während mein iPhone offline ist?

Nichts geht verloren. Jedes Ereignis wird auf deinem Server in SQLite gespeichert, unabhängig davon, ob der Push zugestellt wird. Die Inbox in der App und die Weboberfläche zeigen den vollständigen Verlauf innerhalb deiner Aufbewahrungsdauer. Der Push selbst enthält nur Titel, Text und Ereignis-ID. Beim Öffnen ruft die App die Details von deinem Server ab.

Kann ein KI-Agent meine Boop-Inbox lesen?

Ja. Boop stellt unter <code>/mcp</code> per Streamable HTTP einen schreibgeschützten Model-Context-Protocol-Endpunkt bereit. Seine Werkzeuge können Projekte auflisten, Ereignisse durchsuchen und ein vollständiges Ereignis oder alle Instanzen eines Fingerprints abrufen. Setze <code>BOOP_MCP_TOKEN</code> auf mindestens 16 Zeichen und verwende den Wert als Bearer-Token. Boop enthält kein eigenes Modell, sondern stellt nur strukturierte Kontextdaten bereit.

Teilen 𝕏 in