docs: Betriebshandbuch §8–§13 (Zugang, Benachrichtigungen, Firewall, Zertifikat, Netzwerk, Testvorgehen), healthcheck.sh, Plan Phase 4 erledigt
ci / test (push) Successful in 27s

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Robert Rapp
2026-10-13 17:12:51 +02:00
co-authored by Claude Fable 5.1
parent 47ad1580ff
commit 97bbb58433
4 changed files with 152 additions and 9 deletions
+70 -1
View File
@@ -1,4 +1,4 @@
# Betrieb: Skill-Lebenszyklus, Hermes, Pflege, Freischaltung
# Betrieb: Skill-Lebenszyklus, Hermes, Pflege, Freischaltung, Proxmox-Cluster
## 1. Lebenszyklus eines Skills
@@ -141,3 +141,72 @@ Nach `zfs receive` (Replikation) liefert ein Knoten für Dateien, die dort früh
2. Die defekte Datenbank bzw. das Verzeichnis beiseiteschieben, z. B. `mv /var/lib/docker/buildkit /var/lib/docker/buildkit.defekt-<datum>`.
3. `systemctl start docker`, dann `docker compose -p knaster-infra --env-file /opt/knaster/infra/.env -f /opt/knaster/repo/deploy/compose/infra/docker-compose.yml up -d --force-recreate` (Volumes bleiben, kein `down -v`).
4. Danach auf ops `ansible-playbook playbooks/monitoring.yml --limit infra`.
## 8. Zugang: Benutzer, Rollen, 2FA, Token (Phase 4.1/4.2)
Stand 13.10.2026, Quelle `sites/knaster/proxmox.yaml` (`access`), ausgerollt mit `playbooks/cluster.yml` (Rolle `pve-cluster`).
| Konto | Zweck | Rechte | Geheimnis liegt |
|---|---|---|---|
| `r.rapp@pve` | persönlicher Admin (Weboberfläche) | Gruppe `admins` = Administrator auf `/` | Passwort `PVE_ADMIN_R_RAPP_PASS` in `it/proxmox/.env`, TOTP + Recovery-Keys in `it/proxmox/tfa-r.rapp.txt` |
| `root@pam` | Notfallzugang, SSH-Schlüssel, Ansible | alles | Passwörter `PVExx_PASS` in `.env`, Schlüssel `keys/id_ed25519_pve` |
| `tofu@pve!ops` | OpenTofu auf ops | VM-, Storage-, Mapping-, Pool-Rechte | ops `/root/.config/knaster/tofu.env` |
| `monitoring@pve!prom` | pve-exporter | PVEAuditor | ops `/root/.config/knaster/pve-exporter.env`, Kopie in infra |
| `healer@pve!knaster` | Healer (SPEC-healer) | Rolle `KnasterHealer` (`VM.PowerMgmt`, `VM.Audit`) nur auf `/pool/gpu` | ops `/root/.config/knaster/healer.env` |
- **Anmeldung Weboberfläche:** Benutzer `r.rapp`, Realm „Proxmox VE authentication server“, danach TOTP-Code. Die Recovery-Keys gelten je einmal.
- **TOTP einrichten:** `it/proxmox/tfa-r.rapp.txt` enthält die otpauth-URI und das Secret. In der Authenticator-App „manuell eingeben“ (Secret, 6 Stellen, 30 s) oder aus der URI einen QR-Code erzeugen.
- **Neues Admin-Konto:** Name in `access.admin_users` eintragen, `playbooks/cluster.yml` auf ops, dann vom Laptop `platform/proxmox/scripts/pve-admin-user.sh <name>` (setzt Passwort, TOTP, Recovery-Keys; idempotent).
- **2FA für root@pam** ist bewusst nicht gesetzt: root bleibt Notfallzugang und läuft über SSH-Schlüssel. Wenn gewünscht, gleiches Vorgehen über `pvesh create /access/tfa/root@pam` – vorher den Code in einer App haben, sonst sperrt man sich aus der Weboberfläche aus (SSH bleibt).
- **Token rotieren:** `pveum user token remove <user> <token>`, Datei auf ops löschen, Playbook erneut (Healer) bzw. Token neu anlegen und Datei schreiben (tofu, monitoring).
- Verloren gegangenes TOTP: `pvesh get /access/tfa/<user>` listet die Einträge, `pvesh delete /access/tfa/<user>/<id>` entfernt sie, danach das Skript erneut.
## 9. Benachrichtigungen (Phase 4.3)
Ziel `knaster-mail` (Sendmail an `ki@mygodel.de`, aus `access.mail_to`), Matcher `knaster-alles` ohne Filter (Backup, Fencing, Replikation, Paket-Updates), `default-matcher` abgeschaltet (sonst doppelt). Postfix auf den Knoten liefert direkt an die MX von mygodel.de (13.10. getestet: `250 … Queued mail for delivery`). Kein SMTP-Relay, keine Zugangsdaten.
- Test: `pvesh create /cluster/notifications/targets/knaster-mail/test` auf einem Knoten, Zustellung im Journal: `journalctl -u postfix --since -10min | grep status=`.
- Landet die Mail im Spam: Absender `root@pveXX.buero-godel.local` hat kein SPF. Dann in Exchange Online eine Transportregel oder einen Connector für die Knoten-IPs anlegen.
- Empfänger ändern: `access.mail_to` in der Site-Datei, dann `pvesh set /cluster/notifications/endpoints/sendmail/knaster-mail --mailto <adresse>` (das Playbook legt nur an, es ändert bestehende Ziele nicht).
## 10. Firewall (Phase 4.4)
Datacenter-Firewall aktiv auf allen Knoten (`/etc/pve/firewall/cluster.fw`, Vorlage `roles/pve-cluster/templates/cluster.fw.j2`). Eingehend DROP, ausgehend ACCEPT.
- **IPSET `admin`:** die fünf Knoten, Admin-Laptop `.151`, appsrv08 `.29`, ops `.173`, infra `.188`. Nur diese erreichen 22, 8006, 3128, 5900–5999 und 60000–60050. Alle anderen Adressen im LAN bekommen auf diesen Ports DROP, Ping aus dem LAN geht. Corosync zwischen den Knoten erlaubt Proxmox selbst.
- **Warum eigene Regeln statt IPSET `management`:** Proxmox ergänzt `management` immer um das lokale Netz (`local_network`, hier das ganze /24). Eine Einschränkung auf einzelne Adressen wirkt deshalb nur mit ACCEPT für `+admin` und anschließendem DROP für das /24 (13.10. geprüft: aus einer GPU-VM sind 22 und 8006 zu, vom Laptop und aus infra offen).
- **DHCP-Risiko (D5):** Laptop, ops und infra haben keine Reservierung. Wechselt eine Adresse, ist diese Quelle ausgesperrt. Rückweg: von einer noch zugelassenen Adresse (z. B. `ssh ops`, dann `ssh pve44`) die Adresse in `sites/knaster/proxmox.yaml` ändern und das Playbook laufen lassen, oder direkt `cluster.fw` bearbeiten. Letzter Rückweg: Konsole am Knoten, dort `pve-firewall stop` bzw. `enable: 0` in `cluster.fw`.
- **Totmannschalter:** Das Playbook stellt bei jeder Änderung einen Timer (`knaster-fw-totmann`, 600 s), der `enable: 0` schreibt, und hebt ihn erst nach erfolgreicher Prüfung (SSH und 8006 zu allen Knoten von ops aus) wieder auf. Bricht der Lauf ab, geht die Firewall von selbst wieder aus.
- Neue Verwaltungsquelle (z. B. zweiter Laptop): Eintrag unter `firewall.management`, Playbook laufen lassen.
- Gast-Firewalls (VM/LXC) sind nicht aktiviert; die GPU-VMs schützen ihre Ports mit ufw (Abschnitt 7).
## 11. Zertifikat der Weboberfläche (Phase 4.6)
Die Knotenzertifikate stammen von der Cluster-CA (`/etc/pve/pve-root-ca.pem`, gültig bis 2036) und enthalten die IP-Adresse als SAN. Es reicht, die CA einmal auf dem Laptop als vertrauenswürdig einzutragen, dann sind `https://192.168.100.2xx:8006` für alle fünf Knoten ohne Warnung erreichbar.
- Kopie der CA: `it/proxmox/pve-root-ca.pem` (SHA-256 `A2:71:C0:AB:…:77:3E`, zum Abgleich `openssl x509 -in … -noout -fingerprint -sha256`).
- Import ohne Adminrechte (Benutzerspeicher, Windows fragt einmal nach): `certutil -user -addstore Root C:\Users\r.rapp\it\proxmox\pve-root-ca.pem`. Danach Browser neu starten.
- Kein ACME/Let's Encrypt: die Knoten haben keine öffentlichen Namen (IP-Regel, kein DNS).
## 12. Netzwerk-Prüfung (Stand 13.10.2026)
| Knoten | NIC | Treiber | Link | Bridge |
|---|---|---|---|---|
| pve44, pve46, pve48, pve52 | Intel onboard `nic0` | `e1000e` | 1 GBit/s | `vmbr0` → `nic0`, kein VLAN-aware |
| pve61 | USB-NIC im Dock `enx3ce1a1c0839d` | `r8152` | 1 GBit/s | `vmbr0` → USB-NIC, ein Link-Reset seit Start |
- Keine `e1000e`-Hänger („Detected Hardware Unit Hang“) im Kernel-Log. Sollten sie auftreten: `ethtool -K nic0 tso off gso off` als bekannter Ausweg, dann in `/etc/network/interfaces` festhalten.
- **VLAN:** nicht aktiviert (Global Constraint „vorerst kein VLAN“). Wenn nötig: `bridge-vlan-aware yes` und `bridge-vids 2-4094` auf `vmbr0`, `ifreload -a`; auf pve61 nur vor Ort (USB-NIC).
- Eine zweite NIC für ein getrenntes Corosync- oder Migrationsnetz gibt es auf keinem Knoten. Migration läuft `secure` über das LAN.
- Feste Adressen: Knoten sind statisch, Gäste und Laptop per DHCP (D5 offen, Task 0.2). Erst mit Reservierungen ist die Firewall-Liste dauerhaft stabil.
## 13. Testvorgehen
`platform/proxmox/scripts/healthcheck.sh` (Laptop oder ops, nur lesend) prüft in einem Lauf: Quorum und Stimmen, HA-Dienste, Replikation, Firewall aktiv und Regel `+admin`, Matcher, Benutzer und 2FA; je Knoten Kernel, fehlgeschlagene Dienste, Knoten-Firewall, NTP, `vmbr0`, Platz auf `/`, `tank`, Zertifikatslaufzeit, GPU-Bindung an `vfio-pci`, NIC-Hänger, Weboberfläche; dazu den Negativtest aus einer GPU-VM. Ausgabe `OK`/`FEHLER` je Prüfung, Exit 1 bei Fehlern.
Wann laufen lassen:
1. Nach jedem Playbook-Lauf gegen die Knoten (`site.yml`, `cluster.yml`) und nach jedem Neustart (Abschnitt 6, Schritt 5).
2. Vor einer Änderung an Firewall, Benutzern oder Netzwerk als Vergleichsbasis.
3. Wöchentlich als Routine; Grafana (Abschnitt 7) deckt den Rest kontinuierlich ab.
Manuelle Ergänzungen, die das Skript nicht abdeckt: Anmeldung mit `r.rapp@pve` und TOTP in der Weboberfläche, Testmail (Abschnitt 9), Dock-Test an pve61 (Task 1.3, vor Ort), Wartungsmodus-Probe (Abschnitt 6).
@@ -128,7 +128,7 @@ Ersetzt PLAN §8 „0 Fundament“ (Teil Inventar) und IMPLEMENTATION „Gemeins
**Wo:** remote (DHCP-Server, vermutlich DC `.120` oder UniFi) · **Planner:** „PVE-Config: Netzwerk prüfen – Bridge, VLAN-Fähigkeit und NIC-Kompatibilität“
- [ ] DHCP-Bereich auslesen. Für .207, .209, .210, .212 und .214 Reservierungen auf die MACs der Knoten anlegen (MACs stehen im Healthcheck). Ebenso eine Reservierung für den Admin-Laptop (heute .151 per WLAN). Die Firewall in 4.4 lässt nur diese Adresse zu, ein Lease-Wechsel würde sonst aussperren.
- [ ] DHCP-Bereich auslesen. **Seit 13.10. dringender:** Die Firewall (4.4) lässt nur .151 (Laptop), .173 (ops) und .188 (infra) an die Verwaltungsports; ein Lease-Wechsel sperrt die Quelle aus (BETRIEB §10). Für .207, .209, .210, .212 und .214 Reservierungen auf die MACs der Knoten anlegen (MACs stehen im Healthcheck). Ebenso eine Reservierung für den Admin-Laptop (heute .151 per WLAN). Die Firewall in 4.4 lässt nur diese Adresse zu, ein Lease-Wechsel würde sonst aussperren.
- [ ] Gäste-Block festlegen (Vorschlag `.220–.239`) und als Ausschluss im DHCP eintragen.
Prüfung: `ping` auf jede Adresse des Blocks → keine Antwort. DHCP-Ausschluss sichtbar.
@@ -304,12 +304,12 @@ Ersetzt GPU-Knoten 3 (Teil Cluster). Mit 5 Stimmen ist **kein QDevice** nötig.
**Wo:** remote. Jede Aufgabe hier entspricht einer Planner-Aufgabe.
- [ ] **4.1 Benutzer und Token** (12.10. teilweise: `tofu@pve!ops` mit engen ACLs und `monitoring@pve!prom` (PVEAuditor, Geheimnis nur auf ops `/root/.config/knaster/pve-exporter.env`) angelegt; offen: persönlicher Admin-Benutzer (Name vom Nutzer), `healer@pve!knaster`) („PVE-Config: Persönlicher Admin-Benutzer, Rollen und API-Token anlegen“): Admin-Benutzer und Gruppe, root@pam nur als Notfallzugang. Token `monitoring@pve!prom` (PVEAuditor), `healer@pve!knaster` (nur `VM.PowerMgmt` auf GPU-VMs, PLAN §3), `tofu@pve!ops`.
- [ ] **4.2 2FA** („PVE-Config: Zwei-Faktor-Authentifizierung für Admin-Konten aktivieren“): TOTP für root@pam und Admin. Recovery-Keys offline ablegen.
- [ ] **4.3 Benachrichtigungen** („PVE-Config: Benachrichtigungen (Notification Center) einrichten“): SMTP-Ziel Büro-Postfach, Matcher für Backup, Fencing und Updates. Testnachricht kommt an.
- [ ] **4.4 Firewall** („PVE-Config: Firewall auf Datacenter- und Knotenebene einrichten“): IP-Set `admin` (Laptop) und `appsrv08` (.29). Zuerst Allow-Regeln für 8006, 22 und ICMP, **dann** aktivieren. Konsole als Rückfall bereithalten. Prüfung: Weboberfläche vom Laptop ok, von einem anderen Rechner gesperrt.
- [x] **4.1 Benutzer und Token** (13.10. erledigt, Rolle `pve-cluster`/`playbooks/cluster.yml`: Gruppe `admins` (Administrator auf `/`), `r.rapp@pve` mit Passwort per `scripts/pve-admin-user.sh`, Rolle `KnasterHealer` + `healer@pve!knaster` nur auf `/pool/gpu`, Token auf ops `/root/.config/knaster/healer.env`; BETRIEB §8) (12.10. teilweise: `tofu@pve!ops` mit engen ACLs und `monitoring@pve!prom` (PVEAuditor, Geheimnis nur auf ops `/root/.config/knaster/pve-exporter.env`) angelegt; offen: persönlicher Admin-Benutzer (Name vom Nutzer), `healer@pve!knaster`) („PVE-Config: Persönlicher Admin-Benutzer, Rollen und API-Token anlegen“): Admin-Benutzer und Gruppe, root@pam nur als Notfallzugang. Token `monitoring@pve!prom` (PVEAuditor), `healer@pve!knaster` (nur `VM.PowerMgmt` auf GPU-VMs, PLAN §3), `tofu@pve!ops`.
- [x] **4.2 2FA** (13.10.: TOTP + Recovery-Keys für `r.rapp@pve`, Datei `it/proxmox/tfa-r.rapp.txt`; root@pam bewusst ohne 2FA als Notfallzugang, BETRIEB §8) („PVE-Config: Zwei-Faktor-Authentifizierung für Admin-Konten aktivieren“): TOTP für root@pam und Admin. Recovery-Keys offline ablegen.
- [x] **4.3 Benachrichtigungen** (13.10.: Ziel `knaster-mail` → ki@mygodel.de per Sendmail direkt an die MX, Matcher `knaster-alles`, `default-matcher` aus, Testmail zugestellt; BETRIEB §9) („PVE-Config: Benachrichtigungen (Notification Center) einrichten“): SMTP-Ziel Büro-Postfach, Matcher für Backup, Fencing und Updates. Testnachricht kommt an.
- [x] **4.4 Firewall** (13.10.: aktiv auf allen Knoten, IPSET `admin` = Knoten + .151/.29/.173/.188, ACCEPT +admin dann DROP /24 auf 22/8006/3128/5900-5999/60000-60050 – `management` taugt nicht, Proxmox ergänzt es stets um das /24; Totmannschalter im Playbook; Negativtest aus GPU-VM bestanden; BETRIEB §10) („PVE-Config: Firewall auf Datacenter- und Knotenebene einrichten“): IP-Set `admin` (Laptop) und `appsrv08` (.29). Zuerst Allow-Regeln für 8006, 22 und ICMP, **dann** aktivieren. Konsole als Rückfall bereithalten. Prüfung: Weboberfläche vom Laptop ok, von einem anderen Rechner gesperrt.
- [x] **4.5 Ordnung** (12.10.: Pools `gpu` = 244/246/248/252 per tofu, `infra` = 100/101 per `pveum` – beim Container würde `pool_id` in tofu ein Ersetzen erzwingen; Tags `knaster`, `gpu`, `legacy`, `infra`, `ops` per tofu/pct. LXC-Standard so umgesetzt: unprivilegiert, Debian 13.6, Nesting nur bei Docker) („PVE-Config: Ressourcenpools und Tags festlegen“, „PVE-Config: Standard für neue LXC-Container festlegen“): Pools `infra`, `gpu`, `test`. Tags `gpu`, `infra`, `test`. LXC-Standard: unprivilegiert, Debian-13-Vorlage, Nesting nur für Docker.
- [ ] **4.6 Zertifikat** („PVE-Config: Web-GUI-Zertifikat festlegen (niedrige Priorität)“): `/etc/pve/pve-root-ca.pem` auf dem Laptop als vertrauenswürdig importieren.
- [x] **4.6 Zertifikat** (13.10.: CA nach `it/proxmox/pve-root-ca.pem` kopiert, Knotenzertifikate tragen die IP als SAN; Import am Laptop per `certutil -user -addstore Root …`, BETRIEB §11) („PVE-Config: Web-GUI-Zertifikat festlegen (niedrige Priorität)“): `/etc/pve/pve-root-ca.pem` auf dem Laptop als vertrauenswürdig importieren.
- [x] **4.7 Update-Routine** (12.10.: `docs/BETRIEB.md` Abschnitt 6, Wartungsmodus getestet) („PVE-Config: Update- und Neustart-Routine festlegen (rollierend, Knoten für Knoten)“): Ablauf in `docs/BETRIEB.md` eintragen (Wartungsmodus, ein Knoten nach dem anderen, GPU-VMs vorher sauber stoppen).
---
@@ -418,7 +418,7 @@ Am Ende von Phase 9 wird das Betriebshandbuch abgeschlossen („PVE-Config: Betr
| Planner-Aufgabe (exakter Titel) | Im Plan | Planner-Aktion nach Freigabe |
|---|---|---|
| Proxmox: pve48 root-Passwort klären und SSH-Schlüssel nachtragen | Task 0.1 | bleibt |
| PVE-Config: Netzwerk prüfen – Bridge, VLAN-Fähigkeit und NIC-Kompatibilität | Task 0.2 (D5), VLAN später | bleibt, Beschreibung ergänzen |
| PVE-Config: Netzwerk prüfen – Bridge, VLAN-Fähigkeit und NIC-Kompatibilität | Task 0.2 (D5), VLAN später | 13.10. geprüft (BETRIEB §12: e1000e/r8152, 1 GBit, kein VLAN-aware, keine Hänger), erledigt; Reservierungen bleiben in 0.2 |
| Proxmox: Konfiguration aller Knoten durcharbeiten | aufgeteilt auf 0.1, 1.1–1.3 | schließen mit Verweis auf diesen Plan |
| PVE-Config: Erst-Update aller Knoten (apt full-upgrade) | Task 1.1 | bleibt |
| Proxmox: Speicher aller Knoten richtig konfigurieren | D1, Task 1.2 | bleibt |
@@ -439,7 +439,7 @@ Am Ende von Phase 9 wird das Betriebshandbuch abgeschlossen („PVE-Config: Betr
| Proxmox: pve61 (Surface) zeigt das Grafana-Dashboard als Kiosk | Tasks 1.3, 5.3 | bleibt |
| LLM-Worker: direkte Inferenz-Schnittstelle für LiteLLM (zusätzlich zum Job-Poll), Tunnel, Registry, Fallback-Kette | Task 6.4 | bleibt, Beschreibung: Registry v2 + knaster-Brücke |
| Proxmox: GRP als Testservice in einen LXC-Container umziehen | Phase 8 | bleibt |
| PVE-Config: Betriebshandbuch und Testvorgehen anlegen | Phase 9 (`docs/BETRIEB.md`) | bleibt |
| PVE-Config: Betriebshandbuch und Testvorgehen anlegen | Phase 9 (`docs/BETRIEB.md`) | 13.10. erledigt: §8–§13 und `scripts/healthcheck.sh` |
| P1–P8 (NEX-Aufgaben) | Parallelspur | bleiben |
**Neu angelegt** (nur Schritte ohne bestehende Aufgabe, keine Duplikate):