{
"meta": {
"title": "Architektur von ProxMenux Monitor — AppImage, Flask, SQLite, WebSocket | ProxMenux",
"description": "Aufbau von ProxMenux Monitor: AppImage-Struktur, Flask-Blueprints, Hintergrundaufgaben, Daten aus psutil, pvesh, smartctl und journalctl, SQLite-Speicherung, WebSocket-Terminal, KI-Anbieter, Benachrichtigungskanäle, Reverse-Proxy und optionales Fail2Ban.",
"ogTitle": "ProxMenux Monitor Architektur",
"ogDescription": "ProxMenux Monitor intern: AppImage, Flask-Blueprints, Hintergrundaufgaben, SQLite, WebSocket, KI-Anbieter und Benachrichtigungskanäle.",
"twitterTitle": "ProxMenux Monitor Architektur",
"twitterDescription": "AppImage, Flask, SQLite, WebSocket, KI-Anbieter und Benachrichtigungskanäle — innerhalb des Monitors."
},
"header": {
"title": "Architektur",
"description": "Wie ProxMenux Monitor ausgeliefert wird, was das AppImage enthält und wie Browseranfragen über Flask zu Host-Werkzeugen und SQLite gelangen.",
"section": "ProxMenux Monitor"
},
"intro": {
"title": "Ein Prozess, viele Verantwortlichkeiten",
"body": "Ein Python-Prozess lauscht auf TCP 8008. Er liefert den statischen Next.js-Build aus, stellt die REST-API bereit, verwaltet das WebSocket-Terminal, führt den Health Monitor aus und versendet Meldungen. Ein separater Webserver, Nachrichtenbroker oder externer Datenbankserver ist nicht erforderlich."
},
"requestFlow": {
"heading": "Ablauf einer Anfrage",
"intro": "Eine typische Datenanfrage folgt diesem Weg; reine Browsereinstellungen können lokal bleiben:",
"diagramCaption": "Geschützte Routen prüfen JWT bei aktiver Authentifizierung. Kernrouten und Blueprints liefern zwischengespeicherte oder neu erfasste Host-Daten. Der optionale Fail2Ban-Hook prüft seine zwischengespeicherte Sperrliste. Weitergeleitete IP-Header gelten nur mit PROXMENUX_TRUST_PROXY=1; sonst zählt die Gegenstellenadresse. Dauerhafter Zustand liegt in SQLite und JSON-Dateien wie auth.json.",
"diagramArrowLabel": "HTTP / WS",
"nodes": {
"clientLabel": "Client",
"clientDetail": "Browser oder PWA\n+ optionaler Proxy\nNginx / Caddy /\nTraefik",
"flaskLabel": "Flask :8008",
"flaskDetail": "Blueprints\nJWT-Middleware\nFail2Ban-Hook\n(falls installiert)",
"hostLabel": "Host-Tools",
"hostDetail": "psutil\npvesh\nsmartctl\njournalctl",
"stateLabel": "Lokaler Zustand",
"stateDetail": "SQLite DB\n+ auth.json"
},
"threadsIntro": "Der Prozess führt auch Hintergrundthreads aus. Diese Beispiele erfassen Daten, aktualisieren Caches und SQLite und versenden Meldungen. Weitere Aufgaben existieren; der Versand hängt von seiner Aktivierung ab:",
"headerThread": "Thread",
"headerCadence": "Intervall",
"headerJob": "Auftrag",
"rows": [
{
"thread": "_temperature_collector_loop",
"cadence": "60 s",
"job": "Speichert CPU-Temperatur und Latenzproben in der Verlaufsdatenbank, damit Diagramme auch ohne verbundenen Browser Daten haben."
},
{
"thread": "_health_collector_loop",
"cadence": "5 min",
"job": "Führt den Health-Monitor-Zyklus mit zehn Kategorien aus, speichert Fehler und Datenträgerbeobachtungen, berücksichtigt Unterdrückungen und übergibt neue Ereignisse an den Benachrichtigungsdienst."
},
{
"thread": "_vital_signs_sampler",
"cadence": "CPU 5 s; Temperatur 15 s; RAM 30 s",
"job": "Erfasst CPU-Auslastung, RAM und CPU-Temperatur für aktuelle Anzeigen und anhaltende Zustände, unabhängig von der fünfminütigen Gesamtprüfung."
},
{
"thread": "notification_manager.start()",
"cadence": "Ereignisgesteuert",
"job": "Startet Beobachter für Journal, Tasks und Hooks (JournalWatcher, TaskWatcher, ProxmoxHookWatcher) und sendet an eingerichtete Kanäle, optional mit KI-Umformulierung."
}
]
},
"systemd": {
"heading": "systemd-Einheit",
"intro": "Der Installer erstellt die Unit /etc/systemd/system/proxmenux-monitor.service. Standardkonfiguration:",
"items": [
"User=root: Der Dienst verwendet Root-Rechte für Host-Operationen wie SMART, pvesh und ZFS-Verwaltung. Die Webterminal-Prozesse erben diese Rechte.",
"Restart=on-failure mit zehn Sekunden Wartezeit: Nach fehlerhaftem Ende startet der Dienst automatisch neu.",
"After=network.target: ordnet den Start nach diesem Ziel ein; garantiert keine IP-Adresse, DNS oder externe Verbindung."
],
"inspectTitle": "Aktuelle Unit prüfen"
},
"appimage": {
"heading": "Was das AppImage enthält",
"intro": "Das AppImage enthält ein beim Start eingehängtes Dateisystem. AppRun im Wurzelverzeichnis bereitet die Umgebung vor und startet flask_server.py:",
"consequencesIntro": "Zwei Konsequenzen dieses Layouts:",
"consequences": [
"Mitgelieferte Python-Pakete. Die Python-Pakete liegen im AppImage und laufen mit dem Python-Interpreter des Hosts, 3.11 (PVE 8) oder 3.13 (PVE 9), ohne dass etwas in das System-Python des Hosts installiert wird. Die Anwendung nutzt weiterhin Kernel-Schnittstellen des Hosts und externe Host-Werkzeuge.",
"Hardware-Clients sind enthalten. Mitgeliefert werden ipmitool, lm-sensors und upsc. Messwerte erfordern unterstützte Hardware, Sensorzugriff und für USV-Daten einen eingerichteten NUT-Server."
]
},
"flask": {
"heading": "Struktur der Flask-Anwendung",
"intro": "flask_server.py erstellt eine Flask(__name__)-Instanz mit eingeschränkten CORS-Ursprüngen, registriert zehn Blueprints direkt und initialisiert Terminalrouten. Die Tabelle zeigt die Hauptmodule; die Blueprints für PBS, Monitor-Links, Audit und VM-Sicherung sind ebenfalls registriert. PVE-spezifische Vorwärmer laufen nur auf PVE-Hosts.",
"headerBlueprint": "Blueprint / Modul",
"headerPrefix": "Routenpräfix",
"headerOwns": "Zuständigkeit",
"rows": [
{
"blueprint": "flask_server.py",
"prefix": [
"/api/system",
"/api/storage",
"/api/network",
"/api/vms",
"/api/hardware",
"/api/logs",
"/api/prometheus"
],
"owns": "Kernendpunkte, statische Weboberfläche und optionale Fail2Ban-Prüfung bei vorhandenem Jail proxmenux auf dem Host."
},
{
"blueprint": "flask_auth_routes.py",
"prefix": [
"/api/auth/*"
],
"owns": "Anmeldung, JWT-Ausgabe, TOTP-Einrichtung und -Prüfung, Passwortänderung und API-Token."
},
{
"blueprint": "flask_health_routes.py",
"prefix": [
"/api/health/*"
],
"owns": "Zustandsprüfungen, Detailstatus, aktive und unterdrückte Fehler sowie Unterdrückungseinstellungen. Geschützte Routen verlangen Authentifizierung, wenn aktiviert."
},
{
"blueprint": "flask_terminal_routes.py",
"prefix": [
"/api/terminal/* + WS"
],
"owns": "Stellt je Sitzung ein PTY bereit und verbindet es über WebSocket mit xterm.js im Browser."
},
{
"blueprint": "flask_notification_routes.py",
"prefix": [
"/api/notifications/*"
],
"owns": "Kanäle anlegen, lesen, ändern und löschen; Testversand, KI, Verlauf und manuelle Meldungen."
},
{
"blueprint": "flask_security_routes.py",
"prefix": [
"/api/security/*"
],
"owns": "Anmeldefehler und bei installiertem Fail2Ban Jail-Zustand, Sperrereignisse und manuelles Entsperren."
},
{
"blueprint": "flask_proxmenux_routes.py",
"prefix": [
"/api/proxmenux/*"
],
"owns": "Liest die im Host-Bestand registrierten ProxMenux-Optimierungen."
},
{
"blueprint": "flask_oci_routes.py",
"prefix": [
"/api/oci/*"
],
"owns": "Hilfen zur Bereitstellung von OCI- und Container-Apps auf Proxmox VE 9.1+."
}
],
"endpointsLink": "Integrationsendpunkte und ihre Formate erklärt API-Referenz."
},
"dataSources": {
"heading": "Datenquellen",
"intro": "Host-Daten stammen überwiegend aus Standardbibliotheken, Dateien und Verwaltungsbefehlen. Einige Gastdaten benötigen zusätzlich den QEMU Guest Agent oder Befehle innerhalb eines CT:",
"headerSource": "Quelle",
"headerUsedFor": "Verwendet für",
"rows": [
{
"source": "psutil",
"usedFor": "CPU-Last, RAM, Swap, Belegung von Einhängepunkten, Netzwerkzähler und Prozesse."
},
{
"source": "pvesh / qm / pct",
"usedFor": "Proxmox-Knoteninformationen, VM-/CT-Bestand und Konfiguration, Speicher sowie Task-Verlauf."
},
{
"source": "smartctl",
"usedFor": "SATA-/NVMe-Attribute, SMART-Zustand, Verschleiß, Lebensdauer, Modell und Seriennummer."
},
{
"source": "zpool / zfs",
"usedFor": "Poolzustand (ONLINE / DEGRADED / FAULTED / UNAVAIL), Scrub-Fortschritt und Dataset-Belegung."
},
{
"source": "journalctl",
"usedFor": "Systemprotokolle, OOM-Abbrüche, ATA-/NVMe-/dm-Fehler, Sicherheitsereignisse und eigene Service-Units."
},
{
"source": "ip / iproute2",
"usedFor": "Schnittstellen, Adressen, Bridges, Bonds und OVS-verwaltete Geräte."
},
{
"source": "nvidia-smi · intel_gpu_top",
"usedFor": "Verfügbare GPU-Daten zu Auslastung, VRAM, Temperatur und Encoder/Decoder. Felder hängen von Hersteller, Werkzeug und Treiber ab."
},
{
"source": "lspci · lscpu · dmidecode",
"usedFor": "PCIe-Topologie, CPU-Modell und -Topologie sowie Mainboard- und BIOS-Daten."
},
{
"source": "ipmitool · sensors",
"usedFor": "Out-of-Band-Sensoren, Lüfterdrehzahlen und Mainboard-Temperaturen bei unterstützter Hardware."
},
{
"source": "upsc (NUT)",
"usedFor": "Batteriezustand, Last und Restlaufzeit der USV bei eingerichtetem NUT-Server."
}
],
"cacheTitle": "Caches reduzieren Host-Abfragen",
"cacheBody": "Aufwendige Ergebnisse von smartctl -a und pvesh get werden im Flask-Prozess zeitweise gespeichert, um Datenträger und Cluster-API seltener abzufragen. Die Dauer hängt von der Quelle ab: Sekunden für aktuelle Metriken, Minuten für SMART."
},
"persistence": {
"heading": "Persistenz",
"intro": "Mehrere Zustandsdateien haben unterschiedliche Inhalte und Zugriffsanforderungen:",
"headerPath": "Path",
"headerOwner": "Eigentümer",
"headerContents": "Inhalt",
"rows": [
{
"path": "/usr/local/share/proxmenux/health_monitor.db",
"owner": "root:root",
"contents": "SQLite-Datenbank. Tabellen: errors, events, disk_registry, disk_observations, user_settings, notification_history, excluded_storages, excluded_interfaces. WAL-Journalmodus."
},
{
"path": "/usr/local/share/proxmenux/.notification_key",
"owner": "root 0600",
"contents": "32-Byte-Hauptschlüssel für Benachrichtigungsgeheimnisse im ENC2-Format. Verwendet zufälliges Salt je Wert, abgeleitete Schlüssel und MAC. Alte XOR-Werte werden zur Migration unterstützt."
},
{
"path": "/root/.config/proxmenux-monitor/auth.json",
"owner": "root:root",
"contents": "Authentifizierungskonfiguration: Aktivierung, Benutzername, gesalzener PBKDF2-HMAC-SHA256-Passworthash, TOTP-Geheimnis, Wiederherstellungscodes, installationsbezogener JWT-Schlüssel, API-Token-Metadaten und Widerrufshashes. Alte SHA-256-Hashes werden nach erfolgreicher Anmeldung migriert."
},
{
"path": "/var/log/proxmenux-auth.log",
"owner": "root:root",
"contents": "Klartextprotokoll der Authentifizierung, unabhängig von Fail2Ban. Ist das Jail [proxmenux] installiert und aktiv, liest es das Protokoll zur Erkennung wiederholter Anmeldefehler. Ohne Jail bleibt das Protokoll zur Prüfung verfügbar."
}
],
"backupTitle": "auth.json vor der Neuinstallation sichern",
"backupBody": "Ein AppImage-Austausch bewahrt normalerweise /root/.config/proxmenux-monitor/auth.json und /usr/local/share/proxmenux/health_monitor.db. Bewahren Sie auth.json samt jwt_secret für gültige Token und Metadaten. Die Datenbank enthält unabhängig Zustands- und Meldungsdaten. Sichern Sie .notification_key mit ihr für verschlüsselte Kanaleinstellungen; die Datenbank allein stellt API-Authentifizierung nicht wieder her."
},
"health": {
"heading": "Health-Monitor-Zyklus",
"intro": "Etwa alle fünf Minuten ruft der Hintergrundkollektor health_monitor.py für die Prüfungen der zehn Dashboard-Kategorien auf:",
"items": [
"Kritische PVE-Dienste (pveproxy, pvedaemon, pvestatd, pve-cluster).",
"Proxmox-Speicher: pvesh get /storage und Verfügbarkeit je Speicher.",
"Datenträger und Dateisysteme: SMART, E/A-Fehler in dmesg, ZFS-Zustand und Belegung von Einhängepunkten.",
"VMs und CTs: Startfehler, Abstürze, QMP-Fehler und Probleme beim Herunterfahren.",
"Netzwerk: Bridge- und Bond-Zustand, Verbindungsstatus und Gateway-Latenz.",
"Updates: ausstehende Paketaktualisierungen und Sicherheitspatches.",
"Protokolle: anhaltende Muster, Spitzen und Kaskaden im Systemjournal.",
"Arbeitsspeicher: OOM-Killer-Aktivität und anhaltender Speicherdruck.",
"CPU: Auslastung und CPU-Temperatur im Vergleich zu den konfigurierbaren Schwellen; verfügbare Sensoren hängen von der Hardware ab.",
"Sicherheit: Anmeldefehler, Sperrereignisse und Fail2Ban-Jail-Zustand."
],
"afterIntro": "Befunde verwenden stabile error_key, Kategorie und Schweregrad. Vorhandene Einträge in errors werden an Ort und Stelle aktualisiert (last_seen, Schweregrad, Grund), statt dupliziert zu werden. Der Benachrichtigungsversand hat zudem eigene Regeln für Fingerabdrücke und Wartezeiten.",
"cycleEnd": "Die Bereinigung kann alte Fehler anhand der Unterdrückungsdauer je Kategorie und Zustandsregeln auflösen, verwaiste Einträge entfernter Ressourcen entfernen und events über 30 Tage löschen. Kategorien erklärt Dashboard → Health Monitor."
},
"notifications": {
"heading": "Benachrichtigungsmotor",
"intro": "notification_manager.py koordiniert den Versand: lädt Kanäle, verwaltet die Warteschlange und bietet eine Python-API für Flask und Health Monitor sowie einen CLI-Einstieg für ProxMenux-Hooks in .sh.",
"items": [
"Beobachter erzeugen Ereignisse: JournalWatcher verfolgt das Journal, TaskWatcher fragt Proxmox-Tasks ab, ProxmoxHookWatcher empfängt Sicherungs-, Replikations- und Snapshot-Hooks und PollingCollector verarbeitet langsame Quellen.",
"Vorlagen erzeugen Titel und Nachricht aus Ereignissen. Der konfigurierte KI-Anbieter (OpenAI / Anthropic / Gemini / Groq / Ollama / OpenRouter) kann sie verständlich umformulieren. Beide Fassungen werden in notification_history gespeichert.",
"Kanäle versenden über Dienste wie Telegram, Discord, E-Mail, Gotify, Pushover und Apprise. Implementierungen in notification_channels.py teilen die Schnittstelle create_channel() / send().",
"Verschlüsselung. Vertrauliche Einstellungen (telegram.bot_token, discord.webhook_url, pushover.user_key, pushover.api_token, ai_api_key_*, email.password) werden vor dem Speichern mit dem Schlüssel aus .notification_key verschlüsselt und in der Oberfläche maskiert."
],
"linksFooter": "Ereignisschalter, kanalspezifische Einstellungen und KI erklären Einstellungen → Benachrichtigungen und Einstellungen → KI-Assistent."
},
"websocket": {
"heading": "WebSocket Terminal",
"intro": "Die Registerkarte Terminal verbindet einen schlanken xterm.js-Client über WebSocket mit einem serverseitigen PTY. Es gibt zwei Betriebsarten:",
"items": [
"HTTP-Modus, Standard: Der integrierte Flask-Server verarbeitet mit flask-sock WebSocket-Upgrade-Anfragen.",
"HTTPS-/WSS-Modus: Der TLS-Server verwendet gevent.pywsgi.WSGIServer mit dessen Standard-Handler; flask-sock verarbeitet WebSocket-Verbindungen über TLS."
],
"outro": "Terminal-Kindprozesse erben User=root vom Dienst. Das Öffnen eines WebSockets erfordert ein kurzlebiges Einmalticket vom authentifizierten Terminal-Ticket-Endpunkt mit Verwaltungsrechten.",
"proxyNote": "Beim Reverse-Proxy muss WebSocket-Weiterleitung mit den Headern Upgrade und Connection funktionieren. Das Terminal benötigt diese Weiterleitung."
},
"proxy": {
"heading": "Reverse-Proxy und Fail2Ban",
"intro": "Client-IP-Auswahl und optionale Sperrung in der Anwendung hängen von diesen Einstellungen und Komponenten ab:",
"items": [
"Client-IP-Auswahl. Die Sperrprüfung in before_request und das Auth-Protokoll vertrauen X-Forwarded-For, danach X-Real-IP, nur mit PROXMENUX_TRUST_PROXY=1. Sonst gilt request.remote_addr. Weitergeleitete Header werden nicht automatisch akzeptiert.",
"Optionales Fail2Ban in der Anwendung. Bei Proxyverbindungen kann die Proxy-IP als TCP-Gegenstelle erscheinen. Sind die vertrauenswürdige Client-IP und das aktive Jail proxmenux verfügbar, weist Flask gesperrte IPs mit HTTP 403 zurück. Die Liste wird 30 Sekunden gespeichert und bei späteren Anfragen erneuert, nicht durch einen eigenen Timer."
],
"calloutTitle": "Fail2Ban ist nicht enthalten",
"calloutBody": "Fail2Ban ist nicht enthalten und wird nicht automatisch installiert. Die Installation ist über Monitor-Sicherheit oder Sicherheit → Fail2Ban in ProxMenux Scripts möglich. Fehlen fail2ban-client oder das Jail proxmenux, blockiert dieser Hook keine Anfragen. Die eingestellte Authentifizierung gilt weiter.",
"outro": "Beispiele für Nginx, Caddy und Traefik sowie die Jail-Anleitung stehen unter Zugriff und Authentifizierung und Sicherheit → Fail2Ban."
},
"whereNext": {
"heading": "Weitere Schritte",
"items": [
{
"label": "Zugriff und Authentifizierung",
"href": "/docs/monitor/access-auth",
"tail": " — Ersteinrichtung, Passwort und TOTP-2FA, Reverse-Proxy-Beispiele und Fail2Ban-Jail."
},
{
"label": "API-Referenz",
"href": "/docs/monitor/api",
"tail": " — Integrationsendpunkte, Token-Verwaltung und Authentifizierungskonventionen."
},
{
"label": "Einstellungen → ProxMenux Monitor",
"href": "/docs/settings/proxmenux-monitor",
"tail": " — Dienststeuerung und Zustandsprüfung im ProxMenux-Textmenü."
}
]
}
}