Files
homelab-infra/docs/WORKFLOW.md
T
Micha c677ef0515 Add service removal checklist after stale Borg source finding
Befund vom 2026-05-29: HomelabBorgLastJobCompletedWithWarnings
zuendete vier Tage in Folge mit Borg-Exit-Code 107. Ursache im
Logfile: /local/appdata/homepage wurde am 25.05. entfernt, aber
in der Borg-UI-Source-Liste blieb der Eintrag drin und Borg
warnte taeglich BackupFileNotFoundError. Backups selbst waren
nicht gefaehrdet (alle 23 anderen Quellen sauber archiviert).

Operator hat den Eintrag in der Borg-UI manuell entfernt;
Source-Liste jetzt 23 statt 24, naechster Lauf 2026-05-30 sollte
wieder completed ohne Warning sein.

Erkenntnis: bei Stack-Removal wurde die Borg-Source-Liste nicht
mit-aufgeraeumt. WORKFLOW.md um neuen Abschnitt "Service-Removal-
Checkliste" erweitert mit 9 Pflichtschritten inklusive
Borg-UI-Source-Bereinigung als Schritt 8.

Positiv: die am 2026-05-27 scharfgeschaltete Alert-Pipeline
(Cron Textfile -> node-exporter -> Prometheus -> Alertmanager
-> ntfy-Bridge) hat den Drift binnen 24 h sichtbar gemacht.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 15:01:45 +02:00

381 lines
12 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 |
---
## Service-Removal-Checkliste
Wenn ein Stack endgueltig entfernt wird (Beispiele: Homepage am 2026-05-25, Uptime-Kuma am 2026-05-25, Jellyfin am 2026-05-25), muss in **einem** Aenderungsblock auch der gesamte Sicht-/Backup-Pfad nachgezogen werden, sonst entstehen "Tote-Pfad-Warnings", die erst Tage spaeter auftauchen.
Pflicht-Schritte vor dem Schliessen:
1. Komodo: Stack stoppen, destroy, Stack-Eintrag loeschen.
2. Gitea-Webhook fuer den Stack deaktivieren.
3. Repo-Pfad per `git rm` entfernen.
4. Appdata nach `/mnt/user/appdata/_archive/<name>-removed-YYYY-MM-DD/` verschieben (14 Tage Karenz).
5. DNS-Eintrag im Cloudflare entfernen, sofern Public-Domain.
6. Authelia ACL-Eintrag in `security/authelia/configuration.yml` und auf dem Host bereinigen.
7. Monitoring: Blackbox-Target in `monitoring/blackbox/blackbox.yml` entfernen, Cert-Check-Liste pruefen.
8. **Borg-UI Source-Liste**: `https://borg.kaleschke.info` -> Repository `appdata-critical` -> Source Directories -> alle `/local/appdata/<name>` und ggf. `/local/<name>`-Eintraege loeschen. Sonst kommen daily `HomelabBorgLastJobCompletedWithWarnings`-Push-Nachrichten mit `BackupFileNotFoundError` im Logfile.
9. `docs/SERVICE_CATALOG.md`, `docs/REPO_MAP.md`, `HOMELAB_ARCHITECTURE_MASTER_V2.md` Sektion 7.8 (Entfernt), `docs/MIGRATION_LOG.md` nachziehen.
Wenn ein Stack `webhook_enabled` in Komodo hatte, zusaetzlich pruefen, ob der zugehoerige Gitea-Hook deaktiviert oder geloescht wurde.
---
## Dokumentationspflicht
Nach jeder erfolgreichen Migration oder relevanten Aenderung muessen diese Dateien geprueft werden:
- `docs/MIGRATION_LOG.md`
- `docs/SECRETS_MAP.md`
- `docs/ROLLBACK.md`
- `docs/SERVICES_RECOVERY.md` falls `/mnt/user/services`, Gitea, Komodo oder Host-Automation betroffen sind
- `docs/HARDWARE_INVENTORY.md` und `docs/CAPACITY_AND_LIFECYCLE.md` falls Hardware, Disks, Cache, RAM oder USV betroffen sind
- `docs/NETWORK_INVENTORY.md` und `docs/EXTERNAL_DEPENDENCIES.md` falls Router, DNS, Tailscale, Portfreigaben oder Provider betroffen sind
- `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.