### Security-Fixes (K1–K6, W1–W4, W7, N1, N5–N6, V1, V5–V7)
- K1: CSRF-Schutz via Double-Submit-Cookie (httpapi/csrf.go + csrf_helpers.go)
- K2: requireScreenAccess() in allen manage-Handlern (Tenant-Isolation)
- K3: Tenant-Check bei DELETE /api/v1/media/{id}
- K4: requirePlaylistAccess() + GetByItemID() für JSON-API Playlist-Routen
- K5: Admin-Passwort nur noch als [gesetzt] geloggt
- K6: POST /api/v1/screens/register mit Pre-Shared-Secret (MORZ_INFOBOARD_REGISTER_SECRET)
- W1: Race Condition bei order_index behoben (atomare Subquery in AddItem)
- W2: Graceful Shutdown mit 15s Timeout auf SIGTERM/SIGINT
- W3: http.MaxBytesReader (512 MB) in allen Upload-Handlern
- W4: err.Error() nicht mehr an den Client
- W7: Template-Execution via bytes.Buffer (kein partial write bei Fehler)
- N1: Rate-Limiting auf /login (5 Versuche/Minute pro IP, httpapi/ratelimit.go)
- N5: Directory-Listing auf /uploads/ deaktiviert (neuteredFileSystem)
- N6: Uploads nach Tenant getrennt (uploads/{tenantSlug}/)
- V1: Upload-Logik konsolidiert in internal/fileutil/fileutil.go
- V5: Cookie-Name als Konstante reqcontext.SessionCookieName
- V6: Strukturiertes Logging mit log/slog + JSON-Handler
- V7: DB-Pool wird im Graceful-Shutdown geschlossen
### Phase 6: Screenshot-Erzeugung
- player/agent/internal/screenshot/screenshot.go erstellt
- Integration in app.go mit MORZ_INFOBOARD_SCREENSHOT_EVERY Config
### UX: PDF.js Integration
- pdf.min.js + pdf.worker.min.js als lokale Assets eingebettet
- Automatisches Seitendurchblättern im Player
### Ansible: Neue Rollen
- signage_base, signage_server, signage_provision erstellt
- inventory.yml und site.yml erweitert
### Konzept-Docs
- GRUPPEN-KONZEPT.md, KAMPAGNEN-AKTIVIERUNG.md, MONITORING-KONZEPT.md
- PROVISION-KONZEPT.md, TEMPLATE-EDITOR.md, WATCHDOG-KONZEPT.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8.4 KiB
Info-Board Neu - Watchdog-Konzept
Ziel
Der Watchdog ueberwacht die kritischen Komponenten des Players und sorgt dafuer, dass der Display-Betrieb bei Abstuerzen oder Verhaengungen automatisch wiederhergestellt wird.
Die Ueberwachung erfolgt auf zwei Ebenen:
- Browser-Watchdog — Ueberwachung von Chromium
- Agent-Watchdog — Ueberwachung des Player-Agents
Grundprinzipien
- Watchdogs sind extern und unabhaengig von den ueberwachten Prozessen
- Erkennung erfolgt aktiv durch Health-Checks, nicht durch Liveness-Pings
- Restart-Strategien sind progressiv und vermeiden Restart-Schleifen
- Logging ist strukturiert und fuer Admin-Diagnosen aussagekraeftig
Browser-Watchdog (Chromium-Ueberwachung)
Aufgaben
Der Browser-Watchdog sorgt dafuer, dass:
- Chromium staendig laeuft und antwortet
- der Renderer nicht in einer Endlosschleife haengt
- Rendering-Fehler nicht zu permanenten Schwarzbildern fuehren
- bei Chromium-Crash oder Verhaengung schnell neugestartet wird
Health-Check-Verfahren
Der Watchdog fuehrt regelmaeßig folgende Checks durch:
1. Prozess-Check
Existiert der Chromium-Prozess noch?
- lsof oder ps-Abfrage auf die PID
- Timeout: sofort bei fehlender PID
2. HTTP-Health-Check auf localhost
GET http://localhost:8081/health
Timeout: 5 Sekunden
Erwartet: 200 OK und JSON-Antwort {status: "ok"}
Die player-ui muss einen einfachen /health-Endpunkt bereitstellen, der schnell antwortet, auch wenn die Playlist gerade verarbeitet wird.
3. Rendering-Verifizierung (optional, Phase 2)
Screenshot-basiert erkennen, ob der Browser:
- Fehlerseite zeigt
- komplett schwarz ist (mehr als 95% schwarze Pixel)
- seit mehreren Minuten denselben Content zeigt, obwohl ein Wechsel erwartet wurde
Diese Methode ist fuer v1 optional, wird aber fuer spaetere Verhaengungserkennung eingeplant.
Ueberwachungs-Intervall
- Health-Check alle 30 Sekunden
- Bei Fehler: sofort Neustart pruefen (kein Warten auf naechsten Zyklus)
Restart-Strategie
Strategie: Exponentieller Backoff mit Maximum
Fehlerfall:
Fehler 1: Sofort neustart (Wait 0s)
Fehler 2: Warte 2s, versuche Restart
Fehler 3: Warte 5s, versuche Restart
Fehler 4: Warte 10s, versuche Restart
Fehler 5+: Warte 30s, versuche Restart
Nach 10 aufeinanderfolgende Fehler ohne erfolgreicher Recovery:
- Alert an Admin (via Server-Status)
- Overlay auf "Error" setzen
- Watchdog-Loop verlangsamen auf 5 Min Intervall
Erfolg-Kriterium
Wenn der Health-Check 3x hintereinander erfolgreich ist:
- Backoff-Zaehler zuruecksetzen auf 0
- naechstes Fehler wieder mit sofort-Restart starten
Logging
Jeder Watchdog-Ereignis wird protokolliert:
{
"ts": "2025-03-23T14:22:15Z",
"component": "browser_watchdog",
"event": "restart",
"reason": "health_check_timeout",
"attempt": 2,
"next_retry_in_ms": 5000,
"details": {
"pid_before": 1234,
"pid_after": 1245,
"http_status_before": 0
}
}
Logging-Ziele:
- strukturiert auf stdout/stderr (JSON)
- lokal in
/var/log/signage/watchdog.logmit Rotation
Agent-Watchdog (systemd-Integration)
Aufgaben
Der Agent-Watchdog (bzw. systemd-Unit) sorgt dafuer, dass:
- der Player-Agent staendig laeuft
- nach Crash oder gewolltem Stop schnell neugestartet wird
- Restart-Grenzen ein Verhaengungsloop verhindern
systemd-Konfiguration
[Service]
Type=simple
ExecStart=/usr/local/bin/player-agent
Restart=always
RestartSec=5
StartLimitInterval=300
StartLimitBurst=10
StandardOutput=journal
StandardError=journal
Bedeutung:
Restart=always— Neustart bei jedem Exit (unabhaengig vom Exit-Code)RestartSec=5— Warte 5 Sekunden vor NeustartStartLimitInterval=300— Zaehle Restarts in einem 300s-FensterStartLimitBurst=10— Mehr als 10 Restarts in 300s fuehrt zu systemd-Stop
Wenn StartLimitBurst erreicht wird:
- systemd laesst den Service stehen
- Admin wird informiert (Status-API setzt
agent_watchdog_failed) - manueller Eingriff oder Admin-Kommando noetig
Health-Check durch Agent selbst
Der Agent sollte intern:
- Broker-Verbindung regelmaeßig pruefen
- Server-Sync-Status tracken
- bei kritischen Innenfehlern nicht einfach weiterlaeufen
Wenn sich der Agent selbst als unheilbar beschaedigt sieht:
- strukturiert mit Exit-Code
1beenden (systemd startet neu) - nicht mit
exit(0)haengend beenden
Verhaeltnis zu systemd
Architektur-Entscheidung
systemd uebernimmt die Prozess-Wiederbelebung fuer den Agent.
Der Browser-Watchdog ist ein separater, von systemd unabhaengiger Prozess, weil:
- Chromium staendiger Ueberwachung bedarf (Health-Checks im 30s-Rhythmus)
- ein Systemd-Watchdog-Timer zu unverzeihlich waere (nur on/off, nicht granular)
- der Browser-Watchdog auch die Systemd-Unit selbst monitoren kann (Defensive Architektur)
Optional: systemd WatchdogSec
Fuer den Agent ist es sinnvoll, auch systemd's Watchdog-Timer zu nutzen:
[Service]
WatchdogSec=30
ExecStart=/usr/local/bin/player-agent
Der Agent muesste dann periodisch systemd-notify --ready senden.
Das ist optional fuer v1, wird aber fuer spaetere Robustheit eingeplant.
Integration mit Player-Setup
Verzeichnisstruktur
/usr/local/bin/
player-agent — Go-Binary
browser-watchdog — Go-Binary oder Shell-Script
/etc/systemd/system/
signage-agent.service
signage-browser-watchdog.service
/var/lib/signage/
watchdog-state.json — letzter Zustand, Backoff-Counter
/var/log/signage/
watchdog.log — strukturiertes Logging
Startup-Reihenfolge
- Basis-System bootet, X11 startet
signage-agent.servicestartet (systemd)- Agent startet, prueft Konfiguration, startet
player-uiHTTP-Server signage-browser-watchdog.servicestartet (systemd)- Watchdog wartet initial 10s, bevor erste Checks starten
- Agent laesst Chromium starten
- Watchdog beginnt Health-Checks
Dieses Ordering verhindert, dass der Watchdog versucht, den Browser zu uberwachen, bevor der Agent bereit ist.
Stopp-Reihenfolge bei Shutdown
- systemd sendet SIGTERM an Agent und Browser-Watchdog
- Watchdog: beendet sich, versucht nicht zu restarten
- Agent: beendet sich, laedt Chromium herunter
- Systemd wartet auf Completion
Fehlerklassifizierung und Admin-Reporting
Fehlerklassen
| Fehlerklasse | Symptom | Watchdog-Aktion | Admin-Alert |
|---|---|---|---|
| Prozess-Crash | PID weg | Sofort neustart | Nach 3x Fehlschlag |
| Health-Check-Timeout | HTTP timeout | Backoff-Restart | Nach 5x Fehlschlag |
| Rendering-Fehler | Browser zeigt Fehlerseite | Neustart | Sofort sichtbar |
| Backoff-Maximum | 10+ Fehler in 5min | Stoppen, Alert | Sofort |
| Agent-Unhealthy | Server-Sync fehlgeschlagen | Systemd-Neustart | Nach 3x Sync-Fehler |
Admin-Oberflaeche
Status-Page und Admin-Dashboard zeigen:
{
"screen_id": "info01",
"browser_status": {
"pid": 1234,
"health": "ok",
"last_check_at": "2025-03-23T14:25:00Z",
"restart_count_5m": 0,
"last_error": null
},
"agent_status": {
"pid": 567,
"uptime_seconds": 3600,
"sync_status": "ok",
"last_sync_at": "2025-03-23T14:24:55Z",
"systemd_restart_count": 0
},
"watchdog_alert": null
}
Konfigurierbare Parameter
In /etc/signage/config.yml oder Umgebungsvariablen:
watchdog:
browser:
check_interval_sec: 30
health_check_timeout_sec: 5
restart_backoff_steps: [0, 2, 5, 10, 30] # Sekunden
max_consecutive_errors: 10
error_window_sec: 300
agent:
systemd_unit: "signage-agent.service"
healthcheck_timeout_sec: 10
Testing und Validierung
Testfaelle fuer den Watchdog:
- Chromium manuell toeten (
kill -9 PID) — sollte innerhalb 30s neustartet werden - Player-Agent starten/stoppen — systemd sollte neustart triggern
- Player-UI HTTP-Server abschalten — Browser-Watchdog sollte neustarten
- Schnelle aufeinanderfolgende Crashes — Backoff-Exponentialfunktion pruefen
- Admin-Kommando
restart_player— geordneter Neustart, dann Restart-Counter nicht erhoeht - Watchdog-Logs auf Struktur und Vollstaendigkeit pruefen
Zusammenfassung
Der Watchdog-Ansatz ist:
- Transparent — klare Logging und Admin-Sichtbarkeit
- Progressive — Backoff statt Restart-Schleife
- Defensiv — mehrere Erkennungsmethoden (Prozess, HTTP, optional Rendering)
- Integriert — arbeitet mit systemd zusammen, nicht gegen es
- Skalierbar — Verfahren gilt fuer alle Player unabhaengig von Standort oder Netzwerk