# Git-Deploy und Betriebsüberwachung — Baukasten für Laravel-Projekte **Stand:** 07.10.2026 · **Herkunft:** Pressekonto, live seit v1.1.3 (Git-Deploy) bzw. v1.1.0 (Monitoring) **Für:** Entwickler und KI-Chats, die dieses Setup in ein anderes Laravel-Projekt übernehmen. Dieser Ordner beschreibt ein erprobtes Betriebs-Setup aus zwei Teilen und liefert die Dateien dafür mit: 1. **Git-Deploy per Tag** — ausgeliefert wird nur ein Git-Tag, von Hand per SSH, mit einem Skript, das abbricht, bevor es etwas kaputt macht. 2. **Betriebsüberwachung** — Fehler, Ausfälle und stehende Hintergrundprozesse fallen auf, bevor Kunden sie melden: GlitchTip (Fehlerprotokoll), `/health` (tiefer Health-Check), Uptime Kuma (externer Monitor), ntfy (Push aufs Handy). Die Laravel-Vorlagen sind in einem frischen Laravel 12 (12.69, PHP 8.4, Pest 3) eingebaut und getestet (30 Tests grün); `deploy.sh` ist gegen ein simuliertes Repository durchgespielt (Deploy, Abbruch bei Migrationen, Drift, Rollback, fehlender Worker). --- ## Inhalt | Datei | Wofür | |---|---| | [`01-git-deploy.md`](01-git-deploy.md) | Prinzip, einmalige Einrichtung, Release, Deploy, Rollback, Fallstricke | | [`02-fehlerprotokoll-glitchtip.md`](02-fehlerprotokoll-glitchtip.md) | GlitchTip aufsetzen, Laravel anbinden (Server + Browser), Datenschutz, Auswertung per API | | [`03-betriebsueberwachung.md`](03-betriebsueberwachung.md) | `/health`, Scheduler-Herzschlag, Worker-Prüfung, Alarme (Mail + ntfy), Uptime Kuma | | [`04-checkliste-neues-projekt.md`](04-checkliste-neues-projekt.md) | Abhakliste für die Übernahme in ein neues Projekt | | `vorlagen/deploy.sh` | Deploy-Skript (Einstellungen oben im Skript) | | `vorlagen/env-beispiel.env` | alle `.env`-Werte mit Kommentar | | `vorlagen/laravel/…` | PHP/JS/Blade-Dateien und Tests, Pfade wie im Projekt — 1:1 kopierbar | | `vorlagen/server/…` | Docker-Compose für GlitchTip, ntfy, Uptime Kuma; ntfy-Konfiguration; Caddyfile | --- ## Architektur ``` ┌────────────────────────── Monitoring-Server ──────────────────────────┐ │ GlitchTip (errors.…) ntfy (push.…) Uptime Kuma (status.…) │ └─────▲──────────────────────▲──────────────────────┬────────────────────┘ Fehler (Sentry-SDK) │ Betriebs-Alerts │ prüft jede │ Minute │ (JSON-POST) │ /health, /up │ ┌─────────────────────┴──────────────────────┴──────────────────────▼────────────────────┐ │ App-Server: Laravel │ │ • Exceptions + Fehlersignale → GlitchTip • Scheduler schreibt Herzschlag/Minute │ │ • fehlgeschlagene Jobs/Tasks → Mail + ntfy • /health: DB, Cache, Queue, Scheduler, │ │ • deploy.sh: Tag auschecken, Worker prüfen Platte → 200 / 503 │ └─────────────────────▲───────────────────────────────────────────────────────────────────┘ │ git fetch --tags (Deploy-Key, nur lesen) ┌────────┴────────┐ │ Git-Server │ ← lokal: Commit, Assets bauen, Tag, push │ (Forgejo o. Ä.) │ └─────────────────┘ ``` **Wichtig:** Uptime Kuma läuft auf einem anderen Server als die App — sonst fällt der Monitor mit dem überwachten System aus. ntfy liegt auf demselben Server wie Uptime Kuma; fällt dieser aus, kommt kein Push. Dafür gibt es eine zweite Ebene (kostenloser externer Dienst, nur Mail), siehe 03. ### Wer meldet was? | Ausfall | Wer merkt es | Kanal | |---|---|---| | Exception im Code (Request, Job, Command) | Sentry-SDK | GlitchTip → Mail bei neuem Fehlertyp | | JavaScript-Fehler im Browser | `error-reporting.js` | GlitchTip (Projekt Browser) | | Toter interner Link, 403/429 für Angemeldete, 419 | `ReportErrorSignals` | GlitchTip (Warnung) | | Job endgültig fehlgeschlagen | `Queue::failing` | Mail + ntfy | | Geplanter Task fehlgeschlagen | `onFailure` | Mail + ntfy | | Worker steht | `/health` (Queue-Rückstau) | Uptime Kuma → ntfy/Mail | | Scheduler/Cron steht | `/health` (Herzschlag) | Uptime Kuma | | Platte fast voll, DB/Cache weg | `/health` | Uptime Kuma | | Server/PHP-FPM/Nginx/SSL weg | `/up`, `/health` nicht erreichbar | Uptime Kuma (+ zweite Ebene) | | Worker kommt nach dem Deploy nicht zurück | `deploy.sh` (Test-Job) | Exit 3 im Terminal | --- ## Reihenfolge für ein neues Projekt 1. **Monitoring-Server** einmalig aufsetzen (GlitchTip, ntfy, Uptime Kuma) — wird von allen Projekten geteilt. Je Projekt nur neue GlitchTip-Projekte, ein ntfy-Topic und Monitore. 2. **Laravel-Teil** einbauen (02, 03), Tests grün, ausliefern. 3. **Git-Deploy** einrichten (01) — für ein bestehendes Live-Verzeichnis mit der Umwandlung an Ort und Stelle. 4. **Uptime Kuma** auf `/health` richten, Alarm testen. Die Abhakliste dazu: [`04-checkliste-neues-projekt.md`](04-checkliste-neues-projekt.md). --- ## Bewusst nicht im Baukasten - **Zero-Downtime mit Release-Verzeichnissen** (Envoyer/Deployer-Stil): Wer große Dateien unter `storage/app` hält, deployt besser im selben Verzeichnis mit `artisan down` (wenige Sekunden). - **Admin-Systemstatus-Seite**: projektspezifisch. `HealthProbe::scheduler()` und `disk()` lassen sich dort mitbenutzen. - **Webanalyse (Umami)** und **Auswertung fehlgeschlagener Logins**: in Pressekonto vorhanden, aber eng mit dem Projekt verwoben. Muster in 03, Abschnitt „Erweiterungen“. --- ## Erfahrungen aus dem Betrieb (warum es so gebaut ist) | Erfahrung | Folge im Baukasten | |---|---| | Die Testsuite meldete absichtlich provozierte Fehler („Queue weg“) an das echte GlitchTip | DSNs in `phpunit.xml` leer, Wächtertest | | GlitchTip gruppiert nach Text — `…after 20002 ms` und `…20001 ms` wurden getrennte Einträge | keine variablen Zahlen in Meldungen; Fingerprint bei Signalen | | Ein Google-Aussetzer erzeugte 28 Fehlermeldungen in einer Nacht | vorübergehende Fremdfehler: Retry, `Log::warning`, Alarm erst bei Abbruch | | Nach `queue:restart` kam der Worker nicht zurück — Supervisor lief nicht. Eine Stunde blieben Jobs liegen | Worker-Prüfung am Ende von `deploy.sh`, `/health` prüft den Rückstau | | FPM per „Restart“ statt „Reload“ → Socket kurz weg → 502 | `deploy.sh` macht `reload`; Restart nie | | Version auf Live zeigte `v1.1.0-3-g…-dirty` | `deploy.sh` schreibt `RELEASE` = Tag selbst | | macOS-Muster `Icon` in `.gitignore` traf bei `core.ignorecase` auch `resources/views/flux/icon/` | bei der Umstellung `git status` auf Live genau sichten (01, Fallstricke) | | Per SFTP gelöschte Dateien lagen noch auf Live | Umwandlung zeigt Abweichungen, bevor ausgecheckt wird | | `deploy.sh` wird beim Checkout ersetzt, während Bash es liest | Skript läuft aus einer Kopie | | Alte fehlgeschlagene Jobs scheiterten nach `queue:retry all` an geänderten Klassen | nie pauschal `retry all`; `queue:prune-failed` nach 30 Tagen | | `:placeholder="__('…')"` an `` → Alpine-Fehler im Browser, nur durch GlitchTip gefunden | Browserfehler erfassen; Muster mit Wächtertest abfangen |