Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
20 KiB
Betrieb: Skill-Lebenszyklus, Hermes, Pflege, Freischaltung, Proxmox-Cluster
1. Lebenszyklus eines Skills
Hermes schreibt SKILL.md
│
draft ──(Mensch/Agent: aktivieren)──▶ active, Stufe 0
│ läuft auf dem starken Modell mit Skill-Text,
│ sammelt verifizierte Fälle
Service-Routine: stabil ≥ 95 % ────┤
▼
request_graduation (Freigabe)
│ Hermes erzeugt Varianten →
│ POST /v1/skills/{name}/graduate
▼
promote_skill (Freigabe) ──▶ active, Stufe 1 (schwaches Modell)
│
Drift (Pass-Rate < 80 %) ──▶ demote_skill (automatisch) ──▶ demoted (Stufe 0)
│
≥ 300 Trainingsfälle, Stufe-1-Rate < 90 % ─▶ train_adapter (Freigabe) ──▶ Lifecycle-Pipeline
Stufe 2 (Programm) und Stufe 3 (Classifier) gibt es, wenn der Skill execution: program|classifier deklariert und die passende Stufe freigegeben ist. Programme liegen in knaster/programs.py und gehen wie normaler Code durch ein Review. Classifier entstehen aus gelabelten Fällen (EmbeddingClassifier.train) und liegen unter config/classifiers/<name>.json.
2. Rolle von Hermes
Hermes läuft als Skill-Autor mit dem starken Modell. Er zeigt auf LiteLLM, Alias tier0-strong. Hermes steht nicht im Pfad jeder Anfrage.
| Auslöser | Hermes tut | Schnittstelle |
|---|---|---|
Job graduate_skill (über n8n knaster-jobs) |
10–30 realistische Varianten erzeugen, Graduierung aufrufen. Schlägt sie fehl, den Skill anhand von failures überarbeiten |
POST /v1/skills/{name}/graduate |
Job merge_skills |
zwei Skills zu einem zusammenführen, alten Skill auf retired setzen |
Git-Commit in skills/, dann POST /v1/skills/reload |
Neue Aufgabenklasse (häufige no_skill-Fälle) |
neuen SKILL.md-Entwurf schreiben (status: draft) |
Git-Commit + Reload |
Skills sind Dateien im Repo. Jede Änderung ist dadurch ein nachvollziehbarer Commit und lässt sich zurückdrehen.
3. Pflege per Prompt (Beispiele)
> routine
Service-Routine
Befunde:
- Drift: zusammenfassung Pass-Rate 72% (n=40)
Automatisch erledigt:
- P-12: Skill zusammenfassung auf Stufe 0 zurückstufen → Skill zusammenfassung auf Stufe 0 zurückgestuft
Offene Vorschläge (genehmige P-x / lehne P-x ab):
- P-13 [low] LoRA-Adapter für rechnungen trainieren – 412 verifizierte Fälle, Stufe-1-Rate 86%
> genehmige P-13
P-13 executed: Kandidat 7f3e… (adapter) angelegt und Build gestartet
> wechsle tier1-general auf qwen3-32b-awq
Vorschlag P-14 [medium] Basismodell von tier1-general auf qwen3-32b-awq wechseln …
Bestätige mit „genehmige P-14“.
Freitext, der keinem Befehl entspricht, bildet ein kleines Modell auf einen Befehl ab. Der Agent fragt dann mit „Meinst du …?“ zurück.
4. Dry-Run aufheben (schrittweise)
- Eine Woche mit
KNASTER_DRY_RUN=truelaufen lassen. Die Healer-Ergebnisse stehen als[dry-run] …in den Antworten bzw. Logs. KNASTER_DRY_RUN=falsesetzen. Interne Aktionen (Slot-Status, Skill-Stufen, Kandidaten) liefen schon vorher. Jetzt werden auch Jobs per Webhook verschickt.- Infrastruktur-Aktionen einzeln freischalten, über
config/healer-rules.yaml→enabled_actions: [restart_container], späterrestart_vm.reboot_hostbleibt freigabepflichtig (Policy) und läuft nur im Wartungsfenster.
5. Rollback-Wege
| Was | Wie |
|---|---|
| Adapter/Basismodell | Prompt rollback <slot> → Freigabe |
| Skill-Stufe | Prompt stufe <skill> zurück bzw. Git-Revert der SKILL.md |
| Treiber/Engine | Proxmox-Snapshot der GPU-VM (vor jedem Update anlegen) |
| Konfiguration | Git-Revert und Neustart des Router-Containers |
6. Proxmox: Updates und Neustarts (rollierend, Knoten für Knoten)
Stand 12.10.2026, getestet mit dem Wartungsmodus auf pve44. Gilt für pve44, pve46, pve48, pve52 und pve61.
Wichtig vorab
- Auf den GPU-Knoten gehört die M4000 (Boot-Grafik) der VM. Nach dem frühen Start bleibt der lokale Bildschirm schwarz. Zugang nur per SSH oder Weboberfläche; das GRUB-Menü ist beim Start noch sichtbar (Notzugang: Eintrag bearbeiten,
initcall_blacklist=sysfb_initentfernen). - pve61 hängt am Netz nur über die USB-NIC im Dock. Neustart nur, wenn jemand vor Ort ist. Kommt er nach etwa 2 Minuten nicht zurück: Dock aus- und wieder einstecken.
- Nie zwei Knoten gleichzeitig. Mit 5 Stimmen bleibt das Quorum bei einem fehlenden Knoten erhalten.
Ablauf je Knoten
- Vorher:
pvecm status(Quorate: Yes),ha-manager status,pvesr status(alle Jobs OK). - Wartungsmodus:
ha-manager crm-command node-maintenance enable <knoten>. HA-Gäste ziehen um (infra: Test 36 s nach pve48). - GPU-VM des Knotens sauber stoppen:
qm shutdown <vmid>(244/246/248/252). Sie hat kein HA und kann nicht wandern (Passthrough). - Update:
platform/proxmox/scripts/bootstrap-node.sh <knoten>vom Laptop (idempotent, meldetNeustart nötig), dannreboot. - Nachher prüfen: Kernel,
systemctl --failed,ip -br a show vmbr0, NTP; auf GPU-Knotenlspci -nnk -d 10de:→ überallvfio-pci. - GPU-VM startet von selbst (
onboot). Danach auf ops:cd /root/cluster-knaster/platform/proxmox/tofu && . /root/.config/knaster/tofu.env && bash ../scripts/refresh-vm-access.sh(DHCP-Adressen können wechseln, Hostschlüssel kommen über den Gast-Agenten) undansible gpu_vms -m shell -a "nvidia-smi -L". - Wartungsmodus aus:
ha-manager crm-command node-maintenance disable <knoten>. HA holtinfraauf seinen Heimatknoten pve44 zurück (Test 41 s).
GPU-VMs aktualisieren
- Pakete per
aptin der VM, die NVIDIA-Pakete sind aufhold(R580). Vor Treiberwechseln einen Snapshot anlegen:qm snapshot <vmid> vor-treiber. - Nach einem VM-Neustart immer
refresh-vm-access.sh, solange es keine DHCP-Reservierungen gibt (D5).
7. Infra-Stack und Monitoring (LXC infra)
Stand 12.10.2026 (Task 5.2). Der LXC infra (vmid 101, HA, Heimat pve44, Replikation nach pve48/pve52) führt einen Compose-Stack knaster-infra: Router (Dry-Run), TTS (Piper), Postgres, Prometheus, Alertmanager, Grafana, pve-exporter, node-exporter, autoheal. Kein eigener LiteLLM (D4).
Adressen (DHCP, die IP kann sich nach einem Umzug ändern; aktuelle IP: ansible infra -m debug -a var=ansible_host auf ops oder refresh-vm-access.sh)
| Dienst | URL | Anmeldung |
|---|---|---|
| Grafana | http://<infra-IP>:3000 |
admin bzw. kiosk (Viewer) |
| Prometheus | http://<infra-IP>:9090 |
ohne (nur LAN) |
| Alertmanager | http://<infra-IP>:9093 |
ohne (nur LAN) |
| Router | http://<infra-IP>:8080 |
Bearer-Token |
Wo liegt was
- Konfiguration im Repo:
deploy/compose/infra,deploy/prometheus,deploy/alertmanager,deploy/grafana(Datasource, Dashboards). Im LXC als Kopie unter/opt/knaster/repo(wird bei jedem Ansible-Lauf abgeglichen, dort nichts ändern). - Geheimnisse nur im LXC, nie im Repo:
/opt/knaster/infra/.env(0600) mitPOSTGRES_PASSWORD,KNASTER_API_TOKEN,GRAFANA_ADMIN_PASSWORD,GRAFANA_KIOSK_PASSWORD(beim ersten Lauf mitopenssl randerzeugt, danach nie überschrieben). Lesen:ssh root@<infra-IP> grep ^GRAFANA_KIOSK_PASSWORD= /opt/knaster/infra/.env(für den Kiosk, Task 5.3). /opt/knaster/infra/secrets/router_token(Kopie vonKNASTER_API_TOKENfür den Alertmanager) undsecrets/pve-exporter.env(Kopie von ops/root/.config/knaster/pve-exporter.env, Tokenmonitoring@pve!prom, PVEAuditor).- Einstellungen ohne Geheimnis (Dry-Run,
LITELLM_BASE_URL…) stehen inplatform/proxmox/ansible/roles/infra-stack/defaults/main.ymlund werden bei jedem Lauf in die.envgeschrieben.
Ausrollen (auf ops, idempotent): cd /root/cluster-knaster && git pull, Adressen auffrischen (Abschnitt 6, Schritt 6), dann in platform/proxmox/ansible:
ansible-playbook playbooks/monitoring.yml– Exporter in den GPU-VMs (ohne Treiber-Rolle, kein Neustart) und Stack im LXC.- Ein Image-Update heißt: Tag im Compose-File ändern, committen, Playbook laufen lassen.
Ziele der GPU-VMs (file_sd) auffrischen
Die GPU-VMs haben DHCP-Adressen (D5). platform/proxmox/scripts/monitoring-targets.py schreibt aus tofu output -json gpu_vms und der Registry node.json und gpu.json (Labels instance = VM-Name, pve_node, vmid, slot, slots). Nach jedem VM-Neustart:
cd /root/cluster-knaster/platform/proxmox/tofu && . /root/.config/knaster/tofu.env && bash ../scripts/refresh-vm-access.sh
cd ../ansible && ansible-playbook playbooks/monitoring-targets.yml
Prometheus liest die Dateien in /opt/knaster/infra/file_sd selbst neu, ein Neustart ist nicht nötig.
Exporter in den GPU-VMs: prometheus-node-exporter (Port 9100, Ubuntu-Paket, liest /var/lib/node_exporter/textfile mit den Xid-Zählern) und nvidia_gpu_exporter (Port 9835, nvidia-smi; DCGM unterstützt Maxwell nicht). ufw-Regeln mit Kommentar knaster-monitoring erlauben beide Ports aus 192.168.100.0/24; ufw selbst wird von der Rolle nicht ein- oder ausgeschaltet.
Alerts: Alertmanager meldet an den Router (/v1/healer/alertmanager, Healer im Dry-Run). Der Receiver für n8n knaster-notify ist in deploy/alertmanager/alertmanager.yml nur vorbereitet (auskommentiert). Test: docker exec knaster-infra-alertmanager-1 amtool --alertmanager.url=http://localhost:9093 alert add test severity=warning und … alert query.
Dashboards (Ordner knaster, Startseite „knaster – Übersicht“): Proxmox via Prometheus (grafana.com 10347), Node Exporter Full (1860), Nvidia GPU Metrics (14574), knaster – Übersicht (eigenes).
Achtung HA-Umzug und ZFS-Seiten-Cache (gefunden 12.10.2026 bei der HA-Probe)
Nach zfs receive (Replikation) liefert ein Knoten für Dateien, die dort früher per mmap geöffnet waren, weiter den alten Inhalt aus seinem Seiten-Cache (ZFS 2.4.4, Kernel 7.0.14; Beleg auf pve44: zfs diff <snap> leer, written 0, md5 der Datei trotzdem ungleich der im Snapshot). Folge beim ersten Umzug nach pve48: dockerd las veraltete bbolt-Datenbanken, brach mit panic: invalid freelist page ab, danach fehlten Netzwerk und Volume-Labels. Betroffen ist jeder replizierte LXC mit mmap-Nutzern (Docker, Prometheus-TSDB, später grp-test), sobald er auf einen Knoten zurückkehrt, auf dem er schon lief.
- Schutz im Container: Dienst
knaster-drop-stale-cache.service(Rolleinfra-stack) verwirft vor containerd/docker perposix_fadvise(DONTNEED)den Cache aller Dateien des Containers. Protokoll:journalctl -u knaster-drop-stale-cache -b(zeigt geänderte Datenbank-Prüfsummen). - Eine Lösung auf den Knoten (OpenZFS-Fehler melden bzw. Update, Hookscript) entscheidet der Nutzer.
Wiederherstellung, falls Docker nach einem Umzug nicht startet (im LXC, nichts löschen):
systemctl stop docker containerd;journalctl -u docker -b | grep -A12 paniczeigt die betroffene Datenbank (z. B.buildkit/cache.db).- Die defekte Datenbank bzw. das Verzeichnis beiseiteschieben, z. B.
mv /var/lib/docker/buildkit /var/lib/docker/buildkit.defekt-<datum>. systemctl start docker, danndocker 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, keindown -v).- 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; Passwort, TOTP und Recovery-Keys in Password Depot (Datei tfa-r.rapp.txt am 13.10. gelöscht) |
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: liegt in Password Depot (Feld „Einmalpasswort / 2FA“). Für neue Konten schreibt
pve-admin-user.sheine Dateitfa-<name>.txt; Secret und Recovery-Keys daraus in Password Depot übernehmen und die Datei löschen. - Anmeldung und Vertretung:
docs/ANMELDUNG.md(auch Browser-Falle: Bitwarden-Leiste blockiert den TOTP-Dialog, Inkognito oder Domain ausschließen). - Neues Admin-Konto: Name in
access.admin_userseintragen,playbooks/cluster.ymlauf ops, dann vom Laptopplatform/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/testauf einem Knoten, Zustellung im Journal:journalctl -u postfix --since -10min | grep status=. - Landet die Mail im Spam: Absender
root@pveXX.buero-godel.localhat kein SPF. Dann in Exchange Online eine Transportregel oder einen Connector für die Knoten-IPs anlegen. - Empfänger ändern:
access.mail_toin der Site-Datei, dannpvesh 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(WLAN) und.181(USB-LAN im Dock), 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änztmanagementimmer um das lokale Netz (local_network, hier das ganze /24). Eine Einschränkung auf einzelne Adressen wirkt deshalb nur mit ACCEPT für+adminund 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): Seit 14.10. haben ops (.173) und infra (.188) feste Adressen (infra über
containers.infra.ipin der Site-Datei und tofu, ops perpct set 100 -net0 …ip=…auf pve46; DNS .120, Suchdomäne buero-godel.local). Am DC sind sie noch nicht reserviert, der Support soll die Reservierungen nachziehen (Task 0.2). Nur der Laptop (WLAN .151, Dock .181) hängt noch am Lease. 14.10. passiert: Laptop kam per Dock mit .181 und war ausgesperrt, Rückweg über ops hat funktioniert. Wechselt eine Adresse, ist diese Quelle ausgesperrt. Rückweg: von einer noch zugelassenen Adresse (z. B.ssh ops, dannssh pve44) die Adresse insites/knaster/proxmox.yamländern und das Playbook laufen lassen, oder direktcluster.fwbearbeiten. Letzter Rückweg: Konsole am Knoten, dortpve-firewall stopbzw.enable: 0incluster.fw. - Totmannschalter: Das Playbook stellt bei jeder Änderung einen Timer (
knaster-fw-totmann, 600 s), derenable: 0schreibt, 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-256A2:71:C0:AB:…:77:3E, zum Abgleichopenssl 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 offals bekannter Ausweg, dann in/etc/network/interfacesfesthalten. - VLAN: nicht aktiviert (Global Constraint „vorerst kein VLAN“). Wenn nötig:
bridge-vlan-aware yesundbridge-vids 2-4094aufvmbr0,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:
- Nach jedem Playbook-Lauf gegen die Knoten (
site.yml,cluster.yml) und nach jedem Neustart (Abschnitt 6, Schritt 5). - Vor einer Änderung an Firewall, Benutzern oder Netzwerk als Vergleichsbasis.
- 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).