Pitfalls: /etc/hosts verboten, Split-Horizon-DNS bei UCS, Proxmox VMID-Wechsel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
root
2026-01-29 22:46:19 +01:00
parent 5bb99d39bc
commit ff5057b902
6 changed files with 878 additions and 0 deletions

View File

@@ -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

View File

@@ -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=<pw>" | 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
<div class="pf-v5-c-login__main">
<div class="pf-v5-c-login__main-header"> <-- Header-Section (Logo + Titel)
<h1 id="kc-page-title">...</h1>
</div>
<div class="pf-v5-c-login__main-body"> <-- Body-Section (Formular)
...
</div>
</div>
```
**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

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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

View File

@@ -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