Zum Inhalt

Betrieb, Backup & Restore

Was laufen muss

Komponente Benötigt für Prüfung
Web-App Statusseite, Admin, öffentliche API, SLA-Exporte GET /api/health liefert 200
Worker Zustellung von E-Mail, SMS, Webhook und Push, Uptime-Checks, Wartungsbeginn und automatischer Wartungsabschluss, Warnung bei fehlgeschlagenen Benachrichtigungen, Aufräumjobs E-Mail-Events unter Information → Events wechseln von pending zu sent
PostgreSQL Alles Der Health-Check liefert 503, wenn die Datenbank nicht erreichbar ist

Danger

Ohne Worker funktioniert die Statusseite weiter, aber es werden keine Benachrichtigungen zugestellt, Uptime-Checks laufen nicht und abgelaufene Wartungen werden erst abgeschlossen, wenn der Worker wieder läuft. Überwachen Sie den Worker-Prozess.

/api/health prüft nur den Prozess und die Datenbankverbindung. Er enthält keine Fachdaten und eignet sich für externe Probes.

Startvoraussetzungen

  • Die Web-App startet nur mit gesetztem SESSION_SECRET. Fehlt der Wert, bricht der Start mit einer Fehlermeldung ab. Ist er kürzer als 32 Zeichen, erscheint eine Warnung im Log. Erzeugen mit openssl rand -hex 32.
  • Der Worker braucht DATABASE_URL, denselben SETTINGS_ENCRYPTION_KEY wie die Web-App und APP_URL für Links in Benachrichtigungen.
  • Alle Umgebungsvariablen, auch die Grenzwerte der Rate-Limits (AUTH_RATELIMIT_*, PUBLIC_FORM_RATELIMIT_*), beschreibt Deployment, Migrationen & CI.

Backup

Was gesichert werden muss: die PostgreSQL-Datenbank. Sie enthält den gesamten Zustand: Incidents, SLA-Reports mit ihren bestätigten Snapshots, Einstellungen, Abonnenten, API-Tokens und die Tabellen der Job-Queues.

Was getrennt gesichert werden muss: die Geheimnisse aus der Umgebung, da sie nicht in der Datenbank liegen:

  • SETTINGS_ENCRYPTION_KEY. Ohne ihn können verschlüsselte Passwörter und Schlüssel in der Datenbank nicht gelesen werden.
  • SESSION_SECRET
  • ADMIN_PASSWORD_HASH, falls noch verwendet

Dump erstellen:

pnpm db:backup [ziel]      # schreibt backups/slatus-<datenbank>-<zeitstempel>.dump

Die Version von pg_dump muss mindestens der Version des Datenbankservers entsprechen. Bewahren Sie mehrere Generationen auf, legen Sie mindestens eine Kopie außerhalb des Standorts ab und sichern Sie täglich, zum Beispiel per Cron.

Verschlüsselungsschlüssel einführen oder rotieren

  • Wurde SETTINGS_ENCRYPTION_KEY erst nachträglich gesetzt, führen Sie einmalig pnpm db:encrypt-secrets aus. Das verschlüsselt die bisher im Klartext gespeicherten Geheimnisse.
  • Zum Rotieren setzen Sie den bisherigen Schlüssel als SETTINGS_ENCRYPTION_KEY_OLD und den neuen als SETTINGS_ENCRYPTION_KEY, führen pnpm db:rotate-secret-key aus und entfernen danach SETTINGS_ENCRYPTION_KEY_OLD.
  • Gegen eine nicht lokale Datenbank laufen beide Skripte nur mit --yes-i-am-sure. Sichern Sie vorher.

Restore

Das Wiederherstellen ist destruktiv. pnpm db:restore fragt vor dem Überschreiben nach (Eingabe yes) und lehnt eine DATABASE_URL, die „production“ enthält, ohne --yes-i-am-sure ab. Die Version von pg_restore muss mindestens der Version des Datenbankservers entsprechen.

  1. Stoppen Sie Web-App und Worker.
  2. Stellen Sie sicher, dass PostgreSQL läuft und eine leere Zieldatenbank existiert. Das Restore legt die Datenbank nicht an.
  3. Spielen Sie den Dump ein:

