Files
homelab-infra/docs/WORKFLOW.md
T
Micha cd650b19ac Close Gitea signup, dedup posture-check alerts, extend Borg scope
Operational hardening across several services after live incident
analysis between 2026-05-18 and 2026-05-20:

- Gitea: disable public registration and OpenID signup/signin to
  stop the external POST / 5xx bursts that triggered availability
  alerts. New repo-wide policy requires every productive
  Micha/homelab-infra Komodo stack to ship with an active
  Gitea->Komodo webhook on the current stack ID (documented in
  CLAUDE.md, AI_CONTEXT.md, WORKFLOW.md).
- posture-check: extract the Disk1 fstype check into its own
  function so the documented Disk1 NTFS exception no longer raises
  ntfy warnings, skip POSIX inode checks on NTFS, and dedup ntfy
  alerts via a fingerprint state file with ALERT_REPEAT_SECONDS
  (default 24h). Repeat-spam on the same cause now suppressed.
- docker-critical-events: parse the event JSON for container name,
  action, exit code and signal; drop `die exit=0` events (clean
  stops); ship a structured ntfy message instead of the raw event
  line.
- Borg UI: mount /mnt/user/services into the backup container as
  /local/services:ro and include homelab-infra, stacks and
  posture-check in all-important-sources.txt. RESTORE_MATRIX and
  DISASTER_RECOVERY updated accordingly.
- Unraid user scripts: document the new
  homelab-operations-report-daily cron job and the SMTP password
  file it expects on the host.
- MIGRATION_LOG: capture the four live events from this window -
  Gitea 5xx burst + signup closure, Komodo webhook reconciliation,
  posture-check host-version verification, Borg scope extension,
  and Traefik 5xx alert detuning.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 11:05:35 +02:00

358 lines
10 KiB
Markdown

