Kanbanize Kartenerstellung dokumentiert: Arrival-Rule-Workaround, Board-Struktur

- Neuer Abschnitt "Karten erstellen (Aufgaben-Workflow)" mit Workflow A/B
- Bekannte Struktur erweitert: Workflows, Columns, Lanes für Board 1
- Pitfalls ergänzt: Arrival Rule, Parent-Link API, linkedCards read-only
- Settings und Plans aktualisiert

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
root
2026-02-05 13:09:09 +01:00
parent f0dae88639
commit 4277b10f55
21 changed files with 2636 additions and 159 deletions

View File

@@ -1000,6 +1000,40 @@ curl -H "apikey: $(cat ~/.config/kanbanize/token)" \
| Board | 1 | Team Infrastruktur | | Board | 1 | Team Infrastruktur |
| User | 4 | Robert Wiegand | | User | 4 | Robert Wiegand |
**Workflows auf Board 1:**
| Workflow-ID | Name | Zweck |
|-------------|------|-------|
| 1 | Aufgaben | Operative Tasks (Backlog → ToDo → In Bearbeitung → Erledigt) |
| 2 | Themen | Übergeordnete Themen/Epics, Parent-Karten für Aufgaben |
**Columns & Lanes — Workflow 1 (Aufgaben):**
| Column-ID | Name | Section |
|-----------|------|---------|
| 1 | Aufgaben Backlog | Backlog |
| 2 | ToDo | Requested |
| 3 | In Bearbeitung | In Progress |
| 4 | Erledigt | Done |
| 5 | Ready to Archive | Archive |
| Lane-ID | Name |
|---------|------|
| 1 | Default (Aufgaben) |
**Columns & Lanes — Workflow 2 (Themen):**
| Column-ID | Name | Section |
|-----------|------|---------|
| 29 | Themen Backlog | Backlog |
| 8 | Requested | Requested |
| 9 | In Progress | In Progress |
| 10 | Ready to Archive | Done/Archive |
| Lane-ID | Name |
|---------|------|
| 5 | Default (Themen) |
### Pflicht-Workflow bei Vinos-Arbeiten ### Pflicht-Workflow bei Vinos-Arbeiten
**Bei JEDER Arbeit im Kontext `~/Nextcloud/vinos/` MUSS geprüft werden:** **Bei JEDER Arbeit im Kontext `~/Nextcloud/vinos/` MUSS geprüft werden:**
@@ -1082,24 +1116,71 @@ curl -s -X PATCH -H "apikey: $(cat ~/.config/kanbanize/token)" \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards/<CARD_ID>" "https://weinvinosgmbh.kanbanize.com/api/v2/cards/<CARD_ID>"
``` ```
**Bekannte Column-IDs (Board 1):** **Column-IDs:** Siehe "Bekannte Struktur" oben für vollständige Auflistung beider Workflows.
| Column-ID | Name | Section |
|-----------|------|---------|
| 1 | Aufgaben Backlog | Backlog |
| 2 | ToDo | Requested |
| 3 | In Bearbeitung | In Progress |
| 4 | Erledigt | Done |
| 5 | Ready to Archive | Archive |
**Achtung:** Wenn alle Child-Karten einer Parent-Karte auf "Done" stehen, wird die Parent-Karte automatisch mit verschoben. **Achtung:** Wenn alle Child-Karten einer Parent-Karte auf "Done" stehen, wird die Parent-Karte automatisch mit verschoben.
### Karten erstellen (Aufgaben-Workflow)
**Hintergrund:** Workflow 1 (Aufgaben) hat eine Arrival Rule, die verlangt, dass jede Karte mit einem Thema (Parent im Themen-Workflow 2) verknüpft ist. Direkte Kartenerstellung in Workflow 1 per API schlägt daher fehl.
**Workaround:** Karte zunächst in Workflow 2 (Themen) erstellen, Parent-Link setzen, dann nach Workflow 1 verschieben.
#### Workflow A — Thema existiert bereits
```bash
# 1. Karte in Workflow 2 erstellen (Themen Backlog)
NEW_ID=$(curl -s -X POST -H "apikey: $(cat ~/.config/kanbanize/token)" \
-H "Content-Type: application/json" \
-d '{"board_id": 1, "workflow_id": 2, "lane_id": 5, "column_id": 29, "title": "Neue Aufgabe"}' \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards" | jq -r '.data.card_id')
# 2. Parent-Link zum existierenden Thema setzen
curl -s -X PUT -H "apikey: $(cat ~/.config/kanbanize/token)" \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards/$NEW_ID/parents/<THEMA_ID>"
# 3. Nach Aufgaben ToDo verschieben + Titel/Owner setzen
curl -s -X PATCH -H "apikey: $(cat ~/.config/kanbanize/token)" \
-H "Content-Type: application/json" \
-d '{"workflow_id": 1, "column_id": 2, "lane_id": 1, "owner_user_id": 4}' \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards/$NEW_ID"
```
#### Workflow B — Thema existiert noch nicht
```bash
# 1. Thema in Workflow 2 erstellen
THEMA_ID=$(curl -s -X POST -H "apikey: $(cat ~/.config/kanbanize/token)" \
-H "Content-Type: application/json" \
-d '{"board_id": 1, "workflow_id": 2, "lane_id": 5, "column_id": 29, "title": "Neues Thema"}' \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards" | jq -r '.data.card_id')
# 2. Kind-Karte in Workflow 2 erstellen
CHILD_ID=$(curl -s -X POST -H "apikey: $(cat ~/.config/kanbanize/token)" \
-H "Content-Type: application/json" \
-d '{"board_id": 1, "workflow_id": 2, "lane_id": 5, "column_id": 29, "title": "Aufgabe zum Thema"}' \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards" | jq -r '.data.card_id')
# 3. Parent-Link setzen
curl -s -X PUT -H "apikey: $(cat ~/.config/kanbanize/token)" \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards/$CHILD_ID/parents/$THEMA_ID"
# 4. Kind-Karte nach Aufgaben ToDo verschieben
curl -s -X PATCH -H "apikey: $(cat ~/.config/kanbanize/token)" \
-H "Content-Type: application/json" \
-d '{"workflow_id": 1, "column_id": 2, "lane_id": 1, "owner_user_id": 4}' \
"https://weinvinosgmbh.kanbanize.com/api/v2/cards/$CHILD_ID"
```
### Pitfalls ### Pitfalls
- **Kommentare können NICHT gelöscht werden** — weder via API noch UI. Workaround: Inhalt durch `.` ersetzen - **Kommentare können NICHT gelöscht werden** — weder via API noch UI. Workaround: Inhalt durch `.` ersetzen
- **`\n` wird komplett ignoriert** — immer `<br>` verwenden - **`\n` wird komplett ignoriert** — immer `<br>` verwenden
- **Markdown wird NICHT gerendert** — kein `##`, `**`, `-` etc. - **Markdown wird NICHT gerendert** — kein `##`, `**`, `-` etc.
- **`type` ist immer `plain`** — kann nicht auf `html` gesetzt werden, HTML wird trotzdem gerendert - **`type` ist immer `plain`** — kann nicht auf `html` gesetzt werden, HTML wird trotzdem gerendert
- **Arrival Rule auf Workflow 1** blockiert direkte Kartenerstellung per API — Workaround: Karte in Workflow 2 erstellen, Parent setzen, dann nach Workflow 1 verschieben (siehe "Karten erstellen")
- **Parent-Link Endpunkt:** `PUT /cards/{id}/parents/{parent_id}` — nicht POST, nicht PATCH. Entfernen: `DELETE /cards/{id}/parents/{parent_id}`
- **`linkedCards` Sub-Resource ist read-only** — nur GET, keine Manipulation darüber möglich. Parent/Child-Links über `/parents/` und `/children/` Endpunkte verwalten
### In die Task-Abschluss-Checkliste integriert ### In die Task-Abschluss-Checkliste integriert

View File

@@ -0,0 +1,64 @@
# Plan: Spam-Learning für Grommunio auf srvmailgw03 konfigurieren
## Ziel
Das bestehende Spam-Learning-Script auf srvmailgw03 (`/home/skripte/spam_learning.py`) um Grommunio-IMAP-Accounts erweitern, sodass auch Junk-Mails aus Grommunio für SpamAssassin-Training genutzt werden.
## Voraussetzungen (bereits erfüllt)
- IMAP auf srvmail01 für `robert.wiegand@egonetix.de` und `bestellungen@egonetix.de` aktiviert (privilegeBits)
- Gleiche LDAP-Credentials wie Kopano
- SSH-Zugriff auf srvmailgw03 (10.0.0.37)
## Schritte
### 1. Bestandsaufnahme auf srvmailgw03
- SSH auf srvmailgw03
- `/home/skripte/spam_learning.py` lesen und verstehen
- `/home/skripte/wrapper.sh` lesen
- Cronjob-Konfiguration prüfen (`crontab -l`)
- Prüfen wie Credentials gespeichert sind (im Script, Config-Datei, Environment?)
### 2. IMAP-Konnektivität testen
- Von srvmailgw03 aus IMAP-Verbindung zu srvmail01 (10.0.0.23:993) testen
- Login mit `robert.wiegand@egonetix.de` verifizieren
- Junk-Ordner `Junk-E-Mail` identifizieren und auflisten
### 3. Script anpassen
- Grommunio-Accounts zur Konfiguration hinzufügen:
- Server: `10.0.0.23` (srvmail01), Port 993 (IMAPS)
- Account 1: `robert.wiegand@egonetix.de`, Ordner: `Junk-E-Mail`
- Account 2: `bestellungen@egonetix.de`, Ordner: `Junk-E-Mail`
- Beachten: Grommunio nutzt `Junk-E-Mail` (Bindestrich), Kopano nutzt `Junk E-Mail` (Leerzeichen)
- Credentials: Gleiche LDAP-Passwörter wie für die Kopano-Accounts
### 4. Testen
- Script manuell ausführen (Testlauf)
- Log prüfen (`/var/log/pmg-spam-learning.log`)
- Verifizieren: Mails werden gelesen, an sa-learn übergeben, dann gelöscht
### 5. Dokumentation aktualisieren
- README.md im grommunio-Repo: Spam-Learning-Abschnitt verifizieren/aktualisieren
- `infrastructure/hosts/srvmailgw03.md`: Grommunio-Accounts bestätigen
## Kritische Dateien
| Datei | Server | Aktion |
|-------|--------|--------|
| `/home/skripte/spam_learning.py` | srvmailgw03 | Anpassen |
| `/home/skripte/wrapper.sh` | srvmailgw03 | Prüfen |
| `/var/log/pmg-spam-learning.log` | srvmailgw03 | Verifizieren |
| `README.md` | lokal (grommunio-Repo) | Aktualisieren |
| `infrastructure/hosts/srvmailgw03.md` | lokal | Aktualisieren |
## Verifikation
1. Manueller Testlauf des Scripts auf srvmailgw03
2. Log-Ausgabe zeigt erfolgreiche IMAP-Verbindung zu srvmail01
3. Junk-Mails (falls vorhanden) werden verarbeitet und gelöscht
4. Cronjob bleibt unverändert (Script wird bereits täglich um 01:00 ausgeführt)

View File

@@ -1,136 +1,71 @@
# Plan: Fix Flaw 1 (Service Unavailable) + Flaw 2 (Theme Layout) # Plan: Keycloak Theme CSS Fix — Alle Login-Seiten
## Flaw 1: "Service Unavailable" nach OIDC-Login ## Status
### Diagnose - ~~Flaw 1 (Service Unavailable)~~: **ERLEDIGT** — Ursache war das Files-Plugin, vom User deaktiviert
- **Flaw 2 (Theme Layout)**: Offen — CSS-Fix war unvollständig, PatternFly-Overrides fehlen
**Symptom:** Nach erfolgreichem Keycloak-Login zeigt grommunio-web "Unknown error - Service Unavailable". ## Problem-Analyse (aus 4 Screenshots)
**Log-Evidenz:** ### Screenshot 1 — Username-Eingabe
``` - Logo "egonetix / IT Solutions" + "Log in" Titel LINKS neben der Card, kaum lesbar
zcore[25984]: rhost=[] user= zs_logon_token rejected: Token did not validate - Card enthält nur: Username-Feld, Sign In Button, Passkey-Hint
```
**Wichtig:** `user=` ist LEER -- zcore kann keinen User aus dem Token extrahieren. ### Screenshot 2 — Passkey Login
- "Passkey Login" Text LINKS, kaum lesbar
- Card enthält nur: Username, "Sign in with Passkey" Button, "Try Another Way"
**Was funktioniert:** ### Screenshot 3 — Login-Methode wählen
- PHP OIDC-Flow: `login() returned 0 (NOERROR)` -- Keycloak-Auth OK - "Select login method" Text LINKS, kaum lesbar
- bearer_pubkey: Korrekt, gleicher Key wie Keycloak, lesbar für gromox-User - Card enthält: Username, Passkey-Button, Password-Button
- 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. ### Screenshot 4 — Passwort-Eingabe
- **Mehrere Cards übereinandergestapelt!**
- Eine Card zeigt "robert.wiegand", eine andere das Passwort-Feld
- "Try Another Way" außerhalb beider Cards
### Schritt 1: gromox-zcore Neustart + Live-Test ## Root Cause
```bash PatternFly v5 `.pf-v5-c-login__main` nutzt intern **CSS Grid** mit grid-template-areas. Das egonetix CSS setzt `display: flex` OHNE `!important`, wodurch PatternFly's Grid gewinnt. Die Kinder (header, body, footer) werden in separate Grid-Areas platziert statt als Flex-Column innerhalb einer Card.
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: Zusätzlich fehlen Grid-Overrides für `.pf-v5-c-login__container` und PatternFly-Transparenz-Regeln für Footer und innere Wrapper.
```bash
ssh root@10.0.0.23 'journalctl -u gromox-zcore --since "1 min ago" --no-pager'
```
### Schritt 2: JWT-Token aus Keycloak dekodieren ## Betroffene Datei
Ein Token von Keycloak holen und die Claims pruefen: `/home/icke/keycloak/themes/egonetix/login/resources/css/egonetix.css` auf srvdocker02 (10.0.0.48)
```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) ## Fix: CSS-Änderungen
echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
```
Pruefen ob folgende Claims vorhanden: ### Änderung 1 — Layout-Section: PatternFly-Grid killen
- `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.
Ersetze den bestehenden Layout-Block:
```css ```css
/* Card auf den PARENT anwenden (umschliesst Header + Body) */ /* === Layout === */
.pf-v5-c-login,
.login-pf {
background: transparent !important;
min-height: 100vh;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
.pf-v5-c-login__container {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 100% !important;
max-width: none !important;
grid-template-columns: unset !important;
grid-template-rows: unset !important;
}
```
### Änderung 2 — Card-Section: `!important` auf alle Display/Grid-Properties
Ersetze den Card-Block:
```css
/* === Card (Glassmorphism) === */
.pf-v5-c-login__main { .pf-v5-c-login__main {
background: var(--ego-card-background) !important; background: var(--ego-card-background) !important;
backdrop-filter: var(--ego-card-backdrop) !important; backdrop-filter: var(--ego-card-backdrop) !important;
@@ -142,14 +77,28 @@ Basierend auf Diagnose -- moegliche Fixes:
width: var(--ego-card-width) !important; width: var(--ego-card-width) !important;
max-width: 90vw !important; max-width: 90vw !important;
margin: 0 auto !important; margin: 0 auto !important;
/* Kill PatternFly grid, force flex column */
display: flex !important;
flex-direction: column !important;
align-items: center !important;
grid-template-columns: unset !important;
grid-template-rows: unset !important;
grid-template-areas: unset !important;
} }
```
/* Kinder transparent machen (kein doppelter Card-Effekt) */ ### Änderung 3 — Children-Section: Footer + Grid-Area-Overrides hinzufügen
Ersetze den Children-Block (`.pf-v5-c-login__main-footer` und `grid-column/grid-row` fehlten):
```css
/* === Children transparent (no double card) === */
.pf-v5-c-login__main-header, .pf-v5-c-login__main-header,
.pf-v5-c-login__main-body, .pf-v5-c-login__main-body,
.pf-v5-c-login__main-footer,
#kc-form, #kc-form,
#kc-content-wrapper, #kc-content-wrapper,
#kc-form-wrapper { #kc-form-wrapper,
#kc-header-wrapper {
background: transparent !important; background: transparent !important;
box-shadow: none !important; box-shadow: none !important;
border: none !important; border: none !important;
@@ -158,41 +107,66 @@ Basierend auf Diagnose -- moegliche Fixes:
border-radius: 0 !important; border-radius: 0 !important;
backdrop-filter: none !important; backdrop-filter: none !important;
-webkit-backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
/* Kill PatternFly grid-area assignments */
grid-column: unset !important;
grid-row: unset !important;
} }
``` ```
**Zusaetzlich:** `.pf-v5-c-login__main` Layout korrigieren: ### Änderung 4 — Neue Regel: PatternFly-interne Card-Elemente transparent
Hinzufügen nach Children-Block:
```css ```css
.pf-v5-c-login__main { /* === Kill PatternFly card styling inside login === */
display: flex; .pf-v5-c-login__main .pf-v5-c-card,
flex-direction: column; .pf-v5-c-login__main .pf-v5-c-card__body,
align-items: center; .pf-v5-c-login__main fieldset,
.pf-v5-c-login__main legend {
background: transparent !important;
box-shadow: none !important;
border: none !important;
padding: 0 !important;
} }
``` ```
### Schritt-fuer-Schritt ### Änderung 5 — Page-Title-Regel erweitern
1. **egonetix.css** auf srvdocker02 editieren: Ersetze den Title-Block mit breiterer Abdeckung:
- Card-Styling von `#kc-form, .pf-v5-c-login__main-body, #kc-content-wrapper, #kc-form-wrapper` entfernen ```css
- Card-Styling auf `.pf-v5-c-login__main` setzen /* === Page Title === */
- Alle Kinder (header, body, form-wrapper) transparent machen #kc-page-title,
- Layout-Anpassung: `.pf-v5-c-login__main` als flex-column .pf-v5-c-login__main-header h1,
.pf-v5-c-login__main-header-desc,
h1#kc-page-title,
h1.pf-v5-c-title {
text-align: center !important;
font-size: 18px !important;
font-weight: 600 !important;
color: var(--ego-text-primary) !important;
margin: 0 0 var(--ego-spacing-lg) 0 !important;
padding: 0 !important;
width: 100% !important;
}
```
## Deployment
2. **Keycloak-Cache leeren** (Theme-Aenderungen erfordern Cache-Clear oder Restart):
```bash ```bash
# 1. CSS lokal editieren und per SCP deployen
scp egonetix.css root@10.0.0.48:/home/icke/keycloak/themes/egonetix/login/resources/css/egonetix.css
# 2. Keycloak neustarten (Theme-Cache leeren)
ssh root@10.0.0.48 'docker restart keycloak' 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 ## Verifikation
- **Flaw 2:** Browser -> https://mail.egonetix.de -> Keycloak-Login-Seite zeigt Logo + Titel INNERHALB der Card Alle 4 Seiten im Inkognito-Fenster testen:
- **Flaw 1:** Browser -> Login -> kein "Service Unavailable" Dialog, Mailbox oeffnet sich
| Seite | Was prüfen |
|-------|-----------|
| Username-Eingabe | Logo + "Log in" INNERHALB der Card, zentriert |
| Passkey Login | "Passkey Login" Titel INNERHALB der Card |
| Login-Methode wählen | "Select login method" Titel INNERHALB der Card |
| Passwort-Eingabe | NUR EINE Card, Passwort-Feld darin, kein Stacking |
| Responsive (Handy) | Card füllt Bildschirm, kein Overflow |