bash pnpm db:restore backups/slatus-<…>.dump

  1. Wenden Sie ausstehende Migrationen an: pnpm db:migrate
  2. Starten Sie Web-App und Worker.
  3. Prüfen Sie den Health-Endpunkt und öffnen Sie die Statusseite.

Warning

pnpm db:seed und pnpm db:seed:history löschen Daten und sind nur für Entwicklung und Tests gedacht. Sie laufen nur gegen einen lokalen Host oder eine Datenbank, deren Name auf _dev, _e2e oder _test endet, sonst nur mit --yes-i-am-sure. Alle db:*-Skripte lesen .env.

Migrationen

Migrationen sind nur vorwärts gerichtet. Sie werden mit pnpm db:migrate angewendet, bevor die neue Version startet. Schlägt eine Migration fehl, finden Sie Hinweise zur Wiederherstellung in docs/context/migrations.md im Repository. Bereits angewendete Migrationen dürfen nicht verändert werden.

Routineprüfungen

Intervall Prüfung
Täglich Fehlgeschlagene Events unter Information → Events. Erneut senden oder Ursache prüfen. Der Worker meldet fehlgeschlagene E-Mail-Events zusätzlich alle 10 Minuten als Warnung im Log.
Täglich Backup-Datei vorhanden und aktuell
Wöchentlich Abgelaufene API-Tokens und ungenutzte Abonnenten
Monatlich Offene SLA-Reports und Ausfälle, die auf Bestätigung warten
Nach jeder Änderung Öffentliche Seite und eine Test-Benachrichtigung

Logs

Die Anwendung schreibt strukturierte Logs auf die Standardausgabe. In Produktion sind sie JSON, in der Entwicklung lesbarer Text. Die Log-Stufe legen Sie mit LOG_LEVEL fest (debug bis error), das Format mit LOG_FORMAT (json oder pretty). Durchsuchen Sie die Logs über die Log-Ansicht Ihrer Container-Plattform.

Warnungen, auf die Sie achten sollten:

  • „notification events failed in the last window“: E-Mail-Benachrichtigungen sind fehlgeschlagen.
  • „client ip is private or loopback; reverse proxy may not forward the client ip“: Der Reverse-Proxy gibt die Client-IP nicht weiter, siehe unten.

Sicherheits-Checkliste

  • Entfernen Sie ADMIN_PASSWORD_HASH, sobald ein Datenbank-Admin existiert. Zusätzlich können Sie den Bootstrap-Zugang mit ADMIN_BOOTSTRAP_DISABLED_AFTER ab einem Datum abschalten.
  • Setzen Sie SESSION_SECRET (mindestens 32 Zeichen) und SETTINGS_ENCRYPTION_KEY auf zufällige Werte und bewahren Sie sie sicher auf.
  • Betreiben Sie die Anwendung hinter einem Reverse-Proxy mit HTTPS, der die Client-IP weitergibt, und stellen Sie TRUSTED_PROXY_IP_HEADER passend ein: x-real-ip, wenn der Proxy X-Real-IP setzt, oder x-forwarded-for mit TRUSTED_PROXY_COUNT, wenn er nur X-Forwarded-For ergänzt. Mit einem festen Header kann ein Client den anderen nicht fälschen. Details stehen in Deployment, Migrationen & CI.
  • Prüfen Sie, ob die Grenzwerte für die öffentlichen Formulare (PUBLIC_FORM_RATELIMIT_*) zu Ihrem Besucheraufkommen passen.
  • Entfernen Sie STATUS_PAGE_EMAIL_DRIVER=capture aus der Produktionsumgebung, sonst werden keine Mails versendet.
  • Geben Sie jeder Person die niedrigste Rolle, die ihre Aufgabe abdeckt. Siehe Rollen & Anmeldung.