# Workflow - GitOps / No-Drift Regeln
Dieses Dokument definiert den verbindlichen Arbeitsablauf fuer Aenderungen an der Homelab-Infrastruktur.
---
## Ziel
Es darf **keine dauerhafte Abweichung** zwischen:
- Gitea Online
- lokalem Clone
- Komodo-Stacks
- laufenden Docker-Containern
- Host-Konfiguration
geben.
**Grundsatz:**
> Gitea Online ist die operative Quelle der Wahrheit.
---
## Betriebsmodell
Die Rollen sind bewusst getrennt:
- **Gitea Online** ist `origin` und damit der verbindliche Sollzustand.
- Der **lokale Clone** ist die Arbeitskopie fuer Aenderungen.
- **Komodo** deployed aus Gitea und ist kein Bearbeitungsort.
- Der **Host** ist Laufzeit, nicht Quelle der Wahrheit.
### Operative Hierarchie
1. `origin/master` in Gitea
2. lokaler Clone auf dem Windows-PC
3. Komodo-Deployments / Webhooks
4. laufende Container und Host-Dateien
Wenn diese Ebenen voneinander abweichen, gewinnt immer zuerst Git und nicht der manuelle Live-Zustand.
---
## Standard-Workflow
Aenderungen werden immer in dieser Reihenfolge durchgefuehrt:
1. Lokal synchronisieren
2. Lokal aendern
3. Commit erzeugen
4. Push nach Gitea
5. Komodo reagiert automatisch per Webhook
6. Ergebnis testen
7. Doku pruefen und nachziehen
---
## Standardwerkzeug fuer den Alltag
Der bevorzugte lokale Workflow ist:
- **GitHub Desktop** fuer `Fetch`, `Pull`, `Commit`, `Push`
- Editor nach Wahl fuer Datei-Aenderungen
- Gitea Web fuer Historie, Review und kleine Notfaelle
- Komodo nur fuer Deploy-Status, Logs und Stack-Sicht
### Tagesablauf mit GitHub Desktop
Vor lokaler Arbeit:
1. GitHub Desktop oeffnen
2. `Fetch origin`
3. wenn noetig `Pull origin`
Nach lokaler Arbeit:
1. Aenderungen pruefen
2. bei Compose-/Backup-/Restore-Aenderungen relevante manuelle Repo-Checks ausfuehren
- `ops/policy-checks/check_repo.ps1`
- `ops/restore-tests/check-restore-freshness.ps1` oder gezielte Restore-Checks
2. Commit mit sauberer Nachricht
3. `Push origin`
4. Komodo-Webhook im Hinterkopf behalten
---
## Wenn online in Gitea gearbeitet wurde
Web-Aenderungen in Gitea sind erlaubt, aber nicht der Normalfall.
Wenn online etwas geaendert wurde, gilt **vor der naechsten lokalen Arbeit**:
1. GitHub Desktop oeffnen
2. `Fetch origin`
3. `Pull origin`
4. erst dann lokal weiterarbeiten
Sonst entsteht Drift zwischen Gitea Online und lokalem Clone.
---
## Komodo-Regeln
Komodo ist in diesem Setup:
- primaeres Deployment-Werkzeug
- GitOps-Consumer fuer die Stacks
- Monitoring- und Status-Werkzeug
### Deshalb gilt
- Stack-Konfiguration nur im Repository anpassen
- nicht im Komodo-Web-Editor arbeiten
- Pushes koennen automatisch einen Komodo-Deploy ausloesen
- wenn Komodo und Git voneinander abweichen, gewinnt Git
### Pflicht bei neuen Komodo-Stacks
Jeder neue produktive Komodo-Stack, der aus `Micha/homelab-infra` deployed wird, braucht einen aktiven Gitea-Webhook auf die aktuelle Komodo-Stack-ID.
Pflichtschritte beim Anlegen:
1. Stack in Komodo aus Gitea anlegen
2. `webhook_enabled` in Komodo aktivieren
3. passenden Gitea-Webhook fuer die aktuelle Stack-ID anlegen
4. Gitea-Hook gegen `http://komodo-core:9120/listener/github/stack/<stack-id>/deploy` pruefen
5. einen Push oder Test-Delivery ausloesen und `last_status`/Komodo-Deploy pruefen
6. Ausnahmen explizit dokumentieren
**Regel:** Kein neuer produktiver GitOps-Stack ohne funktionierenden Gitea->Komodo-Webhook. Bewusste Ausnahmen muessen im selben Aenderungsblock dokumentiert werden, inklusive Grund und Alternativ-Deploy-Weg.
Der Standardfall nutzt den globalen `KOMODO_WEBHOOK_SECRET` aus der Komodo-Host-`.env`, ausser Komodo zeigt fuer den Stack explizit ein eigenes per-Stack-Secret.
### Ausnahme: Komodo-Zugangsmodell
Komodo bleibt **bewusst** ohne zentrale Traefik-ForwardAuth-Middleware.
Grund:
- Komodo hat eigene Authentifizierung
- Komodo nutzt REST- und WebSocket-Endpunkte
- Webhooks laufen ueber `/listener/...`
- Periphery nutzt den speziellen WebSocket-Pfad `/ws/periphery`
Deshalb wird Komodo aktuell nur ueber Traefik veroeffentlicht, aber **nicht** pauschal mit `authelia@file` vorgeschaltet.
**Regel:** Aenderungen an Komodo-Auth, Komodo-Routing oder vorgeschalteter Middleware nur nach expliziter Wirkungspruefung auf:
- UI-Login
- Gitea-Webhooks
- Periphery-Verbindung
- API-/Automationszugriffe
---
## Verbotene Arbeitsweise
Folgende Dinge sind grundsaetzlich zu vermeiden:
- Aenderungen direkt im Komodo-Web-Editor
- Aenderungen direkt per `docker run`
- Aenderungen an laufenden Containern ohne Repo-Anpassung
- spontane Host-Hotfixes ohne Nachdokumentation
- Secrets im Git-Repository
- mehrere kritische Dienste gleichzeitig migrieren
---
## Erlaubte Arbeitsweise
Erlaubt und gewuenscht sind:
- Aenderungen an Compose-Dateien im Git-Repo
- Commit + Push vor jedem produktiven Deploy
- GitHub Desktop als Standardweg fuer den lokalen Sync
- Gitea Web fuer Review, Historie und kleine Hotfixes
- Host-Hotfixes nur im Ausnahmefall mit sofortiger Nachpflege im Repo
---
## No-Drift-Prinzip
### Definition
**Configuration Drift** liegt vor, wenn der reale Zustand vom Git-Zustand abweicht.
Beispiele:
- laufender Container wurde manuell veraendert
- lokaler Clone ist nicht mehr auf dem Stand von `origin/master`
- Komodo-Stack entspricht nicht mehr dem Repo
- Host-Dateien wurden angepasst, aber nicht dokumentiert
- Traefik dynamic config wurde lokal geaendert, aber Git weiss nichts davon
### Regel
Wenn Drift erkannt wird, gilt:
1. Drift **nicht ignorieren**
2. Drift **sofort benennen**
3. entscheiden:
- Repo an Realitaet anpassen
- oder Realitaet an Repo zurueckfuehren
4. erst danach weiterarbeiten
### Pflichtcheck bei Drift-Verdacht
Vor jedem Reparaturversuch muessen die Ebenen getrennt geprueft werden:
1. lokaler Clone
2. Gitea `origin/master`
3. Komodo Stack Workspace
4. Docker Runtime
5. Host-Netzwerklistener
Das detaillierte Runbook steht in `docs/GITOPS_DRIFT_RUNBOOK.md`.
**Regel:** `HostConfig.PortBindings` allein beweist keinen aktiven Host-Port. Entscheidend sind `NetworkSettings.Ports`, `docker ps`, `ss -ltnp` und ein echter `curl` gegen den Host-Port.
**Stop-Regel:** Wenn zwei Reparaturversuche nicht zum erwarteten Ergebnis fuehren, keine weiteren Schreibbefehle ausfuehren. Erst die Pflichtmatrix aus dem Runbook ausfuellen.
---
## Ausnahmefall: Hotfix auf dem Host
Manchmal ist ein Live-Hotfix noetig. Das ist erlaubt, aber nur unter diesen Bedingungen:
1. Hotfix nur wenn der Dienst sonst nicht funktioniert
2. Aenderung sofort dokumentieren
3. Aenderung danach ins Git-Modell ueberfuehren
4. kein stiller Dauerzustand
### Pflicht bei Hotfixes
- Was wurde geaendert?
- Wo wurde es geaendert?
- Warum war es noetig?
- Muss diese Aenderung ins Repo uebernommen werden?
- Ist ein Rollback dokumentiert?
---
## Ausnahme: Traefik Dynamic Config
> **Diese Dateien werden von Komodo nicht automatisch deployed.**
Komodo deployed ausschliesslich `docker-compose.yml`-Dateien. Die Traefik-Konfigurationsdateien unter `traefik/dynamic/` im Git-Repo werden **nicht** automatisch auf den Host uebertragen.
Diese Ausnahme bleibt bewusst bestehen. Der File-Provider wird weiterhin nur fuer zentrale Middlewares, TLS und Dashboard-Konfiguration genutzt, waehrend Service-Routing ueber Docker-Labels laeuft.
### Betroffene Dateien
| Git-Pfad | Host-Pfad (NAS) |
|---|---|
| `traefik/dynamic/middlewares.yml` | `/mnt/user/appdata/traefik/dynamic/middlewares.yml` |
| `traefik/dynamic/tls.yml` | `/mnt/user/appdata/traefik/dynamic/tls.yml` |
| `traefik/dynamic/dashboards.yml` | `/mnt/user/appdata/traefik/dynamic/dashboards.yml` |
### Pflicht-Workflow bei Aenderungen an Traefik Dynamic Config
1. Datei im Git-Repo (`traefik/dynamic/`) aendern
2. Commit + Push
3. Datei manuell auf den Host kopieren
4. Traefik laedt dynamic config automatisch neu
5. Aenderung testen
> **Merksatz:** Git-Commit allein reicht hier nicht. Ohne den manuellen Kopier-Schritt wirkt die Aenderung nicht.
---
## Secrets-Regeln
- Secrets liegen niemals im Repository
- Secrets liegen unter `/mnt/user/appdata/secrets/`
- Secrets werden ueber Datei-Mounts mit `_FILE` Variablen oder Komodo Stack Environment Variables eingebunden
- Rechte: `chmod 600`
- Secret-Namen und Pfade werden in `docs/SECRETS_MAP.md` dokumentiert
---
## Image-Versionierung
- Mutable Tags wie `latest`, `stable`, `release` oder reine Major-Tags werden nach Moeglichkeit auf den **aktuell laufenden Digest** gepinnt.
- Digest-Pinning friert den bekannten Laufzeitstand ein; es ist **kein** automatisches Upgrade.
- Echte Versions-Upgrades sind ein eigener, bewusster Aenderungsblock mit anschliessendem Test.
- Wenn der laufende Digest unbekannt ist, wird er zuerst am produktiven Container ausgelesen und erst danach im Repo festgeschrieben.
---
## DNS-Regeln fuer Container
Nicht alle Container koennen externe DNS-Namen aufloesen. Standardmaessig nutzt Docker `127.0.0.11` als internen DNS-Resolver. In bestimmten Netzwerk-Setups schlaegt externe Namensaufloesung damit fehl (`server misbehaving`).
### Regel
Container die **externe Domains aufloesen muessen** erhalten explizit:
```yaml
dns:
- 1.1.1.1
- 8.8.8.8
```
### Aktuell betroffen
| Service | Grund |
|---|---|
| `traefik` | ACME Let's Encrypt (`acme-v02.api.letsencrypt.org`) |
| `ddns-updater` | IP-Erkennung (ipify.org) + Cloudflare API |
---
## Dokumentationspflicht
Nach jeder erfolgreichen Migration oder relevanten Aenderung muessen diese Dateien geprueft werden:
- `docs/MIGRATION_LOG.md`
- `docs/SECRETS_MAP.md`
- `docs/ROLLBACK.md`
- `HOMELAB_ARCHITECTURE_MASTER_V2.md` falls Architektur betroffen ist
- `docs/GITOPS_DRIFT_RUNBOOK.md` falls GitOps-/Komodo-/Runtime-Drift betroffen ist
---
## Rollback-Regel
Jede Aenderung muss rueckrollbar sein. Vor jedem Deploy muss klar sein:
- wie der letzte funktionierende Zustand aussieht
- welcher Commit der letzte stabile Stand ist
- ob Datenpfade unveraendert bleiben
- wie der Dienst im Fehlerfall zurueckgenommen wird
Wenn Rollback nicht klar ist, wird nicht deployed.
---
## Arbeitsregel fuer KI-Assistenten
Wenn mit einer KI gearbeitet wird, gilt immer:
> Lies zuerst:
> 1. `HOMELAB_ARCHITECTURE_MASTER_V2.md`
> 2. `docs/WORKFLOW.md`
> 3. die betroffene Compose-Datei
> 4. ggf. `docs/MIGRATION_LOG.md`
Erst danach duerfen Aenderungen vorgeschlagen werden.
---
## Merksatz
> Erst syncen, dann aendern.
> Erst Git, dann Deploy.
> Kein Drift, kein Chaos.