View File

@@ -0,0 +1,52 @@
# Plan: Aufräumen + Kanbanize-Workflow dokumentieren
## Teil 1: Test-Karte 13515 aufräumen
1. Parent-Link entfernen: `DELETE /api/v2/cards/13515/parents/13458`
2. Zurück nach Ready to Archive (Workflow 2): `PATCH /api/v2/cards/13515``{"workflow_id": 2, "column_id": 10, "lane_id": 5}`
## Teil 2: Kanbanize-Kartenerstellung in CLAUDE.md dokumentieren
Neuer Abschnitt **"### Karten erstellen (Aufgaben-Workflow)"** nach dem bestehenden Abschnitt "Karten verschieben" (Zeile 1095) einfügen.
### Inhalt des neuen Abschnitts
Dokumentiert den 3-Schritt-Workflow, der die Arrival Rule auf Board 1 / Workflow 1 umgeht. Gilt ausschließlich für das Vinos-Board (Board 1, `weinvinosgmbh.kanbanize.com`) — wird als Unter-Abschnitt im bestehenden Vinos-Kanbanize-Block eingefügt:
**Hintergrund:** Workflow 1 (Aufgaben) hat eine Arrival Rule, die verlangt, dass jede Karte mit einem Thema (Parent im Themen-Workflow 2) verknüpft ist. Direkte Kartenerstellung in Workflow 1 per API ist daher nicht möglich.
**Workflow A — Thema existiert bereits:**
1. Karte in Workflow 2 erstellen: `POST /api/v2/cards` mit `workflow_id: 2, lane_id: 5, column_id: 29`
2. Parent-Link setzen: `PUT /api/v2/cards/{new_id}/parents/{parent_id}`
3. Nach Aufgaben ToDo verschieben: `PATCH /api/v2/cards/{new_id}` mit `workflow_id: 1, column_id: 2, lane_id: 1`
4. Titel/Beschreibung/Owner setzen: `PATCH /api/v2/cards/{new_id}` (kann mit Schritt 3 kombiniert werden)
**Workflow B — Thema existiert noch nicht:**
1. Thema in Workflow 2 erstellen: `POST /api/v2/cards` mit `workflow_id: 2, lane_id: 5, column_id: 29`
2. Kind-Karte in Workflow 2 erstellen: `POST /api/v2/cards` (gleiche Parameter)
3. Parent-Link setzen: `PUT /api/v2/cards/{child_id}/parents/{theme_id}`
4. Kind-Karte nach Aufgaben ToDo verschieben: `PATCH /api/v2/cards/{child_id}` mit `workflow_id: 1, column_id: 2, lane_id: 1`
5. Titel/Beschreibung/Owner auf beiden Karten setzen
Ergänzung der **Bekannte Struktur**-Tabelle (Zeile 995) um Workflows, Lanes und Columns beider Workflows.
Ergänzung der **Pitfalls** (Zeile 1097) um:
- Arrival Rule auf Workflow 1 blockiert direkte Kartenerstellung per API
- Parent-Link Endpunkt: `PUT /cards/{id}/parents/{parent_id}` (nicht POST/PATCH)
- `linkedCards` Sub-Resource ist read-only (nur GET)
### Betroffene Datei
- `~/dotfiles/claude_settings/CLAUDE.md` (Zeile ~1076-1102)
## Teil 3: Auto-Memory aktualisieren
Kanbanize-Workflow-Erkenntnisse in `/home/rwiegand/.claude/projects/-home-rwiegand-Nextcloud-vinos-zabbix/memory/MEMORY.md` festhalten.
## Verifizierung
- Karte 13515: `GET /api/v2/cards/13515/parents` → leer, Column = 10 (Ready to Archive)
- Thema 13458: `GET /api/v2/cards/13458``linked_cards` enthält nur 13459 + 13516 (nicht mehr 13515)
- CLAUDE.md: Neuer Abschnitt vorhanden, Settings-Sync nach Gitea gepusht

View File

@@ -0,0 +1,118 @@
# Plan: CIFS-Mount-Monitoring für srv-nu-ftp01
## Ziel
Auf srv-nu-ftp01 alle CIFS-Mounts überwachen, die nach `//vinos.local/DFS/Workflows/` zeigen. Sobald ein Mountpoint nicht aktiv ist, soll Zabbix alarmieren.
## Aktueller Stand
- UserParameters wurden eingetragen, aber **Agent startet nicht** (exit code 1)
- Ursache: Discovery-Zeile über 2 Zeilen umgebrochen → `missing assignment operator` in Zeile 325
- Die Status-Zeile (`cifs.mount.status[*]`) ist OK
## Ist-Zustand fstab
**18 aktive Mounts** (ohne auskommentierte) nach `//vinos.local/DFS/Workflows/`:
- 12× Artikelbilder (gleiche Quelle, verschiedene User-Home-Verzeichnisse)
- Reporting/DWH → `/mnt/Workflows/Reporting/DWH`
- Shop-Filialinfos → `/home/filialinfos/Shop-Filialinfos`
- econda → `/mnt/google_analytics` + `/home/srv-db03/google_analytics`
- sovendus → `/home/sovendus/upload`
- emarsys → `/home/emarsys/upload`
- hubspot → `/home/hubspot/upload`
- Pin-eBrief → `/mnt/Workflows/Pin-eBrief`
- KWK-Export → `/home/kwk-export/KWK-Export`
## Ansatz: Script-File + UserParameters
Die Inline-awk-Variante ist zu lang (~200 Zeichen) und bricht beim Kopieren um. Stattdessen ein minimales Discovery-Script.
## Schritte
### 1. Agent-Config fixen (DRINGEND - Agent ist down!)
Die kaputten Zeilen 324-325 entfernen/ersetzen. Neue Config:
```
UserParameter=cifs.mount.discovery,/etc/zabbix/scripts/cifs_mount_discovery.sh
UserParameter=cifs.mount.status[*],findmnt "$1" >/dev/null 2>&1 && echo 1 || echo 0
```
### 2. Discovery-Script erstellen
Script nach `/home/vinosadmin/cifs_mount_discovery.sh` schreiben (kein root-Zugriff als vinosadmin).
User verschiebt es manuell nach `/etc/zabbix/scripts/cifs_mount_discovery.sh` und setzt `chmod +x`.
```bash
#!/bin/bash
grep -i '//vinos.local/DFS/Workflows' /etc/fstab \
| grep -v '^\s*#' \
| awk 'BEGIN{printf "["} NR>1{printf ","} {printf "{\"{#MOUNTPOINT}\":\"%s\",\"{#REMOTE}\":\"%s\"}",$2,$1} END{printf "]"}'
```
### 3. Agent neustarten und testen
```bash
systemctl restart zabbix-agent2
systemctl status zabbix-agent2
```
Test:
```bash
# Lokal
/etc/zabbix/scripts/cifs_mount_discovery.sh
findmnt /home/fluent/artikelbilder >/dev/null 2>&1 && echo 1 || echo 0
# Via Agent (von srv-monitor02)
zabbix_get -s srv-nu-ftp01 -k 'cifs.mount.discovery'
zabbix_get -s srv-nu-ftp01 -k 'cifs.mount.status[/home/fluent/artikelbilder]'
```
### 4. Host-ID ermitteln
Via Zabbix API: `host.get` mit `search: {name: "ftp01"}`
### 5. Zabbix LLD via API konfigurieren
**a) Discovery Rule** (`discoveryrule.create`)
- Name: `CIFS DFS/Workflows Mount Discovery`
- Key: `cifs.mount.discovery`
- Type: Zabbix Agent (passive/active je nach Config)
- Update Interval: `1h`
**b) Item Prototype** (`itemprototype.create`)
- Name: `CIFS Mount Status: {#MOUNTPOINT}`
- Key: `cifs.mount.status[{#MOUNTPOINT}]`
- Type: Zabbix Agent
- Value Type: Numeric (unsigned)
- Update Interval: `5m`
**c) Trigger Prototype** (`triggerprototype.create`)
- Name: `CIFS Mount {#MOUNTPOINT} nicht aktiv (Remote: {#REMOTE})`
- Expression: `last(/HOST/cifs.mount.status[{#MOUNTPOINT}])=0`
- Severity: High
### 6. Dokumentation
- `zabbix/hosts.md`: srv-nu-ftp01 Abschnitt mit Host-ID, UserParameters, SSH-Befehlen
- `zabbix/README.md`: Host-ID in Schnellreferenz
## Kritische Dateien
| Datei (auf srv-nu-ftp01) | Aktion |
|---------------------------|--------|
| `/etc/zabbix/zabbix_agent2.conf` | Zeilen 324-325 fixen → 2 saubere UserParameter-Zeilen |
| `/etc/zabbix/scripts/cifs_mount_discovery.sh` | Neu erstellen (4 Zeilen) |
| Datei (lokal) | Aktion |
|----------------|--------|
| `zabbix/hosts.md` | srv-nu-ftp01 ergänzen |
| `zabbix/README.md` | Host-ID ergänzen |
## Verifikation
1. `systemctl status zabbix-agent2` → active (running)
2. `zabbix_get -s srv-nu-ftp01 -k 'cifs.mount.discovery'` → JSON mit 18 Mountpoints
3. `zabbix_get -s srv-nu-ftp01 -k 'cifs.mount.status[/home/fluent/artikelbilder]'``1`
4. Zabbix UI: Discovery Rule ausführen → 18 Items + 18 Trigger angelegt
5. Optional: Test-Unmount → Trigger feuert

View File

