11 KiB
11 KiB
checkbot
Checkmk-Bot für Debian-LXC (Proxmox). Überwacht Checkmk per REST-API, lässt Alarme von externem Ollama analysieren, meldet in Telegram und/oder Element (Matrix). Konfiguration komplett über Web-UI.
Vollständiger Plan: /home/sysops/.claude/plans/ja-alle-bernehmen-eager-lark.md
Arbeitsregeln
- Auf diesem Rechner wird nichts installiert (kein venv, kein pip, keine Pakete). Code nur schreiben, Ausführung und Tests passieren im Ziel-LXC.
- Stand: Phase 1 bis 5 als Code, Phase 7 als Dateien geschrieben, nichts ausgeführt oder getestet (siehe README-Statustabelle).
- Code-Kommentare nur bei echtem WHY.
Festgelegte Entscheidungen
- Plattform: Debian-LXC, unprivileged, 1 Core, 1 GB RAM, Python 3, venv im LXC, systemd, Caddy (HTTPS, interne CA). Kein Docker.
- Checkmk 2.3+: nur REST-API (Automation-User, Lese-Rolle). Kein Webhook, kein Notification-Script, kein eingehender Alarm-Port.
- Poller: 30 s (UI einstellbar), nur Nicht-OK, Zustandsvergleich in SQLite, nur Hard-States, Mindestdauer einstellbar (Default 0 s), Flapping gebündelt.
- Ollama extern
office.sysops.de:11434. Zwei Modell-Einstellungen (Alarmtext, Agent), Startqwen3, Hermes zum Vergleich. - Chat: Adapter-Interface. Telegram (Long-Polling) und Matrix (direkt über die Client-Server-API mit
httpx, bewusst nichtmatrix-nio: kein libolm/E2EE nötig; eigener Homeserver, unverschlüsselter Raum, Bot-User mit Access-Token). Parallel, einzeln abschaltbar, Ziel pro Routing-Regel. - Alarm-Flow: Rohalarm sofort, KI-Analyse per Edit nachgereicht (Telegram editMessage, Matrix m.replace). Max 8 Zeilen DE. Timeout 60 s, 2 Retries, sonst "KI nicht verfügbar". Bündelung pro Host 60 s, max 10 Prompts/min, Recovery ohne KI. Downtime: kein Push, Verlauf "unterdrückt". UI-Stummschaltung mit Ablauf.
- Befehle: gemeinsamer Handler,
/in Telegram,!in Matrix, Allowlist pro Backend. - Agent-Loop nur für
/ask,/explain, Tiefenanalyse. 5 feste Lese-Tools (get_service_status,get_host_services,get_state_history,get_downtimes,get_problems), max 6 Schritte, 90 s, Tool-Output untrusted, alle Aufrufe im Audit-Log. - Bot liest Checkmk standardmäßig nur (Automation-User mit Lese-Rolle). Einzige Schreibaktion: Downtime setzen, siehe nächster Punkt.
- Ruhigstellen per Chat (
/muteund/downtimein Telegram,!muteund!downtimein Matrix):- A,
mute: Bot-lokale Stummschaltung mit Dauer, Checkmk bleibt unberührt. Standard. Alarme bieten Buttons "2 h stumm" (Telegram Inline-Buttons, Matrix:!mute 2hals Antwort auf die Alarmnachricht). - B,
downtime: echte Checkmk-Downtime per REST (POST /domain-types/downtime/collections/service, Endpunkt noch gegen echte Instanz prüfen). Eigener Checkmk-User nur mit Downtime-Recht, Secret getrennt vom Lese-User. In der UI abschaltbar, standardmäßig aus, maximale Dauer einstellbar (z.B. 24 h). - B nur durch Allowlist-User nach Bestätigung (Host, Service, Dauer, Kommentar anzeigen, dann Button bzw.
ja). Agent und Modell haben keine Schreib-Tools und lösen B nie aus. - Jede Aktion im Audit-Log: User, Backend, Host, Service, Dauer.
- A,
- UI: FastAPI, Jinja2, HTMX, deutsch, hell/dunkel. Lokale Nutzer (Argon2, optional TOTP), Rollen admin/viewer,
checkbot create-admin, Setup-Assistent. - Secrets in SQLite mit AES-GCM. Nur
master.key, Session-Secret, Bind-Adresse in/etc/checkbot/(chmod 600). UI zeigt Secrets nie an. - Audit-Log ohne Secret-Werte. Prompts versioniert mit Rollback, Testbereich.
- Retention: Verlauf/KI 90 Tage, Audit 1 Jahr.
/healthplus Checkmk-Agent im LXC. - Plugin-Output ist untrusted Input (Prompt Injection), KI löst keine Aktionen aus.
Phasen
- Gerüst: Schema,
crypto.py, Checkmk- und Ollama-Client,/health - UI-Basis: Login, Rollen, Setup-Assistent, Verbindungstests, Audit
- Chat-Interface, Telegram, Poller, Alarm-Flow
- Matrix-Adapter, Routing, Stummschaltung (UI)
- Command-Handler (inkl.
mute,downtimemit Bestätigung), Agent-Loop - Prompt-Versionierung, Testbereich, Verlauf, Retention
- Deployment (
setup-lxc.sh, Caddy, systemd, Checkmk-Agent) - Tests
Geplante Struktur
app/ main.py fileconfig.py db.py models.py crypto.py checkmk.py poller.py
ollama.py pipeline.py agent.py tools.py commands.py audit.py
retention.py health.py chat/{base,telegram,matrix}.py web/
deploy/ setup-lxc.sh systemd/checkbot.service Caddyfile
tests/
Fortschritt Phase 5b (ungetestet)
- Neu:
app/listeners/(Telegram-getUpdates, Matrix-/sync, Backoff, Offset/Since in Tabellelistener_state),app/downtime/(Client, Bestätigungs-Store, Service),app/agent_runs/(Recorder, Tabelleagent_runs, AgentService),app/commands/{mutecmd,downtimecmd,callbacks,...},app/alerts/extras.py(Buttons/Hinweis),app/chatops.py(Verdrahtung), UI/agentund Sectioncheckmk_dt. - Annahmen Telegram:
getUpdatesmitallowed_updates=[message, callback_query], Long-Poll 30 s; erster Start überspringt den Rückstand peroffset=-1;editMessageTextohnereply_markupwürde die Buttons entfernen, daher wird es beim Edit mitgegeben;callback_datamax. 64 Byte (mute:<alert_id>:<min>,deep:<id>,dt:<id>:<min>,dty:<token>,dtn:<token>). - Annahmen Matrix:
/syncmit Filter (nur Raum, nurm.room.message);next_batchwird vor der Verarbeitung gespeichert (höchstens einmal); Edits (m.replace) undm.noticewerden ignoriert; Reply perm.relates_to.m.in_reply_to. - Annahmen Checkmk:
POST /domain-types/downtime/collections/servicemitdowntime_type=service,host_name,service_descriptions,start_time/end_time(ISO 8601 UTC,Z),comment; Erfolg ist 204. Noch gegen eine echte Instanz prüfen. - Alarm-Buttons nur bei Einzelalarmen (nicht Recovery, nicht gebündelt); Reply-Auflösung bei mehreren Services in einer Nachricht lehnt ab und nennt die explizite Form.
Phase 7 Deployment (Dateien unter deploy/, ungetestet, Details in deploy/README.md)
- Genau ein uvicorn-Worker: Rate-Limiter, TOTP-Einrichtung und Downtime-Bestätigungen liegen im Prozessspeicher, außerdem liefe der Poller doppelt. Bind-Adresse und Port kommen aus
checkbot.env(Unit nutzt${CHECKBOT_BIND_*}), Caddy-Upstream wird daraus gerendert. - Caddy-Modi:
internal(Caddy-CA, Root-Zertifikat muss verteilt werden) oderfiles(Zertifikat der Unternehmens-CA nach/etc/caddy/certs). Zugriffslog ohne Query, Authorization, Cookie. /healthüber Caddy nur von 127.0.0.1 undCHECKBOT_MONITOR_IP(Detailtexte intern), sonst 403./healthliefert 503, solange ein Teilcheck nicht ok ist, auch bei "nicht konfiguriert".- Local Check: "nicht konfiguriert" ergibt WARN, "deaktiviert" (Telegram/Matrix fehlen im JSON) OK, Fehler/Bot nicht erreichbar CRIT.
master.keywird nie mit der DB gesichert. Schlüssel erzeugtsetup-lxc.shals root und übergibt sie ancheckbot(das Konfigurationsverzeichnis ist fürcheckbotnur lesbar).- Unprivilegierte LXCs: Drop-In
checkbot-lxc-relaxed.conf(setup-lxc.sh --lxc-relaxed).
Weiterer Weg (entschieden)
Reihenfolge: Testbasis, erster Lauf im Test-LXC (pytest), Korrekturrunde, Phase 6, Phase 6b, Phase 6c, Phase 8, Abnahme, Parallelbetrieb, Tag v0.1.0. Verfeinerungen passieren am Live-System, nicht vorab.
- Testbasis:
pytestmanuell im Test-LXC (Dev-venv mitrequirements-dev.txt), dazu.gitea/workflows/test.ymlfür einen späteren Gitea-Actions-Runner. Logging als Zeilenlog nach journald, Level überCHECKBOT_LOG_LEVEL(Default INFO), nie Secrets in Logs (Test für die Adapter). Zeitzone überCHECKBOT_TZim Setup-Skript, DefaultEurope/Berlin. - Phase 6: Alarm- und Agenten-Prompt versioniert mit Rollback und Testbereich; der Schutzhinweis gegen Prompt Injection wird immer fest angehängt und ist nicht editierbar. Retention einstellbar: Alarmverlauf/Zustellungen 90 Tage, Agenten-Läufe 90 Tage,
state_log30 Tage, Audit 1 Jahr, abgelaufene Mutes 7 Tage, tägliches Aufräumen mit Log der gelöschten Zeilen. Erinnerungen für offene CRIT-Probleme, Standard aus, nicht bei Downtime/Mute. - Phase 6b (Trigger-Regeln, Routing-Seite wird "Regeln"): Zusatzfelder pro Regel: KI-Hinweistext (nur Zusatzkontext hinter dem festen Schutzhinweis), KI an/aus, Erinnerungsintervall (nur CRIT), laut/leise (Telegram
disable_notification). Zusatzbedingungen: Plugin-Output enthält Text (Teilstring, keine Regex wegen ReDoS) und Mindestdauer in Minuten. Keine Checkmk-Labels/Tags. Beispiel: Service*zpool*, ab WARN, eigener Raum, eigener KI-Hinweis. - Phase 6c (Betriebsrobustheit, nach 6b, vor 8):
- Baseline beim Erstlauf: Zustand still merken, eine Zusammenfassung ohne KI (Anzahl, 10 kritischste); Button in der UI setzt die Baseline neu.
- Bestätigte Probleme (Acknowledged in Checkmk) werden mit Grund "bestätigt" unterdrückt, bei Verschlechterung wieder gemeldet. Regel für alle Unterdrückungen: Recovery nur, wenn das Problem vorher gemeldet wurde.
- Host-Alarme: Hosts mitabfragen, "Host DOWN" als eigener Alarm, Service-Alarme des Hosts mit Grund "Host down" unterdrücken, Recovery bei Rückkehr.
- Checkmk nicht erreichbar: nach 3 Fehlzyklen eine Meldung "Checkmk nicht erreichbar seit HH:MM" an die Standardziele, bei Rückkehr eine zweite; währenddessen keine Recoveries.
- Sendelimit 15 Nachrichten pro Minute und Ziel, Überschuss als Sammelmeldung pro Minute, alles bleibt im Verlauf.
- Datenschutz pro Ziel: Inhalt voll oder kurz (nur Host, Service, Status, ohne Plugin-Output und KI-Text), Standard voll, Entscheidung am Live-System.
- Optionale
ui.base_url: Alarme enthalten Link "Details" auf den Verlauf (Telegram-Button, Matrix-Text), nur wenn gesetzt.
- Aktionen: Der Bot führt nie Shell-Befehle aus (weder lokal noch per SSH). Webhook pro Regel (POST JSON an Allowlist-URLs, Audit) kommt erst nach der Abnahme.
- Phase 8: Integrationstests mit Marker
integration(pytest -m integration), Zugangsdaten per Umgebung, nur lesend; Downtime nur mit ausdrücklichem Flag und gegen einen Testhost. Testhostcheckbot-testin Checkmk mit schaltbarem lokalem Check plus halbautomatischestests/e2e/run.py. - Abnahme (
docs/ACCEPTANCE.md): CRIT in Telegram und Element, KI-Analyse binnen 90 s, Recovery ohne KI, Downtime undmuteunterdrücken, Ollama aus ergibt Rohalarm mit "KI nicht verfügbar", Neustart ohne Doppelalarme, Backup und Restore real getestet,/healthim Checkmk grün, Baseline-Zusammenfassung beim Erstlauf, Host-down unterdrückt Service-Alarme, Meldung bei Checkmk-Ausfall, 24 h Dauerlauf ohne Fehler im Journal. - Einführung: erste Woche nur Testziele (separate Gruppe/Raum) per Routing-Regel, danach auf Produktivziele umschalten. Release: Tag
v0.1.0und kurzeCHANGELOG.md. - Bewusst nicht enthalten: Ack, mehrere Checkmk-Sites, weitere Kanäle (Mail/Slack), E2EE in Matrix.