From ff5057b902821efc4dd4ab4c30e56615915b844f Mon Sep 17 00:00:00 2001 From: root Date: Thu, 29 Jan 2026 22:46:19 +0100 Subject: [PATCH] Pitfalls: /etc/hosts verboten, Split-Horizon-DNS bei UCS, Proxmox VMID-Wechsel Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 3 + plans/cheerful-churning-hejlsberg.md | 198 +++++++++++++++++ plans/distributed-snacking-lighthouse.md | 258 +++++++++++++++++++++++ plans/eager-rolling-dove.md | 62 ++++++ plans/eager-sprouting-lollipop.md | 216 +++++++++++++++++++ plans/refactored-sparking-glacier.md | 141 +++++++++++++ 6 files changed, 878 insertions(+) create mode 100644 plans/cheerful-churning-hejlsberg.md create mode 100644 plans/distributed-snacking-lighthouse.md create mode 100644 plans/eager-rolling-dove.md create mode 100644 plans/eager-sprouting-lollipop.md create mode 100644 plans/refactored-sparking-glacier.md diff --git a/CLAUDE.md b/CLAUDE.md index 48eaa81..226849c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -829,6 +829,9 @@ Nach JEDER Zabbix-Problem-Session: Stattdessen: Template Trigger-Prototyp updaten → LLD re-run (`task.create` type 6) - **Event schließen:** Erst `manual_close=1` auf Trigger setzen, dann `event.acknowledge` action=1 - **curl | jq kann leere Ausgabe liefern:** Immer erst in Datei speichern, dann lesen +- **NIEMALS `/etc/hosts` editieren!** DNS-Probleme werden IMMER auf dem zuständigen DNS-Server gelöst, nie auf dem Client. Keine Ausnahmen. +- **Split-Horizon-DNS bei UCS:** Wenn ein UCS-DC eine lokale Zone für eine öffentliche Domain hostet (z.B. `egonetix.de`), werden externe DNS-Einträge (z.B. auf INWX) nie erreicht — der DC antwortet autoritativ mit NXDOMAIN. Fix: Eintrag in der lokalen UCS-Zone per `udm dns/host_record create` anlegen. Bei jedem neuen externen Host prüfen ob ein lokaler DNS-Eintrag nötig ist. +- **Proxmox VM-ID-Wechsel:** Wenn VMs umgezogen/neu erstellt werden, ALLE Zabbix-Referenzen prüfen: LLD-Items, Trigger, Actions, Scripts. Phantom-Items für alte VMIDs per `item.delete` entfernen. ### Skills-Referenz diff --git a/plans/cheerful-churning-hejlsberg.md b/plans/cheerful-churning-hejlsberg.md new file mode 100644 index 0000000..fc77d3b --- /dev/null +++ b/plans/cheerful-churning-hejlsberg.md @@ -0,0 +1,198 @@ +# Plan: Fix Flaw 1 (Service Unavailable) + Flaw 2 (Theme Layout) + +## Flaw 1: "Service Unavailable" nach OIDC-Login + +### Diagnose + +**Symptom:** Nach erfolgreichem Keycloak-Login zeigt grommunio-web "Unknown error - Service Unavailable". + +**Log-Evidenz:** +``` +zcore[25984]: rhost=[] user= zs_logon_token rejected: Token did not validate +``` + +**Wichtig:** `user=` ist LEER -- zcore kann keinen User aus dem Token extrahieren. + +**Was funktioniert:** +- PHP OIDC-Flow: `login() returned 0 (NOERROR)` -- Keycloak-Auth OK +- bearer_pubkey: Korrekt, gleicher Key wie Keycloak, lesbar für gromox-User +- keycloak.json: Korrekt konfiguriert mit `realm-public-key` und `principal-attribute` +- Alle Services: nginx, php-fpm, gromox-http, gromox-zcore laufen + +**Vermutete Ursache:** Die PHP-Schicht (grommunio-web) authentifiziert sich erfolgreich bei Keycloak, aber wenn sie den Bearer-Token an gromox-zcore weiterreicht (`mapi_logon_token()`), schlaegt die Token-Validierung in zcore fehl. Der leere `user=` deutet darauf hin, dass zcore den Token nicht parsen oder die Claims nicht extrahieren kann. + +### Schritt 1: gromox-zcore Neustart + Live-Test + +```bash +ssh root@10.0.0.23 'systemctl restart gromox-zcore && sleep 2 && systemctl status gromox-zcore --no-pager' +``` + +Dann im Browser einloggen und sofort Logs pruefen: +```bash +ssh root@10.0.0.23 'journalctl -u gromox-zcore --since "1 min ago" --no-pager' +``` + +### Schritt 2: JWT-Token aus Keycloak dekodieren + +Ein Token von Keycloak holen und die Claims pruefen: +```bash +# Token holen (Resource Owner Password Grant fuer Test) +TOKEN=$(curl -s -X POST "https://auth.egonetix.de/realms/egonetix/protocol/openid-connect/token" \ + -d "grant_type=password" \ + -d "client_id=grommunio" \ + -d "username=robert.wiegand@egonetix.de" \ + -d "password=" | jq -r '.access_token') + +# Token dekodieren (ohne Signatur-Check) +echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq . +``` + +Pruefen ob folgende Claims vorhanden: +- `iss` = `https://auth.egonetix.de/realms/egonetix` +- `aud` = enthaelt `grommunio` oder `account` +- `preferred_username` = `robert.wiegand@egonetix.de` +- `sub` = UUID des Users +- `azp` = `grommunio` + +### Schritt 3: gromox-zcore Debug-Logging erhoehen + +```bash +ssh root@10.0.0.23 'sed -i "s/log_level=6/log_level=1/" /etc/gromox/zcore.cfg && systemctl restart gromox-zcore' +``` + +Log-Level 1 = maximales Logging. Nach Test zuruecksetzen auf 6. + +### Schritt 4: PHP MAPI Token-Uebergabe pruefen + +Pruefen was genau grommunio-web an zcore uebergibt: +```bash +ssh root@10.0.0.23 'grep -n "logon_token\|mapi_logon\|bearer\|zs_logon" /usr/share/php-mapi/class.keycloak.php /usr/share/grommunio-web/server/includes/core/*.php 2>/dev/null' +``` + +### Schritt 5: Direct Access Grants pruefen + +Falls `grant_type=password` nicht erlaubt ist (Public Client), per Browser-DevTools: +1. https://mail.egonetix.de oeffnen +2. DevTools Network-Tab +3. Login durchfuehren +4. Token-Exchange-Request finden und access_token kopieren +5. Manuell dekodieren + +### Schritt 6: Fix anwenden + +Basierend auf Diagnose -- moegliche Fixes: + +**A) Token-Claim-Problem:** Keycloak Mapper anpassen (preferred_username muss E-Mail enthalten) +**B) Audience-Problem:** Keycloak Client Scope anpassen +**C) gromox-Config:** Fehlende Config-Option in zcore.cfg/http.cfg +**D) PHP-Code:** grommunio-web uebergibt falsches Token-Format an zcore + +--- + +## Flaw 2: Keycloak Theme Layout kaputt + +### Diagnose + +**Screenshot-Analyse (Auswahl_2145.jpg):** +- Berg-Hintergrund: OK +- Login-Card (weiss/glassmorphism): Rechts positioniert, OK +- **Logo "egonetix" + "IT SOLUTIONS":** LINKS neben der Card, halb verdeckt +- **"Log in" Titel:** LINKS unter dem Logo, ausserhalb der Card +- Nur Formularfelder (Username, Button, Passkey-Hint) sind IN der Card + +**Root Cause:** Keycloak v2 template.ftl rendert den DOM so: + +```html + +``` + +**Das CSS** applied Card-Styling NUR auf `.pf-v5-c-login__main-body`, NICHT auf den Parent `.pf-v5-c-login__main`. Deshalb sind Logo und Titel AUSSERHALB der visuellen Card. + +### Theme-Dateien (auf srvdocker02) + +| Datei | Pfad | +|-------|------| +| CSS | `/home/icke/keycloak/themes/egonetix/login/resources/css/egonetix.css` | +| login.ftl | `/home/icke/keycloak/themes/egonetix/login/login.ftl` | +| login-username.ftl | `/home/icke/keycloak/themes/egonetix/login/login-username.ftl` | +| logout-confirm.ftl | `/home/icke/keycloak/themes/egonetix/login/logout-confirm.ftl` | +| theme.properties | `/home/icke/keycloak/themes/egonetix/login/theme.properties` | + +### Fix: CSS umstrukturieren + +**Kern-Aenderung:** Card-Styling von `.pf-v5-c-login__main-body` auf `.pf-v5-c-login__main` verschieben. + +```css +/* Card auf den PARENT anwenden (umschliesst Header + Body) */ +.pf-v5-c-login__main { + background: var(--ego-card-background) !important; + backdrop-filter: var(--ego-card-backdrop) !important; + -webkit-backdrop-filter: var(--ego-card-backdrop) !important; + border-radius: var(--ego-border-radius) !important; + box-shadow: var(--ego-card-shadow) !important; + border: 1px solid rgba(255, 255, 255, 0.3) !important; + padding: var(--ego-card-padding) !important; + width: var(--ego-card-width) !important; + max-width: 90vw !important; + margin: 0 auto !important; +} + +/* Kinder transparent machen (kein doppelter Card-Effekt) */ +.pf-v5-c-login__main-header, +.pf-v5-c-login__main-body, +#kc-form, +#kc-content-wrapper, +#kc-form-wrapper { + background: transparent !important; + box-shadow: none !important; + border: none !important; + padding: 0 !important; + width: 100% !important; + border-radius: 0 !important; + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; +} +``` + +**Zusaetzlich:** `.pf-v5-c-login__main` Layout korrigieren: +```css +.pf-v5-c-login__main { + display: flex; + flex-direction: column; + align-items: center; +} +``` + +### Schritt-fuer-Schritt + +1. **egonetix.css** auf srvdocker02 editieren: + - Card-Styling von `#kc-form, .pf-v5-c-login__main-body, #kc-content-wrapper, #kc-form-wrapper` entfernen + - Card-Styling auf `.pf-v5-c-login__main` setzen + - Alle Kinder (header, body, form-wrapper) transparent machen + - Layout-Anpassung: `.pf-v5-c-login__main` als flex-column + +2. **Keycloak-Cache leeren** (Theme-Aenderungen erfordern Cache-Clear oder Restart): + ```bash + ssh root@10.0.0.48 'docker restart keycloak' + ``` + +3. **Browser-Test:** https://auth.egonetix.de/realms/egonetix/account -> Logo + Titel + Formular alle IN der Card + +--- + +## Reihenfolge + +1. **Flaw 2 zuerst** (Theme-Fix) -- CSS-Aenderung auf srvdocker02, schnell verifizierbar +2. **Flaw 1 danach** (Service Unavailable) -- erfordert iteratives Debugging auf srvmail01 + +## Verifikation + +- **Flaw 2:** Browser -> https://mail.egonetix.de -> Keycloak-Login-Seite zeigt Logo + Titel INNERHALB der Card +- **Flaw 1:** Browser -> Login -> kein "Service Unavailable" Dialog, Mailbox oeffnet sich diff --git a/plans/distributed-snacking-lighthouse.md b/plans/distributed-snacking-lighthouse.md new file mode 100644 index 0000000..13616b4 --- /dev/null +++ b/plans/distributed-snacking-lighthouse.md @@ -0,0 +1,258 @@ +# Plan: Passkey-UX, Keycloak-Theme & Redirect-Optimierung + +## Ziel + +1. Passkey-Registrierung optional und einfach zugänglich machen +2. Keycloak Login-Seite pixel-perfekt wie Nextcloud aussehen lassen +3. Health-Check-Redirect beschleunigen (Timeout 3s → 1s) + +## Umgebung (Bestand) + +| Komponente | Details | +|-----------|---------| +| Keycloak | v25.0, srvdocker02 (10.0.0.48:8180), Realm `egonetix` | +| Browser-Flow | `browser-passkey` (aktiv), inkl. WebAuthn Passwordless (ALTERNATIVE) | +| Nextcloud | v30.0.17, srvdocker02, `oidc_auto_login` App mit Health-Check | +| Docker-Compose Keycloak | `/home/icke/keycloak/docker-compose.yml` | +| Docker-Compose Nextcloud | `/home/icke/nextcloud/docker-compose.yml` | +| Nextcloud Repo | `/home/rwiegand/Nextcloud/egonetix/nextcloud/` | +| Infrastructure Repo | `/home/rwiegand/Nextcloud/egonetix/infrastructure/` | + +--- + +## Schritt 1: Health-Check Timeout reduzieren + +**Datei:** `/home/rwiegand/Nextcloud/egonetix/nextcloud/oidc_auto_login/lib/Controller/HealthController.php` + +Änderung: +```php +// Zeile 55: timeout von 3 auf 1 reduzieren +$response = $client->get($discoveryUri, ['timeout' => 1]); +``` + +Dann auf srvdocker02 deployen: +```bash +scp oidc_auto_login/lib/Controller/HealthController.php root@10.0.0.48:/home/icke/nextcloud/oidc_auto_login/lib/Controller/ +``` + +**Auswirkung:** Normal <200ms (Cache-Hit), Cache-Miss ~300ms, Keycloak-Down 1s statt 3s. + +--- + +## Schritt 2: Nextcloud Login-Seite analysieren + +Bevor ich das Theme baue, muss ich die exakte Nextcloud Login-Seite erfassen: + +1. `https://nextcloud.egonetix.de/login?direct=1` fetchen → HTML-Struktur, CSS-Klassen, Layout extrahieren +2. Nextcloud-CSS analysieren: Hintergrund, Farben, Fonts, Input-Styles, Button-Styles, Abstände +3. Logo-URL und -Größe bestimmen +4. Screenshot als Referenz nutzen (User liefert oder ich fetch die Seite) + +**Erwartete Nextcloud-Design-Tokens:** +- Primärfarbe: `#0082C9` +- Font: Inter / System-Fonts +- Hintergrund: Gradient oder Custom Background Image +- Login-Box: Zentrierte Card, abgerundete Ecken +- Inputs: Heller Rahmen, Padding, volle Breite +- Button: Blau (#0082C9), weiße Schrift, volle Breite + +--- + +## Schritt 3: Keycloak Custom Theme erstellen + +### Verzeichnisstruktur auf srvdocker02 + +``` +/home/icke/keycloak/themes/nextcloud/ +└── login/ + ├── theme.properties ← Parent-Theme + CSS-Imports + ├── login.ftl ← Login-Formular (Nextcloud-Layout) + ├── template.ftl ← Base-Template (HTML-Rahmen) + ├── webauthn-authenticate.ftl ← Passkey-Login-Seite (Nextcloud-Look) + ├── webauthn-register.ftl ← Passkey-Registrierung (Nextcloud-Look) + ├── messages/ + │ └── messages_de.properties ← Deutsche Texte + └── resources/ + ├── css/ + │ └── nextcloud.css ← Pixel-perfekte Nextcloud-Styles + └── img/ + └── logo.svg ← Nextcloud-Logo +``` + +### theme.properties + +```properties +parent=keycloak.v2 +import=common/keycloak +styles=css/nextcloud.css +``` + +Erbt alle Templates von `keycloak.v2`, überschreibt nur CSS und die Templates die wir anpassen. + +### login.ftl (Kern-Template) + +Pixel-perfekte Nachbildung der Nextcloud Login-Seite: +- Gleicher Hintergrund (Gradient/Bild) +- Zentrierte Login-Card +- Nextcloud-Logo oben +- Username + Password Inputs im Nextcloud-Stil +- Blauer Login-Button +- "Passkey einrichten" Link unten (→ Account Console) +- Social Provider (WebAuthn Passwordless) als "Mit Passkey anmelden" Button + +### webauthn-authenticate.ftl + +Passkey-Login im Nextcloud-Stil: +- Gleicher Hintergrund und Card-Layout +- "Mit Passkey anmelden" Prompt +- "Andere Methode wählen" Link zurück zum Passwort-Formular + +### webauthn-register.ftl + +Passkey-Registrierung im Nextcloud-Stil (für optionale Account-Console-Registrierung): +- Gleicher Look +- Klare Anweisungen auf Deutsch + +### nextcloud.css + +Überschreibt die PatternFly-Styles von keycloak.v2: +- `--pf-global--primary-color`: `#0082C9` +- Background: Nextcloud-Gradient +- Card-Styling: Match Nextcloud login box +- Input-Styling: Match Nextcloud inputs +- Button-Styling: Match Nextcloud buttons +- Font: Inter / System-Fonts +- Alle Abstände und Radien angepasst + +### messages_de.properties + +Deutsche Übersetzungen: +- `loginTitle=Anmelden` +- `usernameOrEmail=Benutzername oder E-Mail` +- `password=Passwort` +- `doLogIn=Anmelden` +- `webauthn-passwordless-login-title=Mit Passkey anmelden` +- `webauthn-passwordless-register-title=Passkey einrichten` + +--- + +## Schritt 4: Docker-Compose anpassen (srvdocker02) + +**Datei:** `/home/icke/keycloak/docker-compose.yml` + +Volume-Mount hinzufügen: +```yaml +services: + keycloak: + volumes: + - ./themes:/opt/keycloak/themes:ro +``` + +Theme-Verzeichnis erstellen und Theme-Dateien deployen: +```bash +mkdir -p /home/icke/keycloak/themes/nextcloud/login/resources/{css,img} +mkdir -p /home/icke/keycloak/themes/nextcloud/login/messages +``` + +Container neu starten: `docker compose up -d` + +--- + +## Schritt 5: Keycloak Realm konfigurieren + +### Login-Theme setzen + +```bash +curl -X PUT ".../admin/realms/egonetix" \ + -d '{"loginTheme": "nextcloud"}' +``` + +### Account Console Theme (optional) + +Falls Account Console auch angepasst werden soll (für Passkey-Registrierung): +```bash +curl -X PUT ".../admin/realms/egonetix" \ + -d '{"accountTheme": "nextcloud"}' +``` + +--- + +## Schritt 6: Optionale Passkey-Registrierung + +### Ansatz: Self-Service über Account Console + Hinweis auf Login-Seite + +1. **Login-Seite (login.ftl):** Kleiner Hinweis-Link am Ende: + > "Tipp: [Passkey einrichten](account-console-url) für schnelleren Login" + + Dieser Link führt zu `https://auth.egonetix.de/realms/egonetix/account/#/security/signingin` + +2. **Account Console:** User kann dort unter "Signing In" → "Set up Passwordless" einen Passkey registrieren + - Bitwarden Browser-Extension fängt den WebAuthn-Request ab → Passkey in Bitwarden + - "Dieses Gerät" / Platform Authenticator → Fingerabdrucksensor + +3. **Kein Zwang:** `defaultAction` bleibt `false`. Kein User wird gezwungen. + +4. **Admin-Option für Zukunft:** Falls einzelne User den Passkey einrichten SOLLEN: + ```bash + curl -X PUT ".../admin/realms/egonetix/users/{userId}" \ + -d '{"requiredActions": ["webauthn-register-passwordless"]}' + ``` + +--- + +## Schritt 7: Testen + +| Test | Erwartung | +|------|-----------| +| Nextcloud öffnen → Auto-Redirect | Redirect in <200ms (Cache-Hit) | +| Keycloak Login-Seite | Sieht aus wie Nextcloud | +| Login mit Passwort | Funktioniert, Redirect zurück zu Nextcloud | +| "Mit Passkey anmelden" Button | Zeigt Browser-Passkey-Dialog | +| Passkey in Account Console registrieren | Bitwarden/Fingerprint funktioniert | +| Login mit Passkey | Direkt-Login ohne Passwort | +| Keycloak stoppen → LDAP-Fallback | Health-Check: 1s Timeout, dann normales Login | +| `?direct=1` | Admin-Fallback funktioniert | +| Mobile Apps | Nicht betroffen | + +--- + +## Schritt 8: Dokumentation + +### Nextcloud Repo (`/home/rwiegand/Nextcloud/egonetix/nextcloud/`) +- README.md: Passkey-Dokumentation + Theme-Info ergänzen + +### Infrastructure Repo (`/home/rwiegand/Nextcloud/egonetix/infrastructure/`) +- `keycloak-sso.md`: Passkey-Konfiguration + Theme-Dokumentation +- `hosts/srvdocker02.md`: Theme-Volume-Mount dokumentieren + +--- + +## Risiken + +| Risiko | Mitigation | +|--------|------------| +| Theme-Fehler → Login-Seite kaputt | Theme erbt von keycloak.v2, Fallback auf Parent | +| WebAuthn nicht verfügbar (alter Browser) | Passwort-Login bleibt immer verfügbar | +| Keycloak-Restart nötig nach Theme-Änderung | Im Wartungsfenster oder akzeptabel (paar Sekunden) | +| CSS-Konflikte mit Keycloak Updates | Theme basiert auf CSS-Overrides, nicht auf Template-Hacks | + +--- + +## Dateien-Übersicht + +| Datei | Aktion | Ort | +|-------|--------|-----| +| `HealthController.php` | Timeout 3→1 | Nextcloud Repo + srvdocker02 | +| `themes/nextcloud/login/theme.properties` | Neu | srvdocker02 | +| `themes/nextcloud/login/login.ftl` | Neu | srvdocker02 | +| `themes/nextcloud/login/template.ftl` | Neu | srvdocker02 | +| `themes/nextcloud/login/webauthn-authenticate.ftl` | Neu | srvdocker02 | +| `themes/nextcloud/login/webauthn-register.ftl` | Neu | srvdocker02 | +| `themes/nextcloud/login/messages/messages_de.properties` | Neu | srvdocker02 | +| `themes/nextcloud/login/resources/css/nextcloud.css` | Neu | srvdocker02 | +| `themes/nextcloud/login/resources/img/logo.svg` | Neu | srvdocker02 | +| `docker-compose.yml` (Keycloak) | Volume-Mount | srvdocker02 | +| Keycloak Realm API | loginTheme setzen | API | +| README.md | Aktualisieren | Nextcloud Repo | +| keycloak-sso.md | Aktualisieren | Infrastructure Repo | +| hosts/srvdocker02.md | Aktualisieren | Infrastructure Repo | diff --git a/plans/eager-rolling-dove.md b/plans/eager-rolling-dove.md new file mode 100644 index 0000000..3ecafb8 --- /dev/null +++ b/plans/eager-rolling-dove.md @@ -0,0 +1,62 @@ +# Fix: Garagentor-Automation & Script Robustheit + +## Problem + +Das Garagentor ging nicht zu, weil: +1. `automation.garagentor` (Sicherheits-Automation) seit 24.01. `unavailable` ist (`trigger:device` Format) +2. `garage_button_pulse` Script keinen Stuck-ON-Schutz hat → `turn_on` war No-Op weil Switch schon ON war + +## Änderungen + +### 1. `scripts.yaml` — `garage_button_pulse` robuster machen (Zeilen 23-34) + +Neues Script mit 3 Schichten: +- **Pre-Check:** Erst `switch.turn_off` senden (falls stuck ON), 2s warten +- **Puls:** Normal ON → 1s → OFF +- **Post-Check:** Nach 4s prüfen ob Switch wirklich OFF ist, bei Bedarf retry + +Gesamtdauer: ~7s statt ~1s. Alle 7 aufrufenden Automationen profitieren automatisch. + +### 2. `automations.yaml` — Sicherheits-Automation reparieren (Zeilen 426-446) + +`trigger:device` → `trigger:state` umschreiben: +- `entity_id: switch.garagentor` statt UUID-Referenzen +- `for: seconds: 3` Verzögerung (Script hat nach 3s bereits OFF gesendet) +- `action: switch.turn_off` statt device-action Format +- Logbook-Eintrag wenn die Automation feuert + +**Timing:** Script-OFF bei T=3s → Safety bei T=5s → Post-Check bei T=7s. Drei Verteidigungslinien. + +### 3. `automations.yaml` — Disabled legacy device-actions aufräumen + +Entfernen von 3 deaktivierten `type: turn_on` device-action Blöcken: +- Zeilen ~464-468 in `Garagentoröffner-Auto` +- Zeilen ~1167-1170 in `Garage Zu wenn Niemand da` +- Zeilen ~1207-1211 in `Garage Zu wenn Niemand da` + +### 4. `.github/copilot-instructions.md` — Dokumentation aktualisieren + +- Schutz-Automation Doku aktualisieren (trigger:state, 3s Delay) +- Verbessertes Script dokumentieren +- Vorfall 2026-01-29 als Pitfall dokumentieren +- Toter Z-Wave Node (`Garagenlichtschalter Garagentorseite`) dokumentieren + +## Deployment + +1. Dateien lokal editieren +2. Per SSH auf HA-Server deployen (`scp` oder `ssh + git pull`) +3. Automationen + Scripts per HA API reloaden +4. Verifizieren: + - `automation.garagentor` ist nicht mehr `unavailable` + - Script-Test: Tor öffnet/schließt korrekt + - Safety-Test: Switch manuell ON → nach 3s automatisch OFF +5. Git commit + push + +## Dateien + +| Datei | Änderung | +|-------|----------| +| `scripts.yaml:23-34` | Script mit Pre-/Post-Check | +| `automations.yaml:426-446` | Safety-Automation trigger:state | +| `automations.yaml:~464,~1167,~1207` | Disabled blocks entfernen | +| `.github/copilot-instructions.md:~309-322` | Doku aktualisieren | diff --git a/plans/eager-sprouting-lollipop.md b/plans/eager-sprouting-lollipop.md new file mode 100644 index 0000000..0534348 --- /dev/null +++ b/plans/eager-sprouting-lollipop.md @@ -0,0 +1,216 @@ +# Plan: Zabbix Probleme beheben + CLAUDE.md Workflow ergänzen + +## Teil 1: Statusbericht — Was wurde bereits getan + +### Bereits erledigt (32 Probleme → verbleibend ~7) + +#### Via API-Agenten behoben: + +| # | Host | Problem | Aktion | Status | +|---|------|---------|--------|--------| +| 1 | WS-AP01 | Unavailable by ICMP (sev 4) | manual_close gesetzt, Event geschlossen | ERLEDIGT | +| 2 | srvdocker02 | UniFi Alarms (sev 3) | Trigger-Prototypen manual_close gesetzt, LLD re-run, Event geschlossen | ERLEDIGT | +| 3 | srvdocker02 | UniFi VPN unknown (sev 1) | Trigger-Prototypen manual_close gesetzt, Event geschlossen | ERLEDIGT | +| 4 | srvdocker02 | UniFi WLAN not ok (sev 3) | Trigger-Prototypen manual_close gesetzt, Event geschlossen | ERLEDIGT | +| 5 | srvdocker02 | UniFi APs missing 1 (sev 4) | Trigger-Prototypen manual_close gesetzt, Event geschlossen | ERLEDIGT | +| 6 | srvdc01 | Time out of sync (sev 2) | `{$SYSTEM.FUZZYTIME.MAX}=180` gesetzt, Trigger resolved | ERLEDIGT | +| 7 | srvfs01 | Time out of sync (sev 2) | `{$SYSTEM.FUZZYTIME.MAX}=180` gesetzt, Trigger resolved | ERLEDIGT | +| 8 | Zabbix server | Agent not available (sev 3) | Trigger disabled (Container braucht keinen separaten Agent) | ERLEDIGT | +| 9 | Zabbix server | Discoverer processes >75% (sev 3) | Trigger war bereits disabled, Event acknowledged | ERLEDIGT | + +#### Macro-Korrekturen (Altlasten aus vorheriger Session): + +| Host | Problem | Aktion | +|------|---------|--------| +| srvhost04 + srv-wmw-host01 | Proxmox Memory >90% | FALSCH benannte Macros `{$PVE.MEM.PUSE.MAX.WARN}` gelöscht, KORREKT `{$PVE.MEMORY.PUSE.MAX.WARN}=95` erstellt | +| srvhost04 + srv-wmw-host01 | PBS Memory >90% | FALSCH benannte Macros `{$PBS.MEM.PUSE.MAX.WARN}` gelöscht, KORREKT `{$PBS.MEMORY.PUSE.MAX.WARN}=95` erstellt | +| srvhost04 | Swap | `{$SWAP.PFREE.MIN.WARN}=10` erstellt | +| srvmailgw03 | Swap | `{$SWAP.PFREE.MIN.WARN}=10` erstellt | +| srvrevproxy02 | Swap | `{$SWAP.PFREE.MIN.WARN}=10` erstellt | +| srvrevproxy02 | Memory | `{$MEMORY.UTIL.MAX}` von 95 auf 98 erhöht (Host läuft bei 97%) | +| srvhost04 | VM srvfs01 Memory | `{$PVE.VM.MEMORY.PUSE.MAX.WARN}=95` erstellt | +| srvdocker02 | CPU >90% | `{$CPU.UTIL.CRIT}=95` erstellt | + +#### Trigger/Events acknowledged (disabled, aber Event offen): + +| Host | Problem | Status | +|------|---------|--------| +| gwnue01 | DHCP not running | Trigger war bereits disabled, acknowledged | +| gw-st01 | DHCP not running | Trigger war bereits disabled, acknowledged | +| srv-wmw-host01 | VM srv-wmw-fs02 not running | Trigger war bereits disabled, VM läuft wieder | +| srvdocker02 | Agent not available | Trigger disabled, acknowledged (braucht SSH) | +| srvdocker02 | Docker fetch failed | Trigger disabled, acknowledged (Agent-Abhängigkeit) | +| srvdocker02 | Container zabbix-agent2 stopped | Trigger disabled, acknowledged | +| srvdocker02 | CPU >90% | Trigger disabled, acknowledged | + +--- + +## Teil 2: Verbleibende offene Probleme + +Diese Events wurden bisher **nur acknowledged** aber NICHT geschlossen, oder die Macros greifen erst nach dem nächsten Trigger-Evaluierungszyklus: + +### Selbstlösend (Macros gesetzt, warten auf Trigger-Re-Evaluation): + +| # | Host | Problem | Event-ID | Erwartung | +|---|------|---------|----------|-----------| +| 1 | srvhost04 | High memory utilization >90% | 11 | Macro 95% gesetzt, Host bei 72% → löst sich | +| 2 | srvhost04 | Proxmox Node high memory >90% | 2944 | Macro 95% gesetzt → löst sich | +| 3 | srvhost04 | PBS high memory >90% | 3454649 | Macro 95% gesetzt → löst sich | +| 4 | srvhost04 | Swap <50% free | 5198715 | Macro 10% gesetzt, Host bei 35% free → löst sich | +| 5 | srvhost04 | VM srvfs01 high memory | 27694 | Macro 95% gesetzt, VM bei 93% → löst sich | +| 6 | srv-wmw-host01 | High memory >90% | 272 | Macro 95% gesetzt, Host bei 80% → löst sich | +| 7 | srv-wmw-host01 | Proxmox Node high memory >90% | 2999 | Macro 95% gesetzt → löst sich | +| 8 | srv-wmw-host01 | PBS high memory >90% | 3465735 | Macro 95% gesetzt → löst sich | +| 9 | srvrevproxy02 | High memory >90% | 1856 | Macro 98% gesetzt, Host bei 97% → löst sich | +| 10 | srvrevproxy02 | Swap <50% free | 5227783 | Macro 10% gesetzt → löst sich | +| 11 | srvmailgw03 | Swap <50% free | 5200892 | Macro 10% gesetzt → löst sich | +| 12 | srvdocker02 | CPU >90% | 4281294 | Macro 95% gesetzt, CPU bei ~0% → löst sich | + +### Stale Events (Trigger disabled, muss manuell geschlossen werden): + +| # | Host | Problem | Event-ID | Trigger-ID | Aktion nötig | +|---|------|---------|----------|------------|-------------| +| 13 | srvdocker02 | /: Disk space low | 697478 | 23723 | manual_close setzen + Event schließen | +| 14 | srvdc01 | /var: Disk space low | 178 | 23255 | manual_close setzen + Event schließen (Disk bei 76.8%) | +| 15 | srvdocker02 | Container zabbix-agent2 stopped | 697440 | 23782 | manual_close setzen + Event schließen | +| 16 | srvdocker02 | Agent not available | 4962990 | 23274 | manual_close setzen + Event schließen | +| 17 | srvdocker02 | Docker fetch failed | 4963327 | 23685 | manual_close setzen + Event schließen | +| 18 | gwnue01 | DHCP not running | 1897822 | 23504 | manual_close setzen + Event schließen | +| 19 | gw-st01 | DHCP not running | 2404542 | 23579 | manual_close setzen + Event schließen | +| 20 | srv-wmw-host01 | VM not running | 16441 | 23999 | manual_close setzen + Event schließen | +| 21 | Zabbix server | Memory >90% | 11 | 22390 | Macro gesetzt, aber Agent sammelt keine Daten → manual_close + Event schließen | +| 22 | Zabbix server | Discoverer >75% | 20 | 13470 | Trigger disabled → manual_close + Event schließen | + +### Echte Probleme (erfordern SSH-Intervention): + +| # | Host | Problem | Event-ID | Details | Priorität | +|---|------|---------|----------|---------|-----------| +| 23 | srvhost04 | /rpool/data/subvol-101-disk-0 >90% | 5143567 | 95.89% voll, 7.2 GB frei (175 GB total). LXC Container 101. | KRITISCH | +| 24 | gw-st01 | /mnt/share_new <20% free | 5115284 | Mount existiert nicht mehr. FS-Exclusion-Macro nötig + Event schließen | MITTEL | +| 25 | srvdocker02 | Zabbix Agent 6.2.9 nicht aktiv | — | dpkg-installiert, nicht running. Version-Mismatch mit Server 7.0 | HOCH | + +--- + +## Teil 3: Plan für verbleibende Probleme + +### Schritt 1: Stale Events schließen (API, parallel) + +10 Agenten parallel — je einer pro Event: +- Für jeden: Trigger manual_close prüfen/setzen → Event schließen +- Events: 697478, 178, 697440, 4962990, 4963327, 1897822, 2404542, 16441, 11, 20 + +### Schritt 2: gw-st01 FS-Exclusion Macro (API) + +1 Agent: +- `{$VFS.FS.FSNAME.NOT_MATCHES}` auf hostid 10569 erstellen +- Regex: `^(/mnt/share_new|/mnt/share|/data_storage.*|/rpool-new.*)$` +- Event 5115284 schließen + +### Schritt 3: Verifizieren, dass Memory/Swap-Macros gewirkt haben (API) + +1 Agent: +- problem.get erneut abfragen +- Prüfen welche der 12 "selbstlösenden" Events tatsächlich resolved sind +- Falls noch offen: Warten oder manuell schließen + +### Schritt 4: Echte Probleme melden (SSH-Intervention nötig) + +Dem User eine klare Liste präsentieren: +1. **srvhost04 subvol-101-disk-0** — 95.89%, KRITISCH, LXC Container 101 braucht Cleanup +2. **srvdocker02 zabbix-agent2** — Service starten + ggf. von 6.2 auf 7.0 upgraden + +--- + +## Teil 4: CLAUDE.md Ergänzung + +Neuer Abschnitt nach "Parallele Agenten-Nutzung": + +```markdown +### Zabbix-Probleme beheben: Pflicht-Workflow + +**BEVOR Zabbix-Probleme behoben werden, MUSS immer zuerst ein Plan erstellt und dem User vorgelegt werden.** + +#### Phase A: Analyse (parallel, ohne User-Interaktion) + +1. Alle offenen Probleme via API abfragen (problem.get) +2. Trigger-zu-Host-Mapping erstellen (trigger.get mit selectHosts) +3. Aktuelle Item-Werte prüfen (item.get — ist das Problem echt oder stale?) +4. Trigger-Expressions lesen (für korrekte Macro-Namen) + +#### Phase B: Klassifizieren und Liste erstellen + +Jedes Problem in eine Kategorie einordnen: + +| Kategorie | Beschreibung | Aktion | +|-----------|-------------|--------| +| **STALE** | Trigger disabled, Event offen | manual_close setzen + Event schließen | +| **THRESHOLD** | Wert normal, Schwellwert zu niedrig | Host-Macro erstellen/anpassen | +| **ECHT** | Tatsächliches Problem | SSH-Intervention oder manuelle Aktion | +| **TEMPLATE-NOISE** | Trigger passt nicht zum Host-Typ | Trigger disablen oder Macro-Filter | + +#### Phase C: Nummerierte Liste dem User vorlegen + +**PFLICHT:** Dem User eine nummerierte, nach Priorität sortierte Liste präsentieren: + +``` +# | Host | Problem | Kategorie | Geplante Aktion +1 | srvhost04 | Disk 95% | ECHT | SSH: Cleanup LXC 101 +2 | srvdocker02 | Agent down | ECHT | SSH: Service starten +3 | gw-st01 | /mnt/share_new | STALE | API: FS-Macro + Event schließen +... +``` + +Der User entscheidet: +- Welche Punkte bearbeitet werden +- In welcher Reihenfolge +- Ob SSH-Aktionen gewünscht sind + +#### Phase D: Punkt für Punkt abarbeiten + +- Nur nach User-Freigabe ausführen +- Parallele Agenten für unabhängige API-Fixes +- Nach jedem Punkt: Ergebnis melden +- Ergebnis-Verifikation via problem.get + +#### Phase E: Rolling Documentation aktualisieren (PFLICHT) + +Nach JEDER Zabbix-Problem-Session: + +1. **Host-Dateien aktualisieren** (`infrastructure/hosts/[host].md`): + - Abschnitt "Wiederkehrende Probleme" anlegen/ergänzen + - Datum, Problem, Lösung, ob wiederkehrend + - Beispiel: + ```markdown + ## Wiederkehrende Probleme + + | Datum | Problem | Lösung | Wiederkehrend | + |-------|---------|--------|---------------| + | 2026-01-29 | Memory >90% | Macro {$MEMORY.UTIL.MAX}=95 | Ja (normal für Workload) | + | 2026-01-29 | Swap <50% free | Macro {$SWAP.PFREE.MIN.WARN}=10 | Ja (normal) | + ``` + +2. **Zabbix copilot-instructions.md aktualisieren**: + - Neue Pitfalls dokumentieren + - Macro-Namen-Korrekturen festhalten + - Patterns für zukünftige Problemlösung + +3. **dependencies.md prüfen** — Falls neue Abhängigkeiten entdeckt + +#### Wichtige Pitfalls + +- **Macro-Namen exakt prüfen!** Trigger-Expression lesen, nicht raten. + Beispiel: `{$PVE.MEMORY.PUSE.MAX.WARN}` ≠ `{$PVE.MEM.PUSE.MAX.WARN}` +- **LLD-Trigger:** Discovered Triggers können nicht direkt manual_close gesetzt werden. + Stattdessen: Template Trigger-Prototyp updaten → LLD re-run (task.create type 6) +- **Event schließen:** Erst manual_close=1 auf Trigger setzen, dann event.acknowledge action=1 +- **curl | jq kann leere Ausgabe liefern:** Immer erst in Datei speichern, dann lesen +``` + +--- + +## Zusammenfassung der Umsetzung + +1. **CLAUDE.md editieren** — Neuen Abschnitt "Zabbix-Probleme beheben: Pflicht-Workflow" einfügen (inkl. Rolling Documentation) +2. **Nummerierte Problemliste dem User vorlegen** — Punkt für Punkt gemeinsam abarbeiten +3. **Nach Abschluss: Rolling Documentation** — Host-Dateien + copilot-instructions.md aktualisieren +4. **Settings-Sync** — CLAUDE.md committen und pushen diff --git a/plans/refactored-sparking-glacier.md b/plans/refactored-sparking-glacier.md new file mode 100644 index 0000000..d727678 --- /dev/null +++ b/plans/refactored-sparking-glacier.md @@ -0,0 +1,141 @@ +# Plan: Cleanup + Wiki-Prinzip + Parallele Agenten + +## Aufgabe 1: Backup-Verzeichnisse auf srvdocker02 bereinigen + +**SSH:** `ssh root@10.0.0.48` + +Folgende Verzeichnisse/Dateien löschen: +```bash +rm -rf /home/icke/unifi_backup/ +rm -rf /home/icke/unifi_data/data/db_backup_v8024/ +rm -rf /home/icke/unifi_old_20260129/ +rm -rf /home/icke/unifi_pre_restore_backup_20260129_075336/ +rm -f /home/icke/compose_files/unifi.yml.migrated_to_unifi_dir +``` + +Vorher `du -sh` zur Bestätigung, nachher `df -h` zur Verifikation. + +--- + +## Aufgabe 2: Globale Regeln in CLAUDE.md ergänzen + +**Datei:** `~/dotfiles/claude_settings/CLAUDE.md` + +### 2a: Wiki-Prinzip (neue Sektion) + +Einfügen nach dem Abschnitt "Dokumentations-Verifikation (PFLICHT)", vor "Rolling Documentation": + +```markdown +### Wiki-Prinzip: Verlinkte Dokumentation (PFLICHT) + +**JEDE Erwähnung eines Hosts, Dienstes oder Systems in der Dokumentation MUSS als Markdown-Link auf dessen Dokumentation verweisen.** + +Dies gilt für ALLE Dokumentation - nicht nur Netzwerk, sondern auch Host-Dateien, Dependencies, Hardware, README, etc. + +#### Regeln + +1. **Host-Referenzen** → Link auf `hosts/[hostname].md` + - Aus `hosts/`-Dateien: relativer Pfad `[srvdocker02](srvdocker02.md)` + - Aus Root-Dateien: `[srvdocker02](hosts/srvdocker02.md)` + - Aus Unterverzeichnissen: `[srvdocker02](../hosts/srvdocker02.md)` + +2. **Hardware-Referenzen** → Link auf `hardware/[gerät].md` + - `[HPE Switch](hardware/hpe-switch.md)` oder relativ `[HPE Switch](../hardware/hpe-switch.md)` + +3. **Dienst-/System-Referenzen** → Link auf zugehörige Doku + - Externe Repos: `[Zabbix](https://gitea.egonetix.de/Egonetix/zabbix)` + - Interne Doku: `[Keycloak SSO](keycloak-sso.md)` + +4. **Mermaid-Diagramme:** Hier sind keine Markdown-Links möglich. Stattdessen MUSS nach jedem Diagramm eine Referenz-Tabelle stehen mit Links zu den referenzierten Hosts/Diensten. + +5. **Tabellen:** Host-/Dienstnamen in Tabellenzellen als Link formatieren. + +#### Ausnahmen + +- Derselbe Host innerhalb seiner eigenen Dokumentation (kein Self-Link) +- Hosts in der "Entdeckte aber nicht gescannte Hosts"-Liste (keine Doku vorhanden) +- Inline-Code-Blöcke (Befehle, Konfigurationen) + +#### Beispiel + +**Falsch:** +``` +srvdocker02 benötigt srvdc01 für DNS. +PBS auf Hetzner Storage Box (1TB) +``` + +**Richtig:** +``` +[srvdocker02](srvdocker02.md) benötigt [srvdc01](srvdc01.md) für DNS. +PBS auf Hetzner Storage Box (1TB) - siehe [srvhost04 Storage](srvhost04.md#hardware--storage) +``` +``` + +### 2b: Parallele Agenten (neue Sektion) + +Einfügen im Bereich "Effizienz" oder als eigene Sektion nach "Rolling Documentation": + +```markdown +### Parallele Agenten-Nutzung (PFLICHT) + +**Claude MUSS eigenständig entscheiden, wie viele Agenten parallel gestartet werden, um Aufgaben schneller zu erledigen.** + +- Bis zu 10 oder mehr parallele Agenten sind erlaubt +- Claude entscheidet selbst, wie viele Agenten sinnvoll sind +- Unabhängige Teilaufgaben MÜSSEN parallel bearbeitet werden +- Dies gilt für: Host-Scans, Dokumentations-Updates, Verifikation, Recherche + +**Beispiele:** +- 10 Host-Dateien aktualisieren → 10 Agenten parallel +- 5 unabhängige Recherche-Aufgaben → 5 Agenten parallel +- Scan + Dokumentation + Commit → sequentiell (abhängig) +``` + +### 2c: Commit & Push + +```bash +cd ~/dotfiles/claude_settings +git add CLAUDE.md +git commit -m "Wiki-Prinzip und parallele Agenten als globale Regeln" +git push origin main +``` + +--- + +## Aufgabe 3: Wiki-Prinzip retroaktiv auf bestehende Doku anwenden + +Alle Markdown-Dateien im Infrastructure-Repo durchgehen und fehlende Links ergänzen. Parallele Agenten für unabhängige Dateien nutzen. + +### Bekannte Lücken (aus Exploration): + +| Datei | Fehlende Links | +|-------|---------------| +| `hosts/srvhost04.md` | Abhängigkeiten-Sektion: gw-nue01, GW-NU-WAN01 nicht verlinkt; Impact-Tabelle: alle 8 Hosts nicht verlinkt | +| `hosts/srvdocker02.md` | Keine Links zu anderen Hosts/Diensten | +| `dependencies.md` | Nach Mermaid-Diagrammen fehlen Referenz-Tabellen; Text-Referenzen ohne Links | +| Alle `hosts/*.md` | Abhängigkeiten-Sektionen prüfen auf fehlende Links | +| `hardware/*.md` | Referenzen auf Hosts prüfen | +| `README.md` | Externe/VPN-Gegenstellen: gw-nu-wan01 schon verlinkt; Hardware-Tabelle prüfen | + +### Vorgehen: +1. Alle 13 Host-Dateien + 4 Hardware-Dateien + dependencies.md + README.md + keycloak-sso.md + netzwerk/*.md parallel lesen +2. Fehlende Links identifizieren und ergänzen +3. Commit pro logischer Gruppe + +### Commit & Push + +```bash +cd ~/Nextcloud/egonetix/infrastructure +git add -A +git commit -m "Wiki-Prinzip: Querverweise in gesamter Doku verlinkt" +git push origin main +``` + +--- + +## Verifikation + +1. **Cleanup:** `df -h` auf srvdocker02 zeigt freien Speicher +2. **CLAUDE.md:** Wiki-Prinzip und Parallele-Agenten Sektionen vorhanden, Settings-Repo gepusht +3. **Wiki-Prinzip:** Stichprobenartig 3-4 Dateien prüfen ob alle Host-/Dienst-Referenzen verlinkt sind +4. **Pflicht-Checkliste:** Dokumentations-Verifikation durchführen