@@ -0,0 +1,315 @@
# n8n Security Update: 1.123.5 → 2.3.4
## Executive Summary
**Kritikalität:** Hoch - CVE-2025-68668 (CVSS 9.9) ist nur in 2.0.0+ gefixt
**Downtime:** ~5-10 Minuten (PostgreSQL Auto-Migration + Container Rebuild)
**Risiko:** Niedrig - keine Breaking Changes in Workflows gefunden
**Ziel-Version:** 2.3.4 (aktuelle Stable, nicht 2.0.0 wegen Bug-Fixes)
---
## Sicherheitsrisiko-Bewertung
### Status der 4 CVEs in aktueller Version 1.123.5
| CVE | CVSS | Status in 1.123.5 | Risiko |
|-----|------|-------------------|--------|
| **CVE-2026-21858** "Ni8mare" | 10.0 | ✅ GEFIXT (1.121.0) | Unauthenticated RCE über Webhooks |
| **CVE-2026-21877** | 10.0 | ✅ GEFIXT (1.121.3) | Authenticated RCE via Git Node |
| **CVE-2025-68613** | 10.0 | ✅ GEFIXT (1.122.0) | Authenticated Expression Injection |
| **CVE-2025-68668** | 9.9 | ❌ **NICHT GEFIXT** | Python Sandbox Bypass → RCE |
**Fazit:** CVE-2025-68668 erfordert zwingend Update auf 2.0.0+
---
## Breaking Changes Analyse
### ✅ Keine kritischen Breaking Changes
- **Start Nodes:** Nicht verwendet (alle Workflows nutzen manualTrigger/cron/emailReadImap)
- **Code Nodes:** Kein `process.env` Zugriff (N8N_BLOCK_ENV_ACCESS_IN_NODE=true ist ab 2.0 default)
- **Python Code Nodes:** Nicht verwendet (nur JavaScript Code Nodes)
- **Binary Data Mode:** Keine deprecated Configs
### ⚠️ Funktionstest erforderlich
**3 Workflows mit LangChain/OpenAI Integration:**
- `gebuehrenfrei_live.json`
- `instabank_current.json`
- `tfbank_current.json`
**Verwendung:** AI-gestützte Extraktion von Zahlungsinformationen (Fälligkeitsdatum, IBAN, BIC, Betrag)
**Nodes:**
- `@n8n/n8n-nodes-langchain.agent` (v1.1)
- `@n8n/n8n-nodes-langchain.lmChatOpenAi` (v1)
- `@n8n/n8n-nodes-langchain.memoryBufferWindow` (v1)
**Aktion:** Nach Update AI-Extraktion manuell testen
---
## Update-Plan
### Phase 1: Pre-Update Backup
**Kritisch:** PostgreSQL-Datenbank enthält alle Workflows, Credentials, Execution History
```bash
# 1. Auf srvdocker02 per SSH
ssh root@10.0.0.48
# 2. PostgreSQL Backup erstellen
cd /home/icke/n8n
docker exec postgres-n8n pg_dump -U n8n n8n > "backup-$(date +%Y%m%d-%H%M%S).sql"
# 3. Backup komprimieren und sichern
gzip backup-*.sql
ls -lh backup-*.sql.gz
# 4. Optional: Volume-Backup (enthält auch n8n-Files)
tar -czf "n8n-volumes-$(date +%Y%m%d-%H%M%S).tar.gz" /home/icke/n8n_pg/
```
**Backup-Dateien auf Laptop kopieren (Sicherheitskopie):**
```bash
# Von Laptop aus
scp root@10.0.0.48:/home/icke/n8n/backup-*.sql.gz ~/Nextcloud/egonetix/n8n/backups/
```
---
### Phase 2: Update durchführen
**Datei:** `/home/rwiegand/Nextcloud/egonetix/n8n/Dockerfile.n8n-curl`
**Änderung:**
```dockerfile
# Alt:
FROM n8nio/n8n:1.123.5
# Neu:
FROM n8nio/n8n:2.3.4
```
**Rebuild + Restart:**
```bash
# Auf srvdocker02
cd /home/icke/n8n
# Container stoppen
docker compose down
# Rebuild mit neuer Version (dauert ~2-3 Minuten)
docker compose up -d --build
# Logs überwachen (PostgreSQL Auto-Migration)
docker compose logs -f n8n-new
```
**Erwartete Log-Ausgaben:**
- `Running migrations...` (PostgreSQL Schema-Migration)
- `Migration XYZ successful`
- `n8n ready on 0.0.0.0:5678`
**Abbruchkriterium:** Wenn Fehler in Logs → sofort `docker compose down` und Rollback
---
### Phase 3: Verifikation
#### 3.1 Web-UI Zugriff prüfen
```bash
# Von Laptop
curl -I https://flow.egonetix.de/
# Erwartung: HTTP 200 oder 302 (Redirect zu Login)
```
**Browser-Test:**
- https://flow.egonetix.de/ öffnen
- Login mit Owner-Account
- Dashboard sollte laden
#### 3.2 Workflows prüfen
**In Web-UI:**
1. Workflows-Liste öffnen
2. Status der aktiven Workflows prüfen:
- `gebuehrenfrei_live` → aktiv?
- `instabank_current` → aktiv?
- `tfbank_current` → aktiv?
#### 3.3 LangChain/OpenAI Integration testen
**Pro Workflow (gebuehrenfrei_live, instabank_current, tfbank_current):**
1. Workflow öffnen in Editor
2. "Execute Workflow" klicken (manueller Trigger)
3. **Input:** Test-E-Mail mit Kreditkarten-Rechnung
4. **Erwartete Ausgabe:**
- AI Agent extrahiert: Fälligkeitsdatum, IBAN, BIC, Betrag
- Nextcloud Deck Karte wird erstellt (`/home/node/create_card_from_ai.sh`)
5. **Logs prüfen:**
```bash
docker compose logs n8n-new | grep -i "openai\|langchain\|error"
```
**Falls AI-Extraktion fehlschlägt:**
- Workflow-Logs in Web-UI prüfen
- OpenAI API-Key noch gültig? (in Workflow Credentials)
- Rate Limits überschritten?
#### 3.4 IMAP-Trigger testen
**Workflows mit Email-Trigger:**
- Warten auf nächste eingehende Kreditkarten-E-Mail
- Oder: Manuell Test-E-Mail an IMAP-Account senden
- Prüfen ob Workflow automatisch triggert
#### 3.5 Version bestätigen
```bash
# In Container
docker exec n8n-new n8n --version
# Erwartung: 2.3.4
```
**In Web-UI:**
- Settings → About → Version sollte "2.3.4" zeigen
---
### Phase 4: Rollback (falls nötig)
**Nur wenn kritische Fehler auftreten:**
```bash
# 1. Container stoppen
cd /home/icke/n8n
docker compose down
# 2. Dockerfile zurücksetzen
# In /home/rwiegand/Nextcloud/egonetix/n8n/Dockerfile.n8n-curl:
FROM n8nio/n8n:1.123.5
# 3. Rebuild mit alter Version
docker compose up -d --build
# 4. Falls DB korrupt: Backup einspielen
docker exec -i postgres-n8n psql -U n8n n8n < backup-TIMESTAMP.sql
```
**Wichtig:** Rollback nur bis max. 1 Stunde nach Update - danach könnten neue Workflows/Executions verloren gehen!
---
## Post-Update Maßnahmen
### Dokumentation aktualisieren
**Datei:** `/home/rwiegand/Nextcloud/egonetix/n8n/README.md`
**Abschnitt "Upgrade n8n" aktualisieren:**
```markdown
### Upgrade n8n
Edit `Dockerfile.n8n-curl` and change version:
```dockerfile
FROM n8nio/n8n:2.3.4 # Change version here (aktuell: 2.3.4, Stand: 2026-02-04)
```
Then rebuild:
```bash
docker compose up -d --build
```
**Hinweis:** Breaking Changes zwischen 1.x und 2.x beachten:
- Start Nodes entfernt (verwende manualTrigger stattdessen)
- Python Sandbox sicherer (CVE-2025-68668 gefixt)
- PostgreSQL Schema-Migration läuft automatisch (Backup vorher!)
```
### Infrastructure-Dokumentation
**Datei:** `~/Nextcloud/egonetix/infrastructure/hosts/srvdocker02.md`
**Neuer Abschnitt unter "Docker Containers":**
```markdown
## Wichtige Updates
### n8n Security Update (2026-02-04)
- **Version:** 1.123.5 → 2.3.4
- **Grund:** CVE-2025-68668 (Python Sandbox RCE, CVSS 9.9)
- **Downtime:** ~8 Minuten
- **Migration:** PostgreSQL Schema automatisch migriert
- **Tests:** LangChain/OpenAI Integration erfolgreich getestet
- **Commit:** [commit-hash]
```
### Git Commit
```bash
cd ~/Nextcloud/egonetix/n8n
git add Dockerfile.n8n-curl README.md
git commit -m "Security Update: n8n 1.123.5 → 2.3.4 (CVE-2025-68668)
- Update Dockerfile.n8n-curl auf n8n:2.3.4
- Behebt CVE-2025-68668 (Python Sandbox Bypass, CVSS 9.9)
- PostgreSQL Schema-Migration erfolgreich
- LangChain/OpenAI Workflows getestet und funktional
- Breaking Changes: keine in unserer Konfiguration
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>"
git push origin main
```
---
## Kritische Dateien
| Datei | Änderung |
|-------|----------|
| `Dockerfile.n8n-curl` | Zeile 1: `FROM n8nio/n8n:1.123.5` → `FROM n8nio/n8n:2.3.4` |
| `README.md` | Abschnitt "Upgrade n8n" erweitern mit Breaking Changes Hinweis |
**Keine Änderungen nötig:**
- `docker-compose.yml` (Environment-Variablen bleiben unverändert)
- `scripts/*.sh` (Custom Scripts kompatibel)
- Workflow-Files (keine Start Nodes, kein process.env)
---
## Verification Checklist
Nach Abschluss des Updates:
- [ ] PostgreSQL Backup erstellt und gesichert
- [ ] `docker compose logs` zeigt keine Errors
- [ ] Web-UI unter https://flow.egonetix.de/ erreichbar
- [ ] Login funktioniert
- [ ] Workflows-Liste zeigt alle Workflows
- [ ] 3 LangChain Workflows manuell getestet:
- [ ] `gebuehrenfrei_live` - AI-Extraktion funktioniert
- [ ] `instabank_current` - AI-Extraktion funktioniert
- [ ] `tfbank_current` - AI-Extraktion funktioniert
- [ ] IMAP-Trigger aktiv (bei nächster E-Mail testen)
- [ ] `n8n --version` zeigt 2.3.4
- [ ] README.md aktualisiert
- [ ] `infrastructure/hosts/srvdocker02.md` aktualisiert
- [ ] Git Commit erstellt und gepusht
- [ ] Backup-Files können gelöscht werden (nach 1 Woche Betrieb)
---
## Geschätzte Zeiten
| Phase | Dauer |
|-------|-------|
| Backup | 2-3 Minuten |
| Update (Dockerfile Edit + Rebuild) | 3-5 Minuten |
| Verifikation (Web-UI + Workflows) | 5-10 Minuten |
| Dokumentation | 3-5 Minuten |
| **Gesamt** | **15-25 Minuten** |
**Downtime:** Nur während Container-Restart (~5 Minuten)

View File

@@ -0,0 +1,15 @@
# CRIF #13461 - Untersuchungsergebnis
## Status: Kein Handlungsbedarf
Die Untersuchung hat ergeben, dass der Fix vom 02.02 (Commit `1f2bd4c`) **korrekt funktioniert**:
- Item 99026 hat Intervall `15m;0/1-7,00:00-02:30` (bestätigt via API)
- Letzte Nacht (02.→03.02): Keine Checks zwischen 00:00 und 02:30
- Kein Trigger-Event, keine Alerts seit dem Fix
- User hatte die Daten verwechselt - die Meldungen kamen vom 02.02 01:45 (vor dem Fix)
## Optionale Aktion
- Kanbanize #13461: Bestätigungskommentar posten dass der Fix verifiziert ist
- Karte auf "Erledigt" verschieben (falls gewünscht)

View File

@@ -0,0 +1,62 @@
# Plan: Dokumentation nach VPN-Analyse aktualisieren
## Kontext
Während der Analyse des VPN-Timeouts (flow.wvits.de nicht erreichbar über Client-VPN) wurden folgende Erkenntnisse gewonnen:
- **gw-nu-wan01** hat ein direktes DMZ-VLAN-Interface (igb0.811, IP 10.10.81.14)
- **srv-revproxy01** hat gw-nu-wan01 als Default-Gateway (10.10.81.14), NICHT gw-nu-dmz02
- Admin-VPN (10.250.0.0/24): `pass to any` → funktioniert
- Client-VPN (10.250.1.0/24): Firewall-Regel für 10.10.81.4:443 wurde hinzugefügt (Easy Rule), 10.10.81.4 in OpenVPN "IPv4 Local Networks" ergänzt
- srv-revproxy01 Routing: `10.10.10.0/24` und `10.10.254.0/24` via gw-nu-dmz02 (10.10.81.1), alles andere via gw-nu-wan01
## Zu aktualisierende Dateien
### 1. `infrastructure/hosts/gw-nu-wan01.md`
Aktuell nur Stub mit TODOs. Erweitern um:
- Netzwerk-Interfaces: igb0.811 (10.10.81.14, DMZ VLAN) hinzufügen
- VPN-Server dokumentieren: Admin-VPN (server6, 10.250.0.0/24, Port 1300), Client-VPN (server8, 10.250.1.0/24)
- VPN-Firewall-Regeln: Admin hat `to any`, Client hat spezifische Ziel-Regeln
- Client-VPN Firewall-Regel: `10.250.1.0/24 → 10.10.81.4:443` (Easy Rule, bereits umgesetzt)
- OpenVPN Client-VPN: 10.10.81.4 in "IPv4 Local Networks" ergänzt (bereits umgesetzt)
- Abhängigkeiten aktualisieren: srv-revproxy01 hängt von gw-nu-wan01 ab (Default-GW)
- DNS-Push: 10.10.10.111, 10.10.10.222, domain vinos.local
### 2. `infrastructure/hosts/srv-revproxy01.md`
Ergänzen:
- Routing-Tabelle: Default-GW ist 10.10.81.14 (gw-nu-wan01), nicht gw-nu-dmz02
- Abhängigkeiten: gw-nu-wan01 als Default-Gateway hinzufügen
- Firewall-Abschnitt: WuV_VPN_Admin (10.250.0.0/24) fehlt in der Liste der erlaubten Netze
### 3. `infrastructure/dependencies.md`
n8n-Mermaid-Diagramm aktualisieren:
- gw-nu-wan01 als VPN-Gateway hinzufügen (zwischen VPN-Client und srv-revproxy01)
- VPN-Client-Pfad: VPN → gw-nu-wan01 → DMZ → srv-revproxy01
- Impact-Tabelle: gw-nu-wan01-Ausfall = VPN-Clients erreichen DMZ nicht
- Referenz-Tabelle: gw-nu-wan01 hinzufügen
### 4. `n8n/README.md`
VPN-Voraussetzungen (Zeile 191-198) erweitern:
- 4. Voraussetzung: Firewall auf gw-nu-wan01 erlaubt VPN → DMZ:443 — Status: ✅ Erledigt (Admin: `to any`, Client: Easy Rule 10.250.1.0/24 → 10.10.81.4:443)
- 5. Voraussetzung: 10.10.81.4 in OpenVPN "IPv4 Local Networks" — Status: ✅ Erledigt (beide VPN-Server)
- Abhängigkeiten-Tabelle: gw-nu-wan01 hinzufügen (VPN-Gateway, Default-GW für srv-revproxy01)
## Reihenfolge
1. gw-nu-wan01.md aktualisieren (Kernfund)
2. srv-revproxy01.md aktualisieren (Routing + Abhängigkeit)
3. dependencies.md aktualisieren (Diagramm + Impact)
4. n8n README.md aktualisieren (VPN-Voraussetzungen)
5. Alles committen und pushen (n8n-Repo + infrastructure-Repo)
6. Pflicht-Checkliste durchlaufen (Verifikation, Settings-Sync, Kanbanize)
## Verifikation
- Alle Markdown-Links prüfen (relative Pfade zwischen hosts/)
- Mermaid-Diagramm Knoten gegen Referenz-Tabelle abgleichen
- IPs/Netze konsistent zwischen README, srv-revproxy01.md und dependencies.md
- Zweiter Review-Pass gemäß CLAUDE.md

View File

