diff --git a/knowledge/fixes.json b/knowledge/fixes.json new file mode 100644 index 0000000..c5a4610 --- /dev/null +++ b/knowledge/fixes.json @@ -0,0 +1,1014 @@ +[ + { + "id": "fix-001", + "date": "2026-04-13", + "system": "proxmox", + "host": "192.168.178.10", + "component": "cloudflared", + "severity": "critical", + "title": "Cloudflare Tunnel 530 — QUIC-Timeouts, Tunnel nicht erreichbar", + "symptoms": [ + "Browser zeigt: 530 The origin has been unregistered from Argo Tunnel", + "cloudflared logs: 'failed to dial to edge with quic: timeout: no recent network activity'", + "Tunnel verbindet sich kurz (Registered), bricht dann sofort wieder ab", + "Betrifft alle Subdomains des Tunnels", + "Alle 4 connIndex fallen nacheinander aus" + ], + "root_cause": "UDP Port 7844 (QUIC-Protokoll) wird vom NAT-Router oder einer Firewall gedroppt. cloudflared wählt standardmäßig QUIC, scheitert nach kurzer Idle-Zeit, reconnectet dauerhaft — 530-Fehler für Endnutzer.", + "fix": { + "steps": [ + "1. SSH auf cloudflared-Host", + "2. /etc/systemd/system/cloudflared.service öffnen", + "3. In ExecStart: '--protocol http2' vor 'tunnel run' einfügen", + "4. systemctl daemon-reload && systemctl restart cloudflared", + "5. Verify: journalctl -u cloudflared -n 5 | grep 'Registered' → alle connIndex zeigen protocol=http2" + ] + }, + "prevention": "Bei jeder neuen cloudflared-Installation in NAT/Home-Lab-Umgebung sofort --protocol http2 setzen." + }, + { + "id": "fix-002", + "date": "2026-04-13", + "system": "proxmox", + "host": "192.168.178.10", + "component": "pvestatd", + "severity": "critical", + "title": "pvestatd D-State — Proxmox GUI Graphs leer, CT/VM-Status fehlt", + "symptoms": [ + "Proxmox GUI: alle Graphs leer (CPU, Memory, Network, Disk IO)", + "CT/LXC/VM-Status-Icons fehlen oder zeigen falsche Farbe", + "API /nodes/pve/lxc/{id}/rrddata gibt nur 'time' zurück, keine Metriken", + "'systemctl restart pvestatd' schlägt fehl mit: 'can't acquire lock'", + "Prozesszustand 'Ds' (D=uninterruptible sleep)", + "SIGKILL hat keine Wirkung" + ], + "root_cause": "pvestatd-Prozess gerät in D-State beim Kernel-Aufruf free_pgtables. Tritt auf bei hoher I/O-Last (z.B. während Backup). SIGKILL kann D-State-Prozesse nicht beenden.", + "fix": { + "steps": [ + "1. Stuck PID finden: pid=$(pgrep pvestatd | head -1)", + "2. Prozess aus Cgroup verschieben: echo $pid > /sys/fs/cgroup/cgroup.procs", + "3. Lock-Files entfernen: rm -f /var/run/pvestatd.pid.lock /var/run/pvestatd.pid", + "4. Service reset + start: systemctl reset-failed pvestatd && systemctl start pvestatd" + ], + "note": "Echter Fix nur via Reboot. Cgroup-Trick ermöglicht neuen pvestatd-Start ohne Reboot." + }, + "prevention": "Reboot des Proxmox-Hosts nach schweren Backup-Windows empfohlen." + }, + { + "id": "fix-003", + "date": "2026-04-13", + "system": "proxmox", + "host": "192.168.178.10 (VM 123)", + "component": "opnsense-disk", + "severity": "warning", + "title": "OPNsense Disk >75% — automatisches Log-Cleanup erforderlich", + "symptoms": [ + "Disk-Nutzung nahe dem Limit", + "OPNsense Web UI zeigt Warnung über Speicherplatz" + ], + "root_cause": "OPNsense akkumuliert Suricata JSON-Logs, filterlog, dnsmasq-Logs, pkg-Cache und temporäre Dateien.", + "fix": { + "steps": [ + "1. Alte Logs: find /var/log -name '*.log' -mtime +7 -delete", + "2. Suricata: find /var/log/suricata -name '*.json' -mtime +3 -delete", + "3. Temp: find /tmp /var/tmp -mtime +1 -delete", + "4. Pkg-Cache: pkg clean -y" + ] + }, + "prevention": "Automatisches Cleanup-Script als cron einrichten wenn Disk >75%." + }, + { + "id": "fix-004", + "date": "2026-04-13", + "system": "proxmox", + "host": "192.168.178.10", + "component": "swap", + "severity": "warning", + "title": "Swap 77% voll trotz 73% freiem RAM — Swappiness zu hoch", + "symptoms": [ + "SWAP usage 77% bei nur 28% RAM-Nutzung", + "Prozesse wurden bei früherer Last ausgelagert und nicht zurückgeholt" + ], + "root_cause": "Linux Standard-Swappiness von 60 lagert Pages aus auch wenn RAM verfügbar. Bei 62GB RAM zu aggressiv.", + "fix": { + "immediate": "swapoff -a && swapon -a (nur wenn RAM < 50%)", + "permanent": "echo 'vm.swappiness=10' >> /etc/sysctl.conf && sysctl vm.swappiness=10" + }, + "prevention": "vm.swappiness=10 auf allen Servern mit >16GB RAM setzen." + }, + { + "id": "fix-005", + "date": "2026-04-13", + "system": "proxmox", + "host": "192.168.178.10", + "component": "backup-load", + "severity": "info", + "title": "Proxmox Backup verursacht extrem hohe Load — Kaskaden-Effekt", + "symptoms": [ + "Load Average 60+ auf 22-CPU System", + "SSH extrem langsam", + "pvestatd und andere Services gehen in D-State" + ], + "root_cause": "vzdump ohne I/O-Limit liest/schreibt massiv auf Disk. Kaskadiert mit Tunnel-Reconnect und D-State-Prozessen.", + "fix": { + "permanent": [ + "bwlimit: 50000 in /etc/vzdump.conf", + "ionice: 7 (idle I/O priority)", + "Kompression: lzo statt gzip", + "Backup-Zeiten auf Nacht verschieben" + ] + }, + "prevention": "vzdump.conf: ionice: 7 und bwlimit setzen. Backups in Maintenance-Fenster." + }, + { + "id": "fix-006", + "date": "2026-04-13", + "system": "ctxevent", + "host": "82.165.222.127", + "component": "database-auth", + "severity": "critical", + "title": "Production Login komplett kaputt — falscher DB-User in DATABASE_URL", + "symptoms": [ + "Admin und Participant login: Internal server error", + "Fehler: SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string" + ], + "root_cause": "DATABASE_URL enthielt falschen PostgreSQL-User (renefichtmueller statt ctxmeet). PrismaPg/SCRAM-SHA-256 erfordert zwingend Passwort-String.", + "fix": { + "steps": [ + "1. PostgreSQL-Rollen prüfen: sudo -u postgres psql -c '\\du'", + "2. Korrekten User mit Passwort in DATABASE_URL: postgresql://ctxmeet:@localhost:5432/ctxmeet", + "3. PM2 restart mit --update-env Flag" + ] + }, + "prevention": "DATABASE_URL IMMER mit Passwort setzen. Korrekte DB-User dokumentieren." + }, + { + "id": "fix-007", + "date": "2026-04-13", + "system": "ctxevent", + "host": "82.165.222.127", + "component": "prisma-schema", + "severity": "critical", + "title": "Prisma Schema Drift — migrate status sagt 'up to date' aber Spalten fehlen physisch", + "symptoms": [ + "'prisma migrate status' zeigt 'up to date'", + "Spalten fehlen: twoFactorFailCount, twoFactorLockedUntil, recoveryCodesHash", + "Fehler: P2022: The column does not exist" + ], + "root_cause": "Migrationen als 'applied' markiert, aber SQL nie korrekt ausgeführt. prisma migrate status lügt.", + "fix": { + "steps": [ + "1. Echten DB-Stand prüfen: \\d 'TableName' in psql", + "2. Force-Push Schema: npx prisma db push", + "3. Clean rebuild: rm -rf .next && npx prisma generate && npm run build" + ] + }, + "prevention": "IMMER echten DB-Stand mit \\d verifizieren, nicht nur prisma migrate status." + }, + { + "id": "fix-008", + "date": "2026-04-13", + "system": "ctxevent", + "host": "82.165.222.127", + "component": "table-ownership", + "severity": "high", + "title": "PostgreSQL Table Ownership falsch — prisma db push scheitert", + "symptoms": [ + "prisma db push: permission denied for table", + "Tabellen gehören 'postgres' statt App-User" + ], + "root_cause": "Tabellen von postgres Superuser erstellt. App-User hat keine ALTER-Rechte.", + "fix": { + "sql": "DO $$ DECLARE r RECORD; BEGIN FOR r IN SELECT tablename FROM pg_tables WHERE schemaname='public' AND tableowner != 'ctxmeet' LOOP EXECUTE format('ALTER TABLE %I OWNER TO ctxmeet', r.tablename); END LOOP; END $$;" + }, + "prevention": "Alle DB-Operationen immer als App-User, nie als postgres." + }, + { + "id": "fix-009", + "date": "2026-04-13", + "system": "ctxevent", + "host": "82.165.222.127", + "component": "pm2-env", + "severity": "high", + "title": "PM2 verwendet gecachte alte Umgebungsvariablen nach .env Änderung", + "symptoms": [ + "Neuer .env Wert wird ignoriert", + "App-Verhalten passt nicht zu .env" + ], + "root_cause": "PM2 cached Umgebungsvariablen beim ersten Start. Ohne --update-env werden Änderungen ignoriert.", + "fix": { + "command": "pm2 restart --update-env" + }, + "prevention": "IMMER --update-env bei pm2 restart verwenden." + }, + { + "id": "fix-010", + "date": "2026-04-13", + "system": "erik-server", + "host": "82.165.222.127", + "component": "sshd", + "severity": "critical", + "title": "Erik SSH komplett down — fehlerhafte sshd_config + fehlendes /run/sshd", + "symptoms": [ + "SSH Port 22: Connection refused", + "sshd -t: 'no argument after keyword'" + ], + "root_cause": "Fehlerhafte Zeile in sshd_config (Copy-Paste Unfall) + fehlender /run/sshd Ordner.", + "fix": { + "steps": [ + "1. IONOS VNC Console nutzen (direkte noVNC URL, nicht iframe)", + "2. Fehlerhafte Zeile entfernen: sed -i 'Nd' /etc/ssh/sshd_config", + "3. mkdir -p /run/sshd", + "4. sshd -t (Config testen)", + "5. systemctl start ssh", + "6. Permanent: echo 'd /run/sshd 0755 root root -' > /etc/tmpfiles.d/sshd.conf" + ] + }, + "prevention": "IMMER sshd -t vor restart. /run/sshd in tmpfiles.d. Min. 2 SSH-Pfade zu jedem Server." + }, + { + "id": "fix-011", + "date": "2026-04-13", + "system": "network", + "host": "192.168.178.2", + "component": "cisco-stp", + "severity": "high", + "title": "Cisco SG350 STP Loop — 171ms Latenz durch FritzBox BPDU-Reflexion", + "symptoms": [ + "GE2 cycling LOOPBACKDET alle 30s", + "MAC-Tabelle flusht", + "171ms interne Latenz" + ], + "root_cause": "FritzBox reflektiert BPDUs → Switch erkennt eigene BPDUs als Loop → Port deaktiviert → MAC flush.", + "fix": { + "action": "spanning-tree disable auf GE2 (FritzBox Uplink)" + }, + "prevention": "Bei Consumer-Router-Uplinks STP IMMER deaktivieren." + }, + { + "id": "fix-012", + "date": "2026-04-13", + "system": "network", + "host": "192.168.178.2", + "component": "vlan-starlink", + "severity": "high", + "title": "Starlink CGNAT flooding LAN ohne VLAN-Isolation", + "symptoms": [ + "100.64.x.x Adressen im LAN", + "DHCP-Konflikte", + "Falsche Default Routes" + ], + "root_cause": "Starlink ohne VLAN sendet CGNAT DHCP ins Management-LAN.", + "fix": { + "steps": [ + "1. VLAN anlegen: vlan 30 name Starlink-WAN (eine Zeile!)", + "2. GE12 als Access auf VLAN 30", + "3. STP auf GE12 deaktivieren" + ], + "note": "Cisco SG350 VLAN Syntax: 'vlan X name Y' in EINER Zeile" + }, + "prevention": "Starlink IMMER in dediziertes VLAN." + }, + { + "id": "fix-013", + "date": "2026-04-13", + "system": "network", + "host": "192.168.178.3", + "component": "aruba-reset", + "severity": "warning", + "title": "Aruba 1830 Factory Reset Falle — Switch nach Reset unerreichbar", + "symptoms": [ + "Kein Ping, HTTP, SSH nach Factory Reset", + "L2-Forwarding funktioniert aber Management nicht" + ], + "root_cause": "Factory Reset setzt Aruba in Cloud-Provisioning-Modus. Lokales Management erst nach Cloud-Registrierung.", + "fix": { + "action": "Cloud Portal → portal.instant-on.hpe.com → Add Device → Serial", + "warning": "NIE Factory Reset zur Lösung von Login-Problemen" + }, + "prevention": "Aruba nie per Factory Reset troubleshooten." + }, + { + "id": "fix-014", + "date": "2026-04-13", + "system": "opnsense", + "host": "192.168.178.11", + "component": "config-restore", + "severity": "critical", + "title": "OPNsense config.xml nach blindem Revert kaputt", + "symptoms": [ + "WAN auf falschem vtnet Interface", + "DHCP auf falschem Subnet", + "Kein Internet" + ], + "root_cause": "Blinder Revert auf alte Config hat falsche Interface-Zuordnung und falsches Subnet.", + "fix": { + "steps": [ + "1. VM stoppen", + "2. LVM-Disk mounten (UFS2)", + "3. config.xml.bak (letzte gute Config) als config.xml verwenden", + "4. Interface-Zuordnungen verifizieren (vtnet0=LAN, vtnet1=WAN)", + "5. Unmount + VM starten" + ] + }, + "prevention": "VOR jedem Revert die .bak Datei inspizieren. Interfaces verifizieren." + }, + { + "id": "fix-015", + "date": "2026-04-13", + "system": "opnsense", + "host": "192.168.178.11", + "component": "boot-issues", + "severity": "high", + "title": "OPNsense Boot-Probleme — LAN Route, SSH, pf Blocking", + "symptoms": [ + "LAN-Zugang fehlt nach Boot", + "SSH nicht erreichbar", + "Web UI geblockt" + ], + "root_cause": "Drei Boot-Probleme: LAN-Route fehlt, SSH noauto=1, pf blockiert.", + "fix": { + "steps": [ + "1. configctl interface reconfigure lan", + "2. SSH: noauto=0 in config.xml", + "3. pf: pfctl -d && configctl filter reload" + ] + }, + "prevention": "SSH autostart auf noauto=0. LAN-Route in Monitoring." + }, + { + "id": "fix-016", + "date": "2026-04-13", + "system": "peercortex", + "host": "82.165.222.127", + "component": "cache-null", + "severity": "high", + "title": "Null-Cache Bug — fehlgeschlagene API-Responses 15min gecacht", + "symptoms": [ + "ASN-Lookup zeigt 0 Neighbours/Prefixes", + "Werte bleiben 15min auf 0" + ], + "root_cause": "Fehlgeschlagene RIPE Stat Responses (null) wurden gecacht.", + "fix": { + "rule": "NIEMALS null-Responses cachen: if (result !== null) cache.set(key, result)" + }, + "prevention": "Cache-Implementierung muss null/error explizit ausschließen." + }, + { + "id": "fix-017", + "date": "2026-04-13", + "system": "peercortex", + "host": "82.165.222.127", + "component": "api-timeout", + "severity": "high", + "title": "RIPE Stat Timeout zu kurz für Tier-1 Carrier", + "symptoms": [ + "Lookups für AS174 (Cogent) etc. geben leere Ergebnisse", + "Timeout nach 30s" + ], + "root_cause": "30s Timeout zu kurz für Tier-1 mit 5000+ Neighbours.", + "fix": { + "change": "Timeout von 30s auf 45s erhöhen" + }, + "prevention": "API-Timeouts nach Worst-Case kalibrieren." + }, + { + "id": "fix-018", + "date": "2026-04-13", + "system": "peercortex", + "host": "82.165.222.127", + "component": "api-ratelimit", + "severity": "high", + "title": "PeeringDB/RIPE Stat Rate-Limit Flood ohne Concurrency-Kontrolle", + "symptoms": [ + "HTTP 429 Too Many Requests", + "Hunderte parallele Requests" + ], + "root_cause": "Kein Concurrency-Limit auf externe API-Calls.", + "fix": { + "steps": [ + "Semaphore PeeringDB: max 5 concurrent", + "Semaphore RIPE Stat: max 15 concurrent", + "Retry mit Backoff bei 429" + ] + }, + "prevention": "IMMER Semaphore auf externe API-Calls. Standard: 5-15." + }, + { + "id": "fix-019", + "date": "2026-04-13", + "system": "peercortex", + "host": "82.165.222.127", + "component": "css-injection", + "severity": "warning", + "title": "CSS SyntaxError — Multiline CSS in JavaScript-String", + "symptoms": [ + "SyntaxError im CSS-Parser", + "Styles nicht korrekt" + ], + "root_cause": "CSS als JS-String statt in