@@ -0,0 +1,146 @@
# Plan: flow.wvits.de intern erreichbar machen
## Ziel
`flow.wvits.de` soll aus ausgewählten internen Netzen voll erreichbar sein (inkl. Formulare, Signup). Externe Zugriffe bleiben auf Webhooks beschränkt.
| Netz | Subnet | Zugriff |
|------|--------|---------|
| Admin-Netz | 10.10.254.0/24 | Voller Zugriff |
| Bodega Client | 10.20.20.0/24 | Voller Zugriff |
| Admin-VPN | 10.250.0.0/24 | Voller Zugriff |
| WuV VPN | 10.250.1.0/24 | Voller Zugriff |
| gw-web02 | 10.10.81.12 | Voller Zugriff |
| Extern | alles andere | Nur Webhooks |
## Verifizierte Diagnose
### Problem 1: Firewall gw-nu-dmz02 blockiert
**Getestet:**
- srv-docker01 (10.10.10.24) → DMZ: **durchkommt** (EasyRule für diesen einzelnen Host)
- srv-docker02 (10.10.10.81) → DMZ: **TIMEOUT** (kein Firewall-Eintrag für Subnet)
**Aktuelle Firewall-Regeln zu srv-revproxy01 (10.10.81.4):**
| Quelle | Alias | Port | Status |
|--------|-------|------|--------|
| 10.10.254.0/24 | NET_NU_ADMIN | SSH, 80, 81, 443, 8443 | ✅ vorhanden |
| 10.250.1.0/24 | WuV_VPN_Client | 443 | ✅ vorhanden |
| 10.250.0.0/24 | WuV_VPN_Admin | 443 | ✅ vorhanden |
| 10.20.20.0/24 | NET_BD_CLIENT | 443 | ✅ vorhanden |
| 10.10.10.24 | (EasyRule) | alle | ✅ nur einzelner Host |
| 10.10.10.0/24 | — | — | Nicht benötigt |
| 10.10.0.0/24 | LAN__NETWORK | — | Nicht benötigt |
| 10.20.0.0/24 | — | — | Nicht benötigt |
**Existierende Aliases (relevant):**
- `WebGatewayNets`: 10.10.10.0/24, 10.10.12.0/27, 10.10.20.0/24, 10.10.40.0/24, 10.10.254.0/24
- `LAN__NETWORK`: 10.10.0.0/24
- `WebGateways`: 10.10.81.10, 10.10.81.11, 10.10.81.12
### Problem 2: nginx allow/deny blockiert
**Getestet:**
- srv-docker01 (10.10.10.24) → Webhook-Pfad: **funktioniert** (n8n antwortet)
- srv-docker01 (10.10.10.24) → Signup-Pfad: **403 Forbidden**
- nginx-Log bestätigt: `client: 10.10.10.24, access forbidden by rule`
**Aktuelle allow/deny im non-webhook Location-Block:**
```nginx
allow 10.10.81.12; # gw-web02
deny all;
# Auskommentiert: 10.10.254.0/24, 10.20.20.0/24, 10.250.1.0/24
```
---
## Lösung
### Schritt 1: Firewall gw-nu-dmz02 — Regeln hinzufügen (User macht das)
Auf pfsense Web-UI von gw-nu-dmz02: Firewall-Regeln auf **em1 (LAN)** prüfen/ergänzen.
**Benötigte Regeln zu srv_revproxy01 (10.10.81.4) Port 443:**
| Quelle | Alias vorhanden? | Regel vorhanden? | Aktion |
|--------|-------------------|------------------|--------|
| 10.10.254.0/24 | `NET_NU_ADMIN` ✅ | ✅ HTTPS erlaubt | Keine Änderung |
| 10.20.20.0/24 | `NET_BD_CLIENT` ✅ | ✅ HTTPS erlaubt | Keine Änderung |
| 10.250.0.0/24 | `WuV_VPN_Admin` ✅ | ✅ HTTPS erlaubt | Keine Änderung |
| 10.250.1.0/24 | `WuV_VPN_Client` ✅ | ✅ HTTPS erlaubt | Keine Änderung |
Alle benötigten Netze haben bereits Firewall-Regeln. **Keine Firewall-Änderung nötig.**
Die EasyRule für 10.10.10.24 (srv-docker01) bleibt bestehen (wird für NPM → DMZ benötigt).
### Schritt 2: nginx.conf anpassen
**Datei:** `/home/vinosadmin/n8n-reverse-proxy/nginx.conf` auf srv-revproxy01
**Zugang:** `ssh -J sshtest@10.10.254.201 vinosadmin@srv-revproxy01`
**Änderung im Location-Block `location /77ba0b14e9ccd5521a0ec1867332378c/`:**
Ersetze:
```nginx
#allow 10.10.254.0/24; # Admin-Netz
#allow 10.20.20.0/24; # Bodega Client Netz
#allow 10.250.1.0/24; # VPN Client Netz
allow 10.10.81.12; # gw-web02
deny all;
```
Durch:
```nginx
allow 10.10.254.0/24; # Admin-Netz
allow 10.20.20.0/24; # Bodega Client Netz
allow 10.250.0.0/24; # Admin-VPN
allow 10.250.1.0/24; # WuV VPN Client Netz
allow 10.10.81.12; # gw-web02
deny all;
```
Nur Bodega-Clients + Admin/VPN. Keine breiten Netz-Freigaben (10.10.0.0/24, 10.20.0.0/24, 10.10.10.0/24).
**Container neu starten:**
```bash
cd /home/vinosadmin/n8n-reverse-proxy && docker compose restart
```
### Schritt 3: Testen
```bash
# Von srv-docker02 (10.10.10.81) — derzeit geblockt durch Firewall:
ssh vinosadmin@srv-docker02 "curl -sk --connect-timeout 5 -w 'HTTP %{http_code}\n' \
'https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/signup'"
# Erwartet: HTTP 200 oder 302 (statt Timeout)
# Von srv-docker01 (10.10.10.24) — derzeit geblockt durch nginx:
ssh vinosadmin@srv-docker01 "curl -sk --connect-timeout 5 -w 'HTTP %{http_code}\n' \
'https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/signup'"
# Erwartet: HTTP 200 oder 302 (statt 403)
# Webhook weiterhin funktionsfähig:
ssh vinosadmin@srv-docker01 "curl -sk --connect-timeout 5 -w 'HTTP %{http_code}\n' \
'https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/webhook-test/test'"
# Erwartet: HTTP 404 (n8n: webhook nicht aktiv — ok)
```
---
## Betroffene Systeme
| System | Zugang | Änderung |
|--------|--------|----------|
| gw-nu-dmz02 | pfsense Web-UI | Keine Änderung nötig (Regeln existieren bereits) |
| srv-revproxy01 | SSH via cli-rwe02 | nginx.conf: allow-Regeln erweitern |
## Verifiziert (keine Änderung nötig)
| Prüfpunkt | Status |
|-----------|--------|
| DNS Split (flow.wvits.de → 10.10.81.4) | ✅ funktioniert (srv-docker01, srv-docker02) |
| real_ip Modul (nginx sieht echte Client-IP) | ✅ bestätigt in nginx-Logs |
| Webhook-Pfade (allow all) | ✅ funktioniert von srv-docker01 |
| NPM-Routing zu nginx Container | ✅ funktioniert |
| Route vom Servernetz zur DMZ | ✅ Route existiert (via 10.10.10.1 → 10.10.0.81) |

View File

@@ -0,0 +1,74 @@
# Plan: Leverage auf 5x auf srvdocker02 deployen
## Kontext
- **Server:** srvdocker02 (10.0.0.48 / srvdocker02.egonetix.lan)
- **Projekt-Pfad:** `/home/icke/traderv4`
- **Container:** `trading-bot-v4`
- **.env** wird als Volume gemountet (`./.env:/app/.env`), daher reicht ein Container-Restart
## Schritte
### 1. SSH auf srvdocker02, .env sichern
```bash
ssh root@10.0.0.48
cd /home/icke/traderv4
cp .env .env.backup-$(date +%Y%m%d_%H%M%S)
```
### 2. Leverage-Werte in .env aendern
| Variable | Alt | Neu |
|----------|-----|-----|
| `LEVERAGE` | 10 | **5** |
| `BASE_LEVERAGE` | 10 | **5** |
| `STACK_LEVERAGE` | 10 | **5** |
| `MAX_LEVERAGE_TOTAL` | 20 | **10** |
| `HIGH_QUALITY_LEVERAGE` | 10 | **5** |
| `LOW_QUALITY_LEVERAGE` | 10 | **5** |
| `SOLANA_LEVERAGE` | 10 | **5** |
Per `sed` auf dem Server:
```bash
sed -i 's/^LEVERAGE=10$/LEVERAGE=5/' .env
sed -i 's/^BASE_LEVERAGE=10$/BASE_LEVERAGE=5/' .env
sed -i 's/^STACK_LEVERAGE=10$/STACK_LEVERAGE=5/' .env
sed -i 's/^MAX_LEVERAGE_TOTAL=20$/MAX_LEVERAGE_TOTAL=10/' .env
sed -i 's/^HIGH_QUALITY_LEVERAGE=10$/HIGH_QUALITY_LEVERAGE=5/' .env
sed -i 's/^LOW_QUALITY_LEVERAGE=10$/LOW_QUALITY_LEVERAGE=5/' .env
sed -i 's/^SOLANA_LEVERAGE=10$/SOLANA_LEVERAGE=5/' .env
```
### 3. Container neu starten
```bash
docker compose restart trading-bot
```
Kein Rebuild noetig - .env wird als Volume gemountet und beim Start neu gelesen.
### 4. Verifizieren
```bash
# Container laeuft?
docker ps | grep trading-bot-v4
# Leverage-Werte pruefen
grep -E "LEVERAGE" .env
# Logs: Startup-Meldungen mit Leverage?
docker logs --tail=30 trading-bot-v4
# Health-Check
curl -s http://localhost:3001/api/health
```
## Hinweis: Git-Sync separat
Die lokalen Git-Aenderungen (copilot-instructions.md Verschiebung, .gitignore) werden hier NICHT gepullt, da `git rm --cached .env` die Server-.env beim Pull loeschen wuerde. Git-Sync auf dem Server muss separat mit .env-Backup erfolgen.
## Verifikation
- [ ] SSH-Zugang funktioniert
- [ ] .env Backup erstellt
- [ ] Alle 7 Leverage-Werte geaendert
- [ ] Container neugestartet
- [ ] Health-Check OK
- [ ] Logs zeigen korrekten Start

View File

@@ -0,0 +1,173 @@
# Fix: OAuth Callback 403 Forbidden - WEBHOOK_URL und BASE_URL fehlen Prefix
## Aktuelle Situation (Stand 2026-02-05)
**Problem:** OAuth-Callback zu `flow.wvits.de/rest/oauth2-credential/callback` schlägt mit **403 Forbidden** fehl.
**Screenshot zeigt:** Callback-URL hat **KEINEN Prefix** → nginx blockt mit 403.
## Root Cause Analyse
### Gefundene Probleme:
1.**WEBHOOK_URL ohne Prefix** (Hauptursache)
```yaml
# docker-compose.yml auf srv-docker02
# WEBHOOK_URL=https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/ # ← Auskommentiert!
WEBHOOK_URL=https://flow.wvits.de/ # ← Aktiv, OHNE Prefix
```
→ OAuth-Callbacks gehen zu `/rest/oauth2-credential/callback` statt `/PREFIX/rest/oauth2-credential/callback`
2. ✅ **N8N_EDITOR_BASE_URL fehlt**
```yaml
# N8N_EDITOR_BASE_URL=https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/ # ← Auskommentiert
```
→ n8n nutzt Fallback (`N8N_PROTOCOL + N8N_HOST`), aber ohne Prefix
→ UI-Redirects, WebSocket-URLs, Asset-Loading könnten fehlschlagen
3. ⚠️ **nginx blockt alles ohne Prefix**
```nginx
# /home/vinosadmin/n8n-reverse-proxy/nginx.conf auf srv-revproxy01
location / { return 403; } # ← Catch-All blockt
```
→ Nur Requests unter `/77ba0b14e9ccd5521a0ec1867332378c/` werden weitergeleitet
4. **NPM Asset-Cache existiert** (kein direktes Problem, aber Pitfall)
- Cache-Key: `$host$request_uri` (ohne Client-IP)
- Könnte 403-Responses cachen wenn externer Client Assets abruft
- Aktuell: Cache leer, kein Problem
5. **Custom Certificates Mount-Error** (kein Problem für OAuth)
- `/opt/custom-certificates` Access denied
- Betrifft nur HTTPS zu internen Services mit Custom CA
- SMTP ist unverschlüsselt (SSL=false), kein Impact
## Fix-Plan
### Schritt 1: n8n docker-compose.yml korrigieren (srv-docker02)
**SSH:** `ssh vinosadmin@srv-docker02`
**Datei:** `/home/vinosadmin/n8n/docker-compose.yml`
**Änderungen:**
```yaml
# 1. WEBHOOK_URL mit Prefix aktivieren (Zeile ~31)
# WEBHOOK_URL=https://flow.wvits.de/
WEBHOOK_URL=https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/
# 2. N8N_EDITOR_BASE_URL mit Prefix hinzufügen (nach N8N_PROXY_HOPS)
N8N_EDITOR_BASE_URL=https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/
```
**Begründung:**
- `WEBHOOK_URL`: n8n nutzt diese für OAuth-Callback-URLs und Webhook-Generierung
- `N8N_EDITOR_BASE_URL`: n8n nutzt diese für UI-Redirects, WebSocket-URLs, Asset-Pfade
### Schritt 2: Container neu starten
```bash
cd /home/vinosadmin/n8n
docker compose down
docker compose up -d
```
**Warum `down` statt `restart`?**
- Environment-Variablen werden nur beim `up` neu eingelesen
- `restart` behält alte Env-Vars bei
### Schritt 3: Verifikation
**A) Container-Status prüfen:**
```bash
docker compose ps
docker compose logs -f n8n-main | head -20
```
**B) Environment-Variablen verifizieren:**
```bash
docker exec n8n-n8n-main-1 env | grep -E "(WEBHOOK_URL|EDITOR_BASE_URL)"
```
Erwartete Ausgabe:
```
WEBHOOK_URL=https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/
N8N_EDITOR_BASE_URL=https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/
```
**C) OAuth-Flow testen:**
1. n8n UI öffnen: `https://flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/`
2. Credentials → Microsoft Teams account 2 → "Connect my account"
3. Microsoft-Login → Callback sollte zu `/PREFIX/rest/oauth2-credential/callback` gehen
4. Erfolgreich: "Connected" - Credential ist authorisiert
**D) Nginx-Logs prüfen (falls 403):**
```bash
# Auf srv-revproxy01
ssh -J sshtest@10.10.254.201 vinosadmin@srv-revproxy01
docker logs --tail 50 n8n-reverse-proxy-nginx-1 2>&1 | grep oauth
```
### Schritt 4 (Optional): NPM-Cache leeren
Falls nach dem Fix immer noch Probleme auftreten:
```bash
# Auf srv-revproxy01
ssh -J sshtest@10.10.254.201 vinosadmin@srv-revproxy01
docker exec npm sh -c 'rm -rf /var/lib/nginx/cache/public/*'
docker exec npm nginx -s reload
```
## Geänderte Dateien
| Datei | Host | Änderung |
|-------|------|----------|
| `/home/vinosadmin/n8n/docker-compose.yml` | srv-docker02 | WEBHOOK_URL + N8N_EDITOR_BASE_URL mit Prefix |
## Sicherheit & Impact
**Was ändert sich:**
- OAuth-Callbacks gehen nun zu `/PREFIX/rest/oauth2-credential/callback` (mit Prefix)
- nginx leitet alle `/PREFIX/*` Requests weiter (bestehende IP-Kontrolle bleibt)
- Keine Änderungen an Firewall-Regeln oder nginx-Config
**Keine Regression:**
- Bestehende Webhooks (UPS-Workflow) unverändert: `/PREFIX/webhook/*`
- Interner Zugang via n8n.vinos.de weiterhin funktional
- Externe Webhooks weiterhin erlaubt (`allow all` in Webhook-Block)
## Troubleshooting
### Falls OAuth immer noch 403:
**A) Callback-URL prüfen:**
```bash
# Browser DevTools → Network Tab → OAuth-Redirect URL ansehen
# Sollte sein: flow.wvits.de/77ba0b14e9ccd5521a0ec1867332378c/rest/oauth2-credential/callback
# NICHT: flow.wvits.de/rest/oauth2-credential/callback
```
**B) Container-Logs prüfen:**
```bash
docker compose logs n8n-main | grep -i webhook
```
**C) nginx-Logs prüfen:**
```bash
# Auf srv-revproxy01
docker logs --tail 100 n8n-reverse-proxy-nginx-1 2>&1 | grep "403\|oauth"
```
### Falls SPA nicht lädt (weiße Seite):
**NPM-Cache leeren** (gecachte 403-Responses):
```bash
# Auf srv-revproxy01
docker exec npm sh -c 'rm -rf /var/lib/nginx/cache/public/*'
docker exec npm nginx -s reload
```
**Browser-Cache leeren:**
- Ctrl+Shift+R (Hard Reload)
- Oder Incognito-Fenster

View File

@@ -0,0 +1,234 @@
# Plan: VMware-Alarme mit VM-Namen in Zabbix anzeigen
## Problem
Die Operational Data bei VMware-Alarm-Triggern zeigt `alarm-127.group-d1` (interner vSphere-Key) statt des VM-Namens. Man sieht nicht, WELCHE VM ein Problem hat.
## Ursache
- `vmware.alarms.get[url]` sammelt Alarme auf **Datacenter-Ebene** (entity `group-d1` = Root)
- Das Alarm-JSON enthält **kein** Entity-/VM-Name-Feld
- Der Trigger-Prototype hat **leere opdata** → Zabbix zeigt den lastvalue (= den nutzlosen Key)
- Das VMware Guest Template hat **keine Alarm-Discovery** (auch nicht in der neusten Version 7.4-1 auf GitHub)
## Lösung: Per-VM Alarm-Discovery zum VMware Guest Template hinzufügen
`vmware.vm.alarms.get[url, uuid]` existiert als Item-Key in Zabbix 7.0 — wird nur nicht im Template verwendet. Wenn wir Alarm-Discovery auf die VMware Guest Hosts bringen, erscheinen Alarm-Trigger direkt auf dem jeweiligen VM-Host. **Der Host-Name im Dashboard IST der VM-Name** → Problem gelöst.
### Warum das funktioniert
vSphere feuert Alarme auf **zwei Ebenen**:
1. **Datacenter-Level:** Gesamtstatus ("irgendwo gibt es ein Backup-Problem") → aktueller Zustand
2. **Entity-Level (VM/Host):** Alarm auf der spezifischen VM die das Problem hat → was wir brauchen
`vmware.vm.alarms.get` liefert die Entity-Level Alarme pro VM.
## Schritte
### Schritt 0: Template-Backup (PFLICHT, VOR jeder Änderung)
Vollständige Exports beider VMware-Templates via Zabbix API als JSON-Backup. Enthält ALLE Objekte: Items, Triggers, Discovery Rules, Item-/Trigger-Prototypen, Tags, Preprocessing, Macros, Dependencies.
**a) VMware Guest Template (10174) — wird geändert:**
```
configuration.export format=json options.templates=[10174]
→ ~/Nextcloud/vinos/zabbix/backups/vmware-guest-template-10174-backup.json
```
**b) VMware Template (10173) — opdata-Änderung:**
```
configuration.export format=json options.templates=[10173]
→ ~/Nextcloud/vinos/zabbix/backups/vmware-template-10173-backup.json
```
**c) Verifizierung der Backups:**
- Dateigröße prüfen (sollte mehrere KB sein)
- JSON-Validität prüfen (`python3 -m json.tool`)
- Stichprobe: Tags im Backup vorhanden? (grep nach "tags")
- Stichprobe: Trigger-Prototypen im Backup? (grep nach "trigger_prototypes")
**Restore bei Problemen:**
```
configuration.import format=json source=[Dateiinhalt] rules.templates.updateExisting=true
```
**Backups werden ins Git committed** (`zabbix/backups/`) damit sie versioniert und jederzeit wiederherstellbar sind.
### Schritt 1: Quick-Fix — opdata auf bestehendem Trigger-Prototype verbessern
**Template-Ebene** (VMware Template ID 10173):
- Trigger-Prototype ID `54450``opdata` setzen auf `{#VMWARE.ALARMS.STATUS}`
- Zeigt dann "red"/"yellow" statt "alarm-127.group-d1"
- Betrifft alle 5 entdeckten Alarme auf srv-nu-vcenter01
**API-Call:**
```
triggerprototype.update: triggerid=54450, opdata="{#VMWARE.ALARMS.STATUS}"
```
### Schritt 2: Validierung — Per-VM Alarme testen
**Bevor wir das Template ändern**, prüfen ob `vmware.vm.alarms.get` pro VM funktioniert:
1. Temporäres Test-Item auf einer VM erstellen (z.B. SRV-DATA01, Host-ID 10893):
- Key: `vmware.vm.alarms.get[{$VMWARE.URL},{$VMWARE.VM.UUID}]`
- Type: Simple Check
- Value Type: Text
- History: 1h
2. Warten bis Daten kommen (1-2 Min)
3. Prüfen ob der Backup-Alarm in den per-VM Daten auftaucht
4. Test-Item wieder löschen
**Mögliche Ergebnisse:**
- JSON enthält den Alarm → weiter mit Schritt 3
- JSON ist leer → Backup-Alarm feuert nur auf Datacenter-Ebene, Schritt 3 bringt für diesen speziellen Alarm nichts
### Schritt 3: Neues Template "VMware Guest Alarms" erstellen (PARALLEL, nicht am Original)
**Strategie:** Statt das Original-Template (10174) zu modifizieren, erstellen wir ein **separates Template** mit nur der Alarm-Discovery. Dieses wird zusätzlich zu "VMware Guest" auf die VM-Hosts gelinkt.
**Vorteile:**
- Original "VMware Guest" bleibt 100% unverändert
- Bei Problemen: Template unlinken → alle Alarm-Items sofort weg
- Nachbesserungen am neuen Template ohne Risiko
- Bei Zabbix-Update wird das Original-Template aktualisiert, unser Custom-Template bleibt
**Template-Name:** `VMware Guest Alarms`
**Host Group:** Gleiche wie VMware Guest (wird beim Linken automatisch zugewiesen)
**a) Template erstellen:**
```
template.create:
host: "VMware Guest Alarms"
name: "VMware Guest Alarms"
description: "Per-VM Alarm-Discovery für VMware Guest Hosts.
Ergänzt das Standard VMware Guest Template um Alarm-Monitoring.
Benötigt Macros {$VMWARE.URL} und {$VMWARE.VM.UUID} vom VMware Guest Template."
groups: [{groupid: <Templates-Gruppe>}]
```
**b) Master-Item (Simple Check):**
```
item.create:
hostid: [neues Template]
name: "Get VM alarms"
key: vmware.vm.alarms.get[{$VMWARE.URL},{$VMWARE.VM.UUID}]
type: Simple Check (3)
value_type: Text (4)
history: 0
delay: 0 (VMware Collector)
```
**c) Discovery Rule (Dependent):**
```
discoveryrule.create:
hostid: [neues Template]
name: "VMware VM alarm discovery"
key: vmware.vm.alarms.discovery
type: Dependent (18)
master_itemid: [Get VM alarms Item]
lifetime: 0
LLD Macro Paths:
{#VMWARE.ALARMS.DESC} → $.description
{#VMWARE.ALARMS.KEY} → $.key
{#VMWARE.ALARMS.NAME} → $.name
{#VMWARE.ALARMS.STATUS} → $.overall_status
```
**d) Item-Prototype (Dependent):**
```
itemprototype.create:
ruleid: [Discovery Rule]
hostid: [neues Template]
name: "{#VMWARE.ALARMS.NAME}"
key: vmware.vm.alarms.status["{#VMWARE.ALARMS.KEY}"]
type: Dependent (18)
master_itemid: [Get VM alarms Item]
value_type: Character (1)
preprocessing:
1. JSONPath: $.[?(@.key == "{#VMWARE.ALARMS.KEY}")].key.first()
error_handler: set value to -1
2. Throttling: 1h
```
**e) Trigger-Prototype:**
```
triggerprototype.create:
description: "VMware VM: {#VMWARE.ALARMS.NAME}" ← "VM:" um von vCenter-Level zu unterscheiden
expression: last(/VMware Guest Alarms/vmware.vm.alarms.status["{#VMWARE.ALARMS.KEY}"])<>-1
opdata: "{#VMWARE.ALARMS.STATUS}"
priority: 0 (Not classified) ← gleich wie vCenter-Level Trigger
comments: "{#VMWARE.ALARMS.DESC}"
tags: [{"tag": "scope", "value": "notice"}]
```
**Tag-Kontext:** Das Notification-System basiert auf Tags wie `Meldung_Webhook_*` / `Meldung_Mail_*` (siehe notifications.md). Der `scope=notice` Tag kommt vom Template. Spezifische Routing-Tags (`Meldung_*`) werden bei Bedarf nachträglich auf entdeckte Trigger gesetzt — nicht auf dem Prototype.
### Schritt 3b: Template auf VMware Guest Hosts linken
**Erst auf einem Test-Host:**
1. Template "VMware Guest Alarms" auf SRV-DATA01 (10893) linken
2. Warten bis Master-Item Daten liefert (~1-2 Min)
3. LLD abwarten (~5-10 Min)
4. Prüfen ob Alarm-Items erstellt werden
**Bei Erfolg auf alle VMware Guest Hosts:**
- `host.get` mit `templateids=[10174]` → Liste aller VMware Guest Hosts
- `host.massupdate` mit templates: bestehende + neues Template
### Schritt 4: Verifizierung
1. Warten bis LLD auf VMware Guest Hosts läuft (~5-10 Min)
2. Prüfen ob per-VM Alarm-Items erstellt werden
3. Prüfen ob der Backup-Alarm auf der betroffenen VM auftaucht
4. Dashboard-Anzeige prüfen: VM-Name sollte in Host-Spalte stehen
### Schritt 5: Aufräumen
- History am Master-Item `vmware.alarms.get` auf vCenter (120476) zurück auf `0` setzen
- Ggf. den Datacenter-Level Alarm-Trigger deaktivieren oder behalten (als Fallback)
### Schritt 6: Dokumentation + Commits
- `zabbix/README.md`: VMware Alarm-Monitoring Pattern dokumentieren
- `zabbix/copilot-instructions.md`: Pitfall dokumentieren (opdata leer = zeigt lastvalue)
- Infrastructure: Falls relevant
- Commits in zabbix-Repo + pushen
## Risiken & Fallbacks
| Risiko | Auswirkung | Fallback |
|--------|-----------|----------|
| `vmware.vm.alarms.get` liefert keine per-VM Alarme | Backup-Alarm nur auf Datacenter-Ebene | opdata-Fix (Schritt 1) ist trotzdem besser als Status quo |
| Viele neue Items pro VM | Mehr Last auf Zabbix-Server | Items haben 1h Throttling, Master-Item hat `delay=0` (VMware Collector Intervall) |
| Neues Template funktioniert nicht wie erwartet | Falsches/kein Discovery | **Template unlinken** → alle Items/Trigger sofort weg, kein Restrisiko |
## Rollback-Strategie
1. **Per-VM Alarms funktionieren nicht:** Template "VMware Guest Alarms" von Hosts unlinken → fertig
2. **opdata-Änderung problematisch:** `triggerprototype.update` opdata zurück auf "" → LLD re-run
3. **Komplett-Rollback:** Template-Backup importieren via `configuration.import`
## Betroffene Dateien/Objekte
| Was | ID | Aktion |
|-----|-----|--------|
| VMware Template Trigger-Prototype | 54450 | opdata setzen |
| **NEUES** Template "VMware Guest Alarms" | (wird erstellt) | Alarm-Discovery für VMs |
| VMware Guest Template | 10174 | **NICHT geändert** (nur Backup) |
| Master-Item vCenter (temporär) | 120476 | History zurück auf 0 |
| `zabbix/README.md` | — | Doku ergänzen |
## Verifizierung
```bash
# Nach Schritt 2: Test-Item prüfen
item.get hostids=[10893] search={"key_": "vm.alarms"}
history.get itemids=[TEST_ITEM_ID] history=4
# Nach Schritt 3: Per-VM Alarm Discovery prüfen
item.get templateids=[10174] search={"key_": "alarm"}
# Auf einem VMware Guest Host:
item.get hostids=[10893] search={"key_": "alarm"}
trigger.get hostids=[10893] search={"description": "Backup"}
```

View File

@@ -0,0 +1,23 @@
# Plan: Zertifikat-Doku korrigieren + Evaluierung notieren
## Korrektur
Das Zertifikat CN=zabbix_mailboxueberwachung ist **self-signed vom Exchange** (nicht von AD CA SRV-VINOSCA01). Erneuerung erfolgte per Klick in der Exchange Admin Console.
### Zu korrigierende Stellen
1. **`README.md`** (Zeile 245): `CA: SRV-VINOSCA01.vinos.local``Self-signed (Exchange-lokal)`
2. **`troubleshooting.md`** (Zeile 154): CA-Zeile in Tabelle korrigieren
3. **`troubleshooting.md`** (Zeile 166-177): AD-CA-Erneuerungsschritte durch Exchange-Konsole-Erneuerung ersetzen
4. **`troubleshooting.md`**: Evaluierungshinweis ergänzen — Zertifikat ggf. überflüssig da `smtp_verify_peer=0`
### Neue Troubleshooting-Anleitung (ersetzt AD-CA-Schritte)
Erneuerung per Exchange Admin Console:
1. EAC öffnen → Server → Zertifikate
2. Zertifikat `zabbix_mailboxueberwachung` auswählen → Erneuern
3. Verifizieren per `openssl s_client`
### Evaluierungshinweis
> **TODO:** Evaluieren ob das Zertifikat überhaupt benötigt wird. Zabbix verbindet mit `smtp_verify_peer=0` / `smtp_verify_host=0` — das Zertifikat bietet nur opportunistic TLS (Transport-Verschlüsselung) im internen Netz. Alternativen: Plaintext SMTP oder Zertifikatsvalidierung aktivieren.

View File

@@ -0,0 +1,152 @@
# Plan: n8n Workflow — UPS-Rechnungen abholen und weiterleiten
## Ziel
Täglicher n8n-Workflow, der UPS-Rechnungsmails aus dem Postfach `vinos-monitoring@mailbox.org` per IMAP abruft, das ZIP-Attachment entpackt und die enthaltenen Rechnungen per SMTP an `rechnung@vinos.de` weiterleitet.
---
## Parameter
| Parameter | Wert |
|-----------|------|
| Postfach | `vinos-monitoring@mailbox.org` |
| Empfänger | `rechnung@vinos.de` |
| Absender-Filter | `@ups.com` |
| Intervall | Täglich (07:00) |
| Nach Verarbeitung | Mail in Ordner "Verarbeitet" verschieben |
| IMAP-Server | `imap.mailbox.org:993` (SSL/TLS) |
| SMTP-Server | `smtp.mailbox.org:465` (SSL/TLS) |
---
## Voraussetzungen (manuell, vor Workflow-Erstellung)
### 1. n8n Credentials anlegen (Web-UI)
In n8n unter **Settings → Credentials → Add Credential**:
**IMAP-Credential:**
- Typ: **IMAP**
- Host: `imap.mailbox.org`
- Port: `993`
- User: `vinos-monitoring@mailbox.org`
- Passwort: Mailbox.org-Passwort
- SSL/TLS: Ja
**SMTP-Credential:**
- Typ: **SMTP**
- Host: `smtp.mailbox.org`
- Port: `465`
- User: `vinos-monitoring@mailbox.org`
- Passwort: Mailbox.org-Passwort
- SSL/TLS: Ja
### 2. Ordner "Verarbeitet" im Postfach anlegen
Per Webmail auf mailbox.org oder per IMAP-Client einen Ordner `Verarbeitet` erstellen.
---
## Workflow-Aufbau (6 Nodes)
```
Schedule Trigger → Email Read (IMAP) → IF (hat ZIP-Attachment?)
→ Compression (Decompress) → Send Email (SMTP)
→ IMAP Move to Folder
```
### Node 1: Schedule Trigger
- **Typ:** `n8n-nodes-base.scheduleTrigger`
- **Konfiguration:** Täglich um 07:00 Uhr (`0 7 * * *`)
### Node 2: Email Read (IMAP)
- **Typ:** `n8n-nodes-base.emailReadImap`
- **Postfach:** `vinos-monitoring@mailbox.org`
- **Ordner:** INBOX
- **Filter:** Ungelesene Mails
- **Attachments:** Herunterladen aktiviert
- **Credential:** IMAP (mailbox.org)
### Node 3: IF — Hat ZIP-Attachment?
- **Typ:** `n8n-nodes-base.if`
- **Bedingung:** Binary-Daten vorhanden UND Dateiname endet auf `.zip`
- **Zweck:** Nur Mails mit ZIP-Anhang verarbeiten
### Node 4: Compression — ZIP entpacken
- **Typ:** `n8n-nodes-base.compression`
- **Operation:** Decompress
- **Input:** Binary-Feld des ZIP-Attachments
- **Output:** Entpackte Dateien als Binary-Daten
### Node 5: Send Email (SMTP)
- **Typ:** `n8n-nodes-base.sendEmail` (oder `n8n-nodes-base.emailSend`)
- **Von:** `vinos-monitoring@mailbox.org`
- **An:** `rechnung@vinos.de`
- **Betreff:** `UPS-Rechnung` + Datum aus Original-Mail
- **Body:** Kurzer Hinweistext (z.B. "Anbei die entpackte UPS-Rechnung")
- **Attachments:** Entpackte Dateien aus Node 4
- **Credential:** SMTP (mailbox.org)
### Node 6: IMAP — Mail verschieben
- **Typ:** `n8n-nodes-base.emailReadImap` (oder HTTP-Request an IMAP)
- **Operation:** Mail als gelesen markieren + in Ordner "Verarbeitet" verschieben
- **Hinweis:** n8n hat keine native "IMAP Move"-Operation — ggf. per Code-Node (IMAP-Befehl MOVE) oder als "gelesen markieren" vereinfachen
---
## Bekannte Einschränkung: IMAP Move
n8n's IMAP-Node kann Mails lesen, aber das Verschieben in einen anderen Ordner ist nicht nativ unterstützt. Optionen:
1. **Nur als gelesen markieren** — einfachste Lösung, Node 2 liest dann nur ungelesene
2. **Code-Node mit IMAP-Bibliothek** — per JavaScript direkt IMAP MOVE ausführen
3. **HTTP-Request an Mailbox.org API** — falls vorhanden
**Empfehlung:** Option 1 (als gelesen markieren) für den Start. "Nur ungelesene lesen" verhindert Doppelverarbeitung zuverlässig.
---
## Umsetzung
### Schritt 1: Workflow-Grundgerüst via API erstellen
- POST an `https://flow.wvits.de/api/v1/workflows`
- 5-6 Nodes (je nach IMAP-Move-Lösung)
- Credentials als Platzhalter (in UI verknüpfen)
### Schritt 2: Credentials in n8n-UI verknüpfen
- IMAP-Credential den Email-Read-Nodes zuweisen
- SMTP-Credential dem Send-Email-Node zuweisen
### Schritt 3: Testlauf
- Test-Mail mit ZIP-Anhang an `vinos-monitoring@mailbox.org` senden
- Workflow manuell in der UI ausführen
- Prüfen: ZIP entpackt? Mail bei `rechnung@vinos.de` angekommen?
### Schritt 4: Workflow aktivieren
- `POST /api/v1/workflows/{id}/activate`
---
## Verifikation
1. **API-Test:** `GET /api/v1/workflows/{id}` — Node-Struktur prüfen
2. **Manueller Testlauf:** In n8n-UI "Execute Workflow"
3. **Prüfpunkte:**
- [ ] IMAP-Verbindung zu mailbox.org funktioniert
- [ ] Ungelesene Mails werden abgerufen
- [ ] ZIP-Attachment wird erkannt und gefiltert
- [ ] ZIP wird entpackt, Dateien korrekt
- [ ] SMTP-Versand an rechnung@vinos.de funktioniert
- [ ] Entpackte Dateien sind als Attachment in der Mail
- [ ] Verarbeitete Mail wird als gelesen markiert
4. **Fehlerfall:** Mail ohne ZIP → IF-Node filtert korrekt
---
## Dateien
| Datei | Zweck |
|-------|-------|
| `/home/rwiegand/Nextcloud/vinos/n8n/.env` | API-Key + Base-URL (vorhanden) |
| `/home/rwiegand/Nextcloud/vinos/n8n/README.md` | Projekt-Doku (Update nach Abschluss) |

View File

@@ -0,0 +1,444 @@
# Plan: Vinos/clawd — Governance & Skills Repository
## Ziel
Vinos-spezifisches Governance-Repository anlegen mit Skills, Standards und Workflows — analog zu Egonetix/clawd, aber angepasst für Vinos-Infrastruktur.
**Kontext:** Heute kam ein Fall (BCC-Mail-Routing bei Egonetix) wo Monitoring vergessen wurde → Ausfall 8,5h unbemerkt. Für Vinos existiert nur eine generische CLAUDE.md Anweisung (29.01., Zeile 638-667), die leicht übersehen wird. Egonetix hat ein vollständiges Governance-System aufgebaut (`Egonetix/clawd.git`) mit Skills, Quality Gates und erzwungenen Workflows.
**Entscheidung:** Trennung pro Kunde mit gemeinsamer Grundstruktur — Vinos bekommt eigenes clawd-Repo, basierend auf Egonetix-Vorlage, aber angepasst.
---
## Bestehende Vinos-Infrastruktur (Basis)
### Gitea-Organisation "Vinos"
| Repo | Status | Beschreibung |
|------|--------|--------------|
| `Vinos/infrastructure.git` | ✅ Existiert | Landkarte, hosts/, dependencies.md, Mermaid-Diagramme |
| `Vinos/zabbix.git` | ✅ Existiert | Zabbix-Server-Doku, API, Troubleshooting |
| `Vinos/n8n.git` | ✅ Existiert | Workflow-Automation, komplexe Netzwerk-Architektur |
| `Vinos/srv-job01.git` | ❌ Lokal | Windows Task-Server (sollte gepusht werden) |
| `Vinos/clawd.git` | ❌ NEU | Governance, Skills, Standards (dieses Repo) |
### Dokumentierte Hosts (8 Stück)
- srv-docker01 (10.10.10.24) - Docker + NPM intern
- srv-docker02 (10.10.10.81) - Docker + n8n
- srv-revproxy01 (10.10.81.4) - Reverse Proxy DMZ
- gw-nu-dmz02 (10.10.81.1 / 10.10.0.81) - DMZ Segment-Router
- cli-rwe02 (10.10.254.201) - SSH-Sprungserver
- srv-job01 (10.10.10.42) - Windows Task-Server
- srv-monitor02 - Zabbix Monitoring
- gw-nu-wan01 - WAN/VPN Gateway
### Vinos-Netze
**Wichtig:** Vinos hat NICHT 172.20.20.0/24 (User-Korrektur), sondern mehrere verschiedene Netze:
- 10.10.10.0/24 - LAN
- 10.10.81.0/24 - DMZ
- 10.10.254.0/24 - Management
- Weitere Netze noch zu dokumentieren
→ In der ersten Version KEINE Netzwerk-Spezifikation im Skill (kann später ergänzt werden)
### Bestehendes Monitoring-Beispiel (exzellent!)
`~/Nextcloud/vinos/srv-job01/C_Tasks/dhl_premiumadress/`:
- **MONITORING.md** (237 Zeilen) - WAS überwachen, Items, Trigger, Schwellwerte
- **ZABBIX_IMPLEMENTATION_GUIDE.md** (415 Zeilen) - WIE implementieren in Zabbix
**Das ist bereits die perfekte Arbeitsteilung!** Zeigt dass das Konzept schon angewendet wurde, aber nicht als globaler Standard erzwungen ist.
---
## Ziel-Struktur: Vinos/clawd
```
~/Nextcloud/vinos/clawd/
├── README.md # Einstieg, Übersicht
├── skills/
│ ├── monitoring/
│ │ └── SKILL.md # Monitoring-Requirements (Basis: Egonetix)
│ ├── infra/ # (später)
│ ├── mail/ # (später)
│ └── assistant/ # (später)
├── team/
│ ├── STANDARDS.md # Vinos-spezifische Arbeitsstandards
│ ├── WORKFLOW-POLICY.md # Change-Management-Workflow
│ └── post-mortems/ # (leer, für künftige Incidents)
├── reports/
│ └── monitoring-gap-vinos.md # Gap-Analyse für Vinos (optional, später)
├── scripts/ # (später, ggf. Monitoring-Helper)
└── references/
└── dhl-monitoring-example.md # Verweis auf srv-job01/dhl als Referenz
```
**Gitea Remote:** `ssh://git@gitea.egonetix.de:222/Vinos/clawd.git`
---
## Was übernehmen? Was anpassen?
### Übernehmen von Egonetix/clawd:
| Datei | Was übernehmen |
|-------|----------------|
| `skills/monitoring/SKILL.md` | Grundstruktur, Workflow (4 Schritte), Check-Typen, Schwellwerte, Szenarien-Template |
| `team/STANDARDS.md` | Change-Management-Workflow (7 Schritte), Pre-/During-/Post-Change-Pflichten, Monitoring-Pflicht |
| `team/WORKFLOW-POLICY.md` | Delegation-Regeln, Sub-Agent-Accountability |
### Anpassen für Vinos:
| Aspekt | Egonetix | Vinos (angepasst) |
|--------|----------|-------------------|
| **Netzwerk** | 10.0.0.0/24 explizit genannt | WEGLASSEN (mehrere Netze, noch nicht vollständig dokumentiert) |
| **Zabbix-URL** | http://10.0.0.48:8092 | https://zabbix.vinos.de (gleiche Instanz, anderer Zugang) |
| **Task-Tracking** | Gitea Cards | Kanbanize (weinvinosgmbh.kanbanize.com) |
| **Beispiele** | BCC-Mail-Routing (srv-docker02, srv-mail01) | DHL-Monitoring (srv-job01) + generische Szenarien |
| **Ansprechpartner** | Harry | [Vinos-spezifisch, noch zu klären] |
| **Host-Namen** | srvdocker02, srvrevproxy02 | srv-docker02, srv-revproxy01 |
| **Gültigkeit** | egonetix + vinos | Nur Vinos |
---
## Implementierungsplan
### Phase 1: Repo-Setup
**1.1 Lokales Repo erstellen**
```bash
cd ~/Nextcloud/vinos
mkdir clawd
cd clawd
git init
git branch -M main
```
**1.2 Basis-Struktur anlegen**
```bash
mkdir -p skills/monitoring
mkdir -p team/post-mortems
mkdir -p reports
mkdir -p scripts
mkdir -p references
```
**1.3 README.md erstellen**
```markdown
# Vinos — Governance & Skills
Zentrale Dokumentation für Arbeitsstandards, Skills und Workflows für Kunde **Vinos**.
## Struktur
| Verzeichnis | Inhalt |
|-------------|--------|
| `skills/` | Wiederverwendbare Skills (monitoring, infra, mail, etc.) |
| `team/` | Arbeitsstandards, Workflows, Post-Mortems |
| `reports/` | Gap-Analysen, Reviews |
| `references/` | Referenz-Beispiele aus der Praxis |
## Skills
- [monitoring](skills/monitoring/SKILL.md) — Monitoring-Anforderungen definieren (PFLICHT)
## Standards
- [STANDARDS.md](team/STANDARDS.md) — Verbindliche Arbeitsregeln
- [WORKFLOW-POLICY.md](team/WORKFLOW-POLICY.md) — Change-Management-Workflow
## Quick Links
- [Vinos Infrastructure](../infrastructure/) — Host-Übersichten, Abhängigkeiten
- [Zabbix](../zabbix/) — Monitoring-Server-Dokumentation
- [Gitea Organisation](https://gitea.egonetix.de/Vinos)
```
**1.4 Gitea-Repo erstellen**
```bash
curl -X POST -H "Authorization: token $(cat ~/.config/gitea/token)" \
-H "Content-Type: application/json" \
-d '{
"name":"clawd",
"description":"Governance, Skills und Arbeitsstandards für Vinos",
"private":false,
"auto_init":false
}' \
"https://gitea.egonetix.de/api/v1/orgs/Vinos/repos"
```
**1.5 Remote hinzufügen und pushen**
```bash
cd ~/Nextcloud/vinos/clawd
git remote add origin ssh://git@gitea.egonetix.de:222/Vinos/clawd.git
git add README.md
git commit -m "Initial commit: Vinos/clawd Repo-Struktur"
git push -u origin main
```
---
### Phase 2: Monitoring-Skill erstellen
**2.1 Egonetix-Skill als Basis kopieren**
```bash
cp /tmp/clawd/skills/monitoring/SKILL.md ~/Nextcloud/vinos/clawd/skills/monitoring/SKILL.md
```
**2.2 Anpassungen vornehmen**
| Zeile | Was ändern | Von (Egonetix) | Zu (Vinos) |
|-------|------------|----------------|------------|
| 2-3 | Description | "...new systems AND changes..." | Gleich lassen (gilt auch für Vinos) |
| 8-9 | Hintergrund | Mail-Ausfall 2026-02-01 | Gleich lassen (zeigt Ursprung) + Hinweis "Gilt für Vinos seit 2026-02-02" |
| 386-392 | Gültigkeit | "egonetix + Remote ST / vinos" | **Neu:** Nur Vinos, Netzwerk-Info weglassen |
| 136 | Bezug | "Kanban-Card, Task-Beschreibung" | **Kanbanize-Card** explizit erwähnen |
| 159 | Alerting | "Telegram/Email" | Gleich lassen (Kanäle noch zu klären) |
| 203-230, 232-260, 262-294, 296-334, 336-366 | Szenarien 1-5 | Egonetix-Host-Namen | Generisch halten ODER Vinos-Host-Namen (srv-docker02 statt srvdocker02) |
| 370-380 | Bekannte Lücken | Egonetix Gap-Analyse | **Neu:** Verweis auf Vinos-spezifische Lücken (optional, später Gap-Analyse) |
| 396-402 | Referenzen | Egonetix-Reports | **Neu:** Verweis auf DHL-Monitoring-Beispiel |
**2.3 Neue Gültigkeit-Sektion (Zeile 386-392 ersetzen)**
```markdown
## Gültigkeit
Dieser Skill gilt für die **Vinos-Infrastruktur**.
**Zabbix-Instanz:** https://zabbix.vinos.de (gleiche Instanz wie Egonetix)
**Netze:** Vinos nutzt mehrere Netze (10.10.10.0/24 LAN, 10.10.81.0/24 DMZ, 10.10.254.0/24 Management, weitere). Details siehe [infrastructure/netzwerk/](../../infrastructure/netzwerk/).
**Task-Tracking:** Kanbanize (weinvinosgmbh.kanbanize.com) — technische Doku in Gitea, Aufgaben-Management in Kanbanize.
```
**2.4 Neue Referenzen-Sektion (Zeile 396-402 ersetzen)**
```markdown
## Referenzen
- `../references/dhl-monitoring-example.md` — Verweis auf DHL-Monitoring (srv-job01) als Vinos-spezifisches Beispiel
- `skills/infra/SKILL.md` — Infrastruktur-Management (TODO)
- `skills/mail/SKILL.md` — Mail-Infrastruktur (TODO)
- `team/STANDARDS.md` — Verbindliche Arbeitsstandards, Abschnitt 9
```
**2.5 Referenz-Beispiel erstellen**
`references/dhl-monitoring-example.md`:
```markdown
# DHL-Monitoring — Referenz-Beispiel
Dieses Beispiel zeigt die perfekte Arbeitsteilung zwischen System-Agent und Zabbix-Spezialist.
## Was ist das?
DHL Premium Address ist ein automatisierter File-Transfer auf srv-job01 (Windows Task-Server). Die Monitoring-Dokumentation ist ein exzellentes Beispiel für:
- WAS überwachen (System-Agent-Perspektive)
- WIE implementieren (Zabbix-Spezialist-Perspektive)
## Dokumente
| Datei | Zweck | Zeilen |
|-------|-------|--------|
| [MONITORING.md](../../srv-job01/C_Tasks/dhl_premiumadress/MONITORING.md) | **WAS**: Items, Trigger, Schwellwerte, Dashboard-Widgets | 237 |
| [ZABBIX_IMPLEMENTATION_GUIDE.md](../../srv-job01/C_Tasks/dhl_premiumadress/ZABBIX_IMPLEMENTATION_GUIDE.md) | **WIE**: Schritt-für-Schritt Zabbix-Konfiguration | 415 |
## Warum ist das ein gutes Beispiel?
**Klare Arbeitsteilung:**
- System-Agent: Definiert WAS überwacht werden soll (Check-Typen, Schwellwerte, Alert-Bedingungen)
- Zabbix-Spezialist: Implementiert WIE es in Zabbix umgesetzt wird (Items, Trigger, API-Calls)
**Konkrete Schwellwerte:**
- Warning: >50 Mails in Queue
- Critical: >200 Mails in Queue
- Zeitfenster: Alerts nur nach 08:00 (nach Scheduled Tasks)
**Vollständiger Kontext:**
- Scheduled Tasks erklärt
- Log-Locations dokumentiert
- Troubleshooting-Szenarien vorbereitet
**Quality Gate:**
- Trigger mit Tags (`Meldung_Webhook_IFS-Meldungen`)
- Recovery-Expressions definiert
- Manual Close erlaubt
## Nutzen als Template
Wenn du ein neues System/Service implementierst, nutze diese Dokumente als Template:
1. Kopiere die Struktur von MONITORING.md
2. Passe die Items/Trigger an dein System an
3. Erstelle ein ZABBIX_IMPLEMENTATION_GUIDE.md für den Zabbix-Spezialisten
**Das erfüllt exakt den Monitoring-Skill-Workflow!**
```
---
### Phase 3: Team-Standards erstellen
**3.1 Egonetix STANDARDS.md als Basis kopieren**
```bash
cp /tmp/clawd/team/STANDARDS.md ~/Nextcloud/vinos/clawd/team/STANDARDS.md
```
**3.2 Anpassungen vornehmen**
| Abschnitt | Was ändern |
|-----------|------------|
| Header (Zeile 1-5) | Datum auf 2026-02-02, Genehmigung durch [Vinos-Ansprechpartner] |
| 1.1 Dokumentation lesen (Zeile 18-22) | Pfad anpassen: `/root/Nextcloud/egonetix/``~/Nextcloud/vinos/` |
| 1.4 Genehmigung (Zeile 34-36) | Ansprechpartner anpassen (statt "Harry" → Vinos-spezifisch) |
| 3.3 Monitoring-Pflicht (Zeile 62-69) | Gleich lassen, Verweis auf Abschnitt 9 bleibt |
| 9 Monitoring-Pflicht (Zeile 162-203) | Verweis auf `skills/monitoring/SKILL.md` bleibt, Beispiel-Paths anpassen |
**3.3 Neue Header-Sektion**
```markdown
# Team-Standards — Verbindliche Arbeitsregeln
**Gültig ab:** 2026-02-02
**Anlass:** Monitoring-Gap (Egonetix Mail-Incident 2026-02-01) → auch für Vinos relevant
**Genehmigt durch:** [Vinos-Ansprechpartner, TODO]
```
**3.4 WORKFLOW-POLICY.md erstellen**
Übernehmen von Egonetix, minimale Anpassungen:
- Pfade: `/root/Nextcloud/egonetix/``~/Nextcloud/vinos/`
- Ansprechpartner: "Harry" → Vinos-spezifisch
---
### Phase 4: Weitere Dateien (optional, später)
**Nicht in dieser Phase:**
- reports/monitoring-gap-vinos.md — kann später erstellt werden (analog zu Egonetix Gap-Analyse)
- scripts/ — Monitoring-Helper-Scripts, Token-Watchdog (bei Bedarf)
- skills/infra/, skills/mail/ — weitere Skills nach Bedarf
**Fokus:** Nur Monitoring-Skill + Standards in dieser ersten Version.
---
### Phase 5: Integration in CLAUDE.md
**5.1 CLAUDE.md erweitern (globale Anweisung)**
Nach Zeile 667 (Ende von "PFLICHT: Monitoring-Abgleich") einfügen:
```markdown
**Für Vinos-Projekte gilt zusätzlich:**
Der vollständige Monitoring-Workflow ist im **Monitoring-Skill** definiert:
- `~/Nextcloud/vinos/clawd/skills/monitoring/SKILL.md`
Dieser Skill MUSS bei jeder Infrastruktur-Arbeit aufgerufen werden (analog zu verification-before-completion). Details siehe Skill-Dokumentation.
```
**5.2 Session-Start Hook anpassen (optional)**
Falls Hook existiert: Bei `~/Nextcloud/vinos/` auch `clawd/` Skills laden.
---
### Phase 6: Erste Commits
**6.1 Alle Dateien committen**
```bash
cd ~/Nextcloud/vinos/clawd
git add -A
git commit -m "Add: Monitoring-Skill, Team-Standards, DHL-Referenz
- skills/monitoring/SKILL.md: Basierend auf Egonetix, angepasst für Vinos
- team/STANDARDS.md: Arbeitsstandards mit Change-Management-Workflow
- team/WORKFLOW-POLICY.md: Delegation und Accountability
- references/dhl-monitoring-example.md: srv-job01 DHL als Vorbild
Basis: Egonetix/clawd (Commit 9c1cac8)
"
```
**6.2 Pushen**
```bash
git push origin main
```
**6.3 CLAUDE.md committen und pushen**
```bash
cd ~/dotfiles/claude_settings
git add CLAUDE.md
git commit -m "Add: Verweis auf Vinos/clawd Monitoring-Skill"
git push origin main
```
---
## Verifikation
Nach Abschluss prüfen:
- [ ] `Vinos/clawd.git` existiert auf Gitea
- [ ] Lokales Repo: `~/Nextcloud/vinos/clawd/` vorhanden
- [ ] `skills/monitoring/SKILL.md` existiert (angepasst für Vinos)
- [ ] `team/STANDARDS.md` existiert (Vinos-spezifisch)
- [ ] `references/dhl-monitoring-example.md` verweist korrekt auf srv-job01
- [ ] README.md im Root verlinkt alle Strukturen
- [ ] Alle Dateien committet und gepusht
- [ ] CLAUDE.md erweitert (Verweis auf Vinos-Skill)
- [ ] Test: In `~/Nextcloud/vinos/` eine neue Session starten → Skill sollte verfügbar sein (manuelle Prüfung)
---
## Nächste Schritte (nach dieser Phase, nicht Teil des Plans)
- Gap-Analyse für Vinos durchführen → `reports/monitoring-gap-vinos.md`
- srv-job01 auf Gitea pushen (lokal vorhanden, fehlt auf Gitea)
- Weitere Skills nach Bedarf erstellen (infra, mail)
- Post-Mortems bei künftigen Incidents dokumentieren
---
## Kritische Dateien
| Datei | Zeilen (ca.) | Beschreibung |
|-------|--------------|--------------|
| `skills/monitoring/SKILL.md` | ~400 | Monitoring-Requirements-Workflow (Basis: Egonetix, angepasst) |
| `team/STANDARDS.md` | ~200 | Arbeitsstandards mit Monitoring-Pflicht |
| `team/WORKFLOW-POLICY.md` | ~50 | Delegation und Workflow-Regeln |
| `references/dhl-monitoring-example.md` | ~80 | Verweis auf DHL-Monitoring als Vinos-Beispiel |
| `README.md` | ~40 | Einstieg ins Repo |
| `~/.claude/CLAUDE.md` | +10 | Verweis auf Vinos-Skill hinzufügen |
---
## Entscheidungen (geklärt)
| Frage | Entscheidung |
|-------|--------------|
| Egonetix-Skill übernehmen oder neu schreiben? | Übernehmen + anpassen (Grundstruktur bleibt) |
| Netzwerk-Spezifikation in Skill? | NEIN (mehrere Netze, noch nicht vollständig dokumentiert) |
| BCC-Mail-Routing-Beispiel für Vinos? | NEIN (war Egonetix, nicht Vinos) |
| DHL-Monitoring-Beispiel nutzen? | JA (exzellentes Vinos-Beispiel, referenzieren) |
| Kanbanize erwähnen? | JA (explizit als Task-Tracking-System) |
| Gap-Analyse jetzt erstellen? | NEIN (später, nicht Teil dieser Phase) |
| srv-job01 auf Gitea pushen? | NEIN (später, nicht Teil dieser Phase) |
---
**Dieser Plan ist fertig zur Umsetzung.**

View File

@@ -0,0 +1,63 @@
# Plan: Update srvclawdbot01.md for OpenClaw (Clawdbot) + Telegram
## Target File
`/home/rwiegand/Nextcloud/egonetix/infrastructure/hosts/srvclawdbot01.md`
## Changes Overview
### 1. Header Table (Line 8)
**Change:** Update `Funktion` from `Claude Remote Agent` to `Claude Remote Agent + OpenClaw Bot`
### 2. Services Table (Lines 18-22)
**Change:** Add a new row for the Telegram Bot service after the existing entries:
```
| clawdbot-gateway | 18789 | OpenClaw Telegram Bot (@egomol_bot) |
```
### 3. New Section "## OpenClaw / Clawdbot" (after line 123, i.e. after the Claude Remote Agent section ends)
**Change:** Insert a complete new section with:
- Website link, npm package info, bot name
- Komponenten table (5 paths)
- Channels table (Telegram, active)
- Service-Verwaltung code block (systemctl --user commands, clawdbot CLI)
- Gateway info (Port 18789, loopback, token auth, dashboard URL)
### 4. Ressourcen Section (Lines 125-130)
**Change:** Keep existing values (RAM 2 GB, Disk 8 GB) - no modification needed.
### 5. Abhängigkeiten Section (Lines 11-14)
**Change:** Add two new dependencies:
- **Telegram API** (api.telegram.org) - fuer Bot-Kommunikation
- **Anthropic API** (api.anthropic.com) - fuer Claude Model
## Resulting File Structure
```
# srvclawdbot01 - Claude Remote Agent Server
(header table with updated Funktion)
## Abhängigkeiten
(existing + 2 new API dependencies)
## Services
(existing + clawdbot-gateway row)
## Claude Remote Agent
(all existing content unchanged)
## OpenClaw / Clawdbot <-- NEW SECTION
(website, npm, bot info)
### Komponenten <-- NEW
### Channels <-- NEW
### Service-Verwaltung <-- NEW
### Gateway <-- NEW
## Ressourcen
(unchanged)
## Postfix Konfiguration
(unchanged)
```
## No Content Removed
All existing sections and content are preserved. Only additions and one field update (Funktion).

View File

@@ -0,0 +1,139 @@
# Plan: moltbot Arbeitsumgebung einrichten
## Ziel
moltbot (@egomol_bot) soll genauso arbeiten wie die CLI-Sessions: Infrastructure-Doku pflegen, Server verwalten, Repos committen/pushen. Dafür braucht er CLAUDE.md, SSH-Zugriff auf alle Server, und Gitea-Zugang.
## Ausgangslage (srvclawdbot01)
- Clawdbot läuft, Telegram-Channel OK, Pairing abgeschlossen
- SSH-Key existiert: `/root/.ssh/id_rsa` (root@srvclawdbot01)
- Gitea (gitea.egonetix.de:222) ist in known_hosts
- **Fehlt:** CLAUDE.md, SSH-Zugriff auf Infra-Server, Repos geklont, Gitea-Key, Verzeichnisstruktur
## Schritte
### 1. CLAUDE.md deployen
**Datei:** `/root/.claude/CLAUDE.md` auf srvclawdbot01
```bash
scp /home/rwiegand/dotfiles/claude_settings/CLAUDE.md root@10.0.0.61:/root/.claude/CLAUDE.md
```
Claude Code CLI liest diese Datei automatisch als globale Instruktionen. 1:1 Kopie.
### 2. Verzeichnisstruktur anlegen
Gleiche Struktur wie auf dem Laptop, damit CLAUDE.md-Pfade funktionieren:
```bash
ssh root@10.0.0.61 "mkdir -p /root/Nextcloud/egonetix"
```
### 3. SSH-Key auf alle Server verteilen
Den existierenden Key `/root/.ssh/id_rsa.pub` auf alle Server kopieren:
| Server | IP | User |
|--------|----|------|
| srvhost04 | 95.216.112.133 | root |
| srvdc01 | 10.0.0.21 | root |
| srvdocker02 | 10.0.0.29 | root |
| srvmail01 | 10.0.0.23 | root |
| srvmailgw03 | 10.0.0.37 | root |
| srvrevproxy02 | 10.0.0.29 | root |
| srvfs01 | ? | root |
| gwnue01 | 10.0.0.1 | root |
| gw-st01 | 172.20.20.1 | root |
**Methode:** Vom Laptop aus den Public Key lesen und per SSH auf jeden Server verteilen:
```bash
PUBKEY=$(ssh root@10.0.0.61 "cat /root/.ssh/id_rsa.pub")
for host in srvhost04 srvdc01 srvdocker02 srvmail01 srvmailgw03 srvrevproxy02 srvfs01 gwnue01; do
ssh root@$host "echo '$PUBKEY' >> /root/.ssh/authorized_keys && sort -u -o /root/.ssh/authorized_keys /root/.ssh/authorized_keys"
done
```
### 4. Known Hosts populieren
Vom Server aus alle Hosts einmal kontaktieren, damit SSH nicht nach Fingerprints fragt:
```bash
ssh root@10.0.0.61 "for h in 10.0.0.21 10.0.0.23 10.0.0.29 10.0.0.37 95.216.112.133 10.0.0.1 172.20.20.1; do
ssh-keyscan -H \$h >> /root/.ssh/known_hosts 2>/dev/null
done
sort -u -o /root/.ssh/known_hosts /root/.ssh/known_hosts"
```
### 5. Gitea SSH-Key hinterlegen
Public Key als Deploy-Key oder User-Key in Gitea registrieren:
```bash
PUBKEY=$(ssh root@10.0.0.61 "cat /root/.ssh/id_rsa.pub")
curl -X POST -H "Authorization: token $(cat ~/.config/gitea/token)" \
-H "Content-Type: application/json" \
-d "{\"title\":\"moltbot (srvclawdbot01)\",\"key\":\"$PUBKEY\"}" \
https://gitea.egonetix.de/api/v1/user/keys
```
### 6. Repos klonen
Infrastructure-Repo und relevante Repos auf srvclawdbot01 klonen:
```bash
ssh root@10.0.0.61 "
cd /root/Nextcloud/egonetix
git clone ssh://git@gitea.egonetix.de:222/Egonetix/infrastructure.git
"
```
Optional weitere Repos (zabbix, claude-remote-agent) je nach Bedarf.
### 7. dotfiles/claude_settings klonen
Damit moltbot die Settings-Sync Pflicht erfüllen kann:
```bash
ssh root@10.0.0.61 "
mkdir -p /root/dotfiles
cd /root/dotfiles
git clone ssh://git@gitea.egonetix.de:222/root/claude_settings.git
"
```
### 8. Gitea Token auf Server hinterlegen
```bash
ssh root@10.0.0.61 "mkdir -p /root/.config/gitea"
scp /home/rwiegand/.config/gitea/token root@10.0.0.61:/root/.config/gitea/token
```
### 9. tea CLI installieren (optional)
Falls `~/bin/tea` auf dem Server gewünscht ist für Gitea-Interaktion.
### 10. Git-Config auf Server setzen
```bash
ssh root@10.0.0.61 "
git config --global user.name 'moltbot'
git config --global user.email 'moltbot@egonetix.de'
"
```
## Verifikation
1. `ssh root@10.0.0.61 "cat /root/.claude/CLAUDE.md | head -5"` — CLAUDE.md vorhanden
2. `ssh root@10.0.0.61 "ssh root@10.0.0.21 hostname"` — SSH zu srvdc01 funktioniert
3. `ssh root@10.0.0.61 "cd /root/Nextcloud/egonetix/infrastructure && git pull"` — Repo-Zugriff OK
4. `ssh root@10.0.0.61 "cd /root/dotfiles/claude_settings && git pull"` — Settings-Repo OK
5. moltbot in Telegram bitten: "Lies die README von infrastructure und sag mir was drin steht"
6. moltbot bitten: "Prüfe den Status von srvdocker02 per SSH"
## Offene Punkte
- IPs von srvfs01 und srvrevproxy02 verifizieren (aus Host-Dateien)
- gw-st01 (172.20.20.1) ist nur über VPN erreichbar — prüfen ob srvclawdbot01 VPN-Routing hat
- Entscheidung: Soll moltbot eine eigene Git-Identity bekommen (moltbot@egonetix.de) oder die gleiche wie der User?

View File

@@ -0,0 +1,97 @@
# Document Model Selection Strategy in CLAUDE.md
## Goal
Create a clear, non-ambiguous rule for model selection (Haiku vs Sonnet vs Opus) that balances token costs with quality, avoiding false economies where cheaper models lead to more expensive debugging cycles.
## Key Insight from Discussion
Using Haiku for execution with Opus for error recovery is likely **more expensive** in practice because:
- Context loss between models
- Opus must do blind forensics on Haiku's errors
- Error recovery costs more tokens than doing it right the first time
## Model Characteristics
### Haiku (claude-haiku-4-5)
- **Speed**: Fastest
- **Cost**: Cheapest per token
- **Best for**: Truly trivial, zero-risk tasks
- **Risk**: Higher error rate, weaker context understanding
### Sonnet (claude-sonnet-4-5)
- **Speed**: Medium
- **Cost**: Medium (~3x Haiku)
- **Best for**: Most standard tasks, the "default choice"
- **Risk**: Good balance of speed/quality
### Opus (claude-opus-4-5)
- **Speed**: Slower
- **Cost**: Highest (~5x Haiku)
- **Best for**: Complex tasks, deep debugging, critical systems
- **Risk**: Lowest error rate, best context understanding
## Proposed Decision Tree
```
TASK COMPLEXITY:
1. Is this trivial? (git status, typo fix, read a single file)
→ HAIKU
2. Is this a standard task with a plan?
Default: OPUS plans AND executes (one shot, no context loss)
Exception: SONNET executes if BOTH:
- Plan is super-straightforward (mechanical steps, no decisions)
- AND error probability is very low (documented, tested system)
3. Complex/risky tasks?
→ OPUS (always)
```
**Core Principle:** Avoid model switches mid-task. Context loss costs more than using Opus from start.
**Why Opus for execution too?**
- Real-world execution rarely matches the plan exactly
- Opus can adapt on-the-fly without re-planning overhead
- Token-efficient when you factor in error recovery costs
## Critical Files
- `~/.claude/CLAUDE.md` - Global instructions to update
## Implementation Plan
1. **Add new section to CLAUDE.md** after "Mandatory Workflow"
- Title: "Model Selection Strategy"
- Decision tree with concrete examples
- Anti-patterns (what NOT to do)
2. **Document these rules:**
- **Default: Opus plans AND executes** (one shot, no context loss)
- **Sonnet**: Only for execution when plan is super-straightforward AND low error risk
- **Haiku**: Only for truly trivial read-only tasks
- **Never mix models mid-task** - context loss costs more than using Opus from start
3. **Include real examples:**
- **Haiku**: `git status`, reading a single file, checking if a file exists
- **Sonnet** (rare exception): Executing a well-tested deployment script when plan is 100% mechanical
- **Opus** (default): Host scans, documentation, SSH operations, service restarts, debugging, anything with potential for surprises
4. **Add anti-pattern:**
- ❌ "Opus plans, Sonnet/Haiku executes, Opus fixes errors" → Context loss costs more tokens
- ❌ "Save tokens by using cheaper models" → False economy, error recovery is expensive
- ✅ "Opus plans AND executes in one shot" → No context loss, adapts on-the-fly
- ✅ "Only use Haiku for truly trivial read-only tasks"
## Verification
- Read the updated CLAUDE.md section
- Verify the decision tree is unambiguous
- Check that examples are concrete, not vague
- User confirms it's no longer "schwammig"
## Decision Made
After discussion, the strategy is:
- **Opus as default** for planning AND execution (one shot, no context loss)
- **Sonnet only as rare exception** when plan is 100% mechanical AND low error risk
- **Haiku only for trivial read-only** operations
Rationale: Context loss between models costs more tokens than using Opus from start. Real-world execution rarely matches plans exactly.

View File

@@ -0,0 +1,63 @@
# Plan: Monitor-Auswahl im RDP Client
## Problem
`_get_best_monitor_selection(count)` wählt automatisch die N linkesten Monitore.
Bei 3 Monitoren (Laptop + 2 Extern) wird bei "2 Monitors" immer Laptop + 1 Extern gewählt,
statt der gewünschten 2 Externen.
## Lösung: "Custom..." Option mit Checkbox-Dialog
Eine neue Option "Custom..." im Multi-Monitor-Dropdown, die einen Dialog öffnet,
in dem der User per Checkbox auswählt, welche Monitore genutzt werden sollen.
Die Auswahl wird pro Verbindung in `monitor_ids` gespeichert.
## Änderungen in `rdp_client.py`
### 1. Neue Methode: `_get_monitor_details()`
- Ruft `xfreerdp /monitor-list` auf
- Gibt Liste mit Monitor-Infos zurück: `[{id, name, resolution, position, is_primary}]`
- Ergänzt um xrandr-Ausgabenamen (DP-3-1, eDP-1, etc.) für bessere Lesbarkeit
### 2. Neuer Dialog: Monitor-Auswahl-Dialog
- Wird geöffnet wenn "Custom..." im Dropdown gewählt wird
- Zeigt alle verfügbaren Monitore mit Checkboxen:
```
[x] Monitor 0: DP-3-1 1920x1080 +3840+60
[ ] Monitor 1: eDP-1 1920x1200 +0+0 (primary)
[x] Monitor 2: DP-3-2 1920x1080 +1920+60
```
- Mindestens 1 Monitor muss ausgewählt sein
- OK/Cancel Buttons
### 3. Dropdown-Optionen erweitern (`_get_multimon_options()`)
- Neue Option `"Custom..."` am Ende hinzufügen (vor Span)
- Optionen: `["No", "2 Monitors", "3 Monitors", "Custom...", "All Monitors", "Span"]`
### 4. Connection-Editor anpassen (Zeile ~1441)
- Wenn "Custom..." gewählt wird → Dialog öffnen
- Ausgewählte Monitor-IDs in `monitor_ids` speichern (z.B. `"0,2"`)
- Label neben Dropdown zeigt aktuelle Auswahl: "Monitors: 0, 2"
### 5. Verbindungsaufbau anpassen (Zeile ~930-966)
- Neuer Case für `multimon == "Custom..."`:
```python
elif multimon == "Custom...":
monitor_list = conn.get("monitor_ids", "0")
cmd.append("/multimon")
cmd.append(f"/monitors:{monitor_list}")
```
### 6. Details-Anzeige anpassen (Zeile ~721)
- Bei "Custom..." zusätzlich die gespeicherten Monitor-IDs anzeigen
## Betroffene Datei
- `/home/rwiegand/Nextcloud/entwicklung/Werkzeuge/rdp_client.py`
## Verifikation
1. Script starten: `python3 rdp_client.py`
2. Verbindung bearbeiten → "Custom..." wählen → Dialog prüfen
3. Monitore 0 und 2 auswählen → Speichern
4. Verbindung starten → prüfen ob `xfreerdp /multimon /monitors:0,2` aufgerufen wird

View File

@@ -0,0 +1,188 @@
# Plan: CRIF Nächtliche False-Positive Problemmeldungen beheben
## Problem
**Kanbanize-Ticket:** #13461 - "VAE-Meldungen erhält jede Nacht Nachricht über CRIF"
**Symptome:**
- Jede Nacht kommt eine Zabbix-Problemmeldung zum CRIF-Export
- Problem löst sich nach ca. 15 Minuten automatisch
- Die Zeiten sind sehr unregelmäßig
**Betroffener Trigger:**
- TriggerID: 44829
- Name: `processing_backup_monitoring_hours_crif`
- Host: SRV-JOB01
- Kategorie: Interface/CRIF
## Hintergrund
Laut Dokumentation (troubleshooting.md:151-164):
- **Ablauf:** NAV erstellt Export → Scheduled Task (02:00) lädt zu CRIF FTP hoch → Dateien werden ins Backup-Verzeichnis verschoben
- **Trigger-Funktion:** Prüft ob Dateien jünger als 1 Tag im `\\vinos.local\sys\nav\interfaces\CRIFBuergel\backup` Ordner existieren
- **Häufige Ursache:** NAV Aufgabenwarteschlange läuft nicht (aber hier löst sich das Problem selbst → kein echter Fehler)
## Hypothese (BESTÄTIGT durch Phase 1)
**VERIFIZIERTE FAKTEN:**
- Trigger 44829 auf SRV-JOB01 überwacht CRIF-Backup (korrekt dokumentiert)
- Item: `processing_backup_monitoring_hours_crif` (Trapper-Type, empfängt Werte)
- Events feuern um ~01:15-01:45 CET (nicht 02:00!)
- Scheduled Task "Transfer-FilesWinSCP" läuft um 02:00
- **ABER:** Backup-Dateien landen schon um 01:07-01:41 (vorher!)
**Erkannte Ursache:**
Es gibt einen **ANDEREN Prozess** der die Backup-Dateien um ~01:00-01:30 erstellt (vermutlich NAV/Business Central Export). Der 02:00 Task ist nur der **Transfer**, nicht die Erstellung.
Der Trigger prüft um ~01:30 und findet zu dem Zeitpunkt noch keine neuen Dateien (Export läuft noch), dann sind sie 15-45 Min später fertig → Auto-Recovery.
**Problem:** Timing zwischen NAV-Export (unregelmäßig 01:07-01:41) und Monitoring-Check (~01:30) ist zu eng.
## Implementierungsplan
### Phase 1: Diagnose & Datensammlung ✅ ABGESCHLOSSEN
**Ergebnisse:**
**Trigger 44829 (verifiziert via Opus-Agent):**
- Host: SRV-JOB01 (hostid 10636)
- Item: 99026 "processing_backup_monitoring_hours_crif" (Trapper-Type)
- Expression: `{86644}=1` (feuert wenn Item-Wert = 1)
- Tags: IFS-Meldungen, VAE-Meldungen, fts
**Event-Pattern (7 Tage):**
- Häufigkeit: 5 Events in 7 Tagen (täglich nachts)
- Timing: 01:15-01:45 CET
- Dauer bis Recovery: 15-45 Min (Durchschnitt: 36 Min)
- 100% Auto-Recovery
**Scheduled Task "Transfer-FilesWinSCP":**
- Läuft um: 02:00:00 täglich
- Dauer: 2-3 Sekunden
- LastTaskResult: 0 (erfolgreich)
**KRITISCHER FUND: Timing-Diskrepanz**
- Backup-Dateien landen: 01:07-01:41 (unregelmäßig!)
- Scheduled Task läuft: 02:00 (zu spät!)
- → Es gibt einen ANDEREN Prozess der die Dateien erstellt
**Hypothese bestätigt:** NAV/Business Central erstellt Exports um ~01:00-01:30, Transfer-Task transportiert sie um 02:00. Trigger prüft während der Export-Erstellung läuft.
### Phase 2: Lösungsansatz entwickeln
**EMPFOHLENE LÖSUNG (basierend auf Phase 1):**
**Option A: Monitoring-Check-Timing verschieben** ⭐ BESTE LÖSUNG
- **Problem:** Check läuft während NAV-Export (01:15-01:45)
- **Lösung:** Item-Update-Intervall so setzen dass Check NACH Export läuft (z.B. 02:30 oder 03:00)
- **Vorteil:** Einfach, keine False-Positives mehr
- **Nachteil:** Erkennt Probleme erst 1-2h später
**Option B: Grace Period / Hysteresis einbauen**
- **Problem:** Export braucht 15-45 Min aber Trigger ist ungeduldig
- **Lösung:** Trigger feuert erst wenn 2-3 Checks in Folge fehlschlagen (z.B. "no data for 2 hours")
- **Vorteil:** Erkennt echte Ausfälle vs. temporäre Export-Phasen
- **Nachteil:** Komplexere Trigger-Logic
**Option C: Maintenance Window**
- **Problem:** Nächtliche Wartung/Export = False-Positive
- **Lösung:** Maintenance Window 01:00-02:00 CET
- **Vorteil:** Sauber, professionell
- **Nachteil:** Echte Ausfälle in diesem Fenster werden nicht gemeldet
**Option D: NAV-Export-Prozess finden und direkt überwachen**
- **Problem:** Wir überwachen Backup-Dateien, nicht den Prozess
- **Lösung:** NAV Aufgabenwarteschlange direkt überwachen (siehe troubleshooting.md:160 "Häufigste Ursache: NAV läuft nicht")
- **Vorteil:** Root-Cause-Monitoring statt Symptom-Monitoring
- **Nachteil:** Erfordert NAV-Zugriff und neue Items
**EMPFEHLUNG:** Kombination A + B
1. Check-Timing auf 02:30 verschieben (nach Export UND Transfer)
2. Hysteresis: "Problem erst wenn 2 Checks (30 Min) fehlschlagen"
3. Damit: False-Positives weg + echte Ausfälle erkannt
### Phase 3: Fix implementieren (Option A - Check-Timing verschieben)
**Ziel:** Item-Update-Intervall so setzen dass Check NACH NAV-Export + Transfer läuft.
**Schritte:**
1. **Item 99026 Details abrufen:**
- Aktuelles Update-Intervall prüfen
- Type = Trapper → Werte werden gepusht, kein Poll-Intervall
- → Das Script das die Werte pusht muss gefunden werden
2. **Monitoring-Script finden:**
- Auf SRV-JOB01: Scheduled Task der das Item befüllt
- Wahrscheinlich: PowerShell-Script das Backup-Ordner prüft
- Task-Name vermutlich: "Zabbix*CRIF*" oder ähnlich
- Pfad vermutlich: `C:\Skripte\` oder `C:\Tasks\`
3. **Scheduled Task anpassen:**
- Backup der Task-Definition erstellen
- Task-Zeitplan von aktuell (vermutlich 01:30) auf **02:30** verschieben
- Begründung: NAV-Export läuft 01:07-01:41, Transfer 02:00, Check danach um 02:30
4. **Dokumentation aktualisieren:**
- `troubleshooting.md` Abschnitt "CRIF Bürgel Export-Monitoring" ergänzen
- Neues Timing dokumentieren
- Begründung für Änderung festhalten
5. **Verifikation:**
- Morgen (03.02.2026) um ~02:30 Events prüfen
- Bestätigen: Kein False-Positive mehr
- 3-5 Nächte beobachten
### Phase 4: Dokumentation & Abschluss
1. **Troubleshooting.md aktualisieren:**
- Abschnitt "CRIF Bürgel Export-Monitoring" erweitern
- Fix und Erkenntnisse dokumentieren
- Pitfall hinzufügen falls relevant
2. **README.md aktualisieren:**
- Trigger-ID Eintrag aktualisieren falls Name/Beschreibung geändert
3. **Kanbanize-Kommentar erstellen:**
- Problemdokumentation nach Template
- User-Freigabe einholen bevor gepostet wird
4. **Git Commit:**
- Dokumentationsänderungen committen
- Aussagekräftige Commit-Message
## User-Entscheidung
✅ Option A gewählt: Monitoring-Check-Timing verschieben
- Check-Zeit von ~01:30 auf 02:30 verschieben
- Damit läuft Check NACH NAV-Export (01:07-01:41) UND Transfer-Task (02:00)
## Risiken & Überlegungen
- **Kein Produktions-Impact:** CRIF-Export läuft, nur Monitoring ist zu sensitiv
- **Vorsicht:** Schwellwert nicht zu hoch setzen, sonst übersehen wir echte Ausfälle
- **Testing:** Idealerweise würden wir 2-3 Nächte beobachten nach dem Fix
## Verification Strategy
**Sofort nach Fix:**
1. Scheduled Task Status prüfen: NextRunTime = 02:30?
2. Task manuell triggern um zu testen
**Nächste Nacht (03.02.2026):**
1. Um ~02:35: Zabbix Events prüfen
2. Bestätigen: Kein neues Problem-Event
3. Bestätigen: Item-Wert = 0 (OK)
**Langfristig (3-5 Nächte):**
1. Event-Historie beobachten
2. Bestätigen: Keine False-Positives mehr
3. Optional: NAV-Export simuliert ausfallen lassen um zu testen ob echter Alarm käme
## Success Criteria
- [ ] Trigger 44829 feuert nicht mehr jede Nacht
- [ ] Wenn CRIF-Export tatsächlich fehlt, wird er trotzdem erkannt
- [ ] User erhält keine nächtlichen Problemmeldungen mehr
- [ ] Dokumentation ist aktualisiert
- [ ] Kanbanize-Kommentar erstellt und User-approved

View File

@@ -1,11 +1,4 @@
{ {
"statusLine": {
"type": "command",
"command": "$HOME/.claude/statusline-command.sh"
},
"enabledPlugins": {
"superpowers@claude-plugins-official": true
},
"hooks": { "hooks": {
"SessionStart": [ "SessionStart": [
{ {
@@ -18,5 +11,12 @@
] ]
} }
] ]
},
"statusLine": {
"type": "command",
"command": "$HOME/.claude/statusline-command.sh"
},
"enabledPlugins": {
"superpowers@claude-plugins-official": true
} }
} }