Files
tickte-system/docs/superpowers/specs/2026-09-30-serverpuls-design.md
T
2026-09-30 12:43:13 +00:00

199 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Serverpuls – Server-Monitoring in WOMS
Stand: 2026-09-30 · Status: Design vom Nutzer im Chat freigegeben, Spec zur Prüfung
## Ziel
Ein neuer Navbar-Eintrag **Serverpuls** in WOMS (ticket.webklar.com) zeigt Admins die
Auslastung des Servers und das Wachstum der einzelnen Projekte über Tage, Wochen und
Monate – als Verlaufskurven „wie bei Aktien“. Feste Warnregeln (keine KI) melden
Probleme per E-Mail in drei Stufen.
Ausdrücklich **nicht KI-gesteuert**: Messung, Auswertung und Mails laufen
deterministisch in einem kleinen Dienst ohne Claude.
## Rahmenbedingungen
- Server: 8 Kerne, 15 GB RAM, 4 GB Swap (am 2026-09-30 voll), Platte 150 GB (76 % belegt),
~61 Container. Der Dienst selbst muss sehr sparsam sein (Limit 128 MB RAM, 0,5 CPU).
- WOMS ist eine statische React/Vite-SPA auf Appwrite; Server-Logik liegt in kleinen
Node-Diensten hinter dem WOMS-nginx (Vorbild: `ticket-integrations`,
`/api/integrations/`, Auth über Appwrite-JWT).
- Admin in WOMS = Appwrite-Konto mit Label `admin` (`AuthContext.jsx`).
- Der Deploy-Webhook von WOMS deployt jeden gepushten Branch; live geht nur per Push
des Nutzers nach `test`.
## Entscheidungen
| Frage | Entscheidung |
|---|---|
| Name | Serverpuls |
| Rolle der KI | keine; feste Warnregeln |
| „Projekt“ | jede App / jeder Container (Previews als eigene Apps) mit CPU, RAM, Speicher |
| Warnkanal | E-Mail in drei Stufen Low / Medium / Critical |
| Mail-Takt | Critical sofort, Medium Sammelmail täglich 07:00, Low Wochenübersicht Mo 07:00 |
| Mail-Adresse | `server@webklar.com` ist Absender **und** einziger Empfänger |
| Umsetzung | eigener schlanker Dienst (kein Beszel, kein Netdata) |
| Sichtbarkeit | nur Admins (Navbar und API) |
## Architektur
```
Host /proc (ro) ──┐
docker-socket-proxy (nur GET containers/stats) ──┼──> serverpuls (Node 22, SQLite) ──> SMTP server@
/home/webklar/apps + Docker-Volumes (ro) ──┘ │
└── HTTP :8091 <── WOMS-nginx /api/serverpuls/ <── ServerpulsPage (uPlot)
```
### Einheiten
1. **Collector** (`collect/`): liest Messwerte, gibt reine Datenobjekte zurück.
- `host.js` – `/proc/stat` (CPU % aus Differenz), `/proc/meminfo` (RAM verfügbar,
Swap), `/proc/loadavg`, Zombies = Prozesse mit State `Z` in `/proc/*/stat`.
Plattenbelegung `/` per `statfs` auf `/host/apps` (gleiches Dateisystem `/dev/sda1`).
- `docker.js` – über den Socket-Proxy: Container-Liste (Name, Compose-Projekt/-Service,
Status, Health, RestartCount) und `stats?stream=false` (CPU %, RAM).
- `sizes.js` – Größe pro App: Ordner unter `/home/webklar/apps/<app>` plus Docker-
Volumes der Container dieser App (`du -sb`, unter `nice -n 19 ionice -c3`).
Außerdem „Aufräumbar“: ungenutzte Images, Build-Cache, gestoppte Container
(`/system/df` über den Proxy).
2. **App-Zuordnung** (`apps.js`): Container → App über das Label
`com.docker.compose.service` bzw. den Containernamen; eine kleine Mapping-Datei
`config/apps.json` erlaubt Umbenennen/Zusammenfassen (z. B. `webklar-ticket-*` →
„Ticketsystem“) und Ordnerzuordnung. Previews erscheinen einzeln.
3. **Speicher** (`store.js`): SQLite (`node:sqlite`) im Volume `serverpuls-data`.
- Tabellen: `host_samples`, `app_samples`, `app_sizes`, `cleanup_samples`,
`alerts` (Zustand), `mail_queue`.
- Aufbewahrung: Rohwerte (5 min) 7 Tage → Stundenmittel/-max 90 Tage →
Tageswerte unbegrenzt. Verdichtung täglich 03:30.
- Erwartete Größe < 100 MB/Jahr.
4. **Regeln** (`rules.js`): reine Funktion `(aktuelle + historische Werte) → Liste aktiver
Befunde {id, level, titel, wert, seit}`. Schwellen in `config/rules.json`.
5. **Alarmierung** (`alerts.js`): vergleicht Befunde mit gespeichertem Zustand, erzeugt
Mails (sofort/täglich/wöchentlich), Wiederholungssperre 24 h, „✅ behoben“-Mail beim
Verschwinden. Zustand in SQLite → Neustart erzeugt keine Doppel-Mails.
6. **Mailer** (`mail.js`): nodemailer, `mail.your-server.de:587` STARTTLS, Login
`server@webklar.com`. Fehlgeschlagene Mails bleiben in `mail_queue` und werden
alle 5 min erneut versucht (max. 24 h).
7. **API** (`api.js`): HTTP-Server Port 8091, Basis `/api/serverpuls`. Jede Anfrage
(außer `/health`) braucht `X-Appwrite-JWT`; der Dienst fragt `/account` bei Appwrite
ab (Cache 60 s) und verlangt Label `admin`, sonst 401/403.
8. **Scheduler** (`main.js`): 5-min-Takt, nächtliche Größenmessung 03:00, Verdichtung
03:30, Medium-Digest täglich 07:00, Low-Wochenübersicht Mo 07:00 (Europe/Berlin).
### Messung
- Alle 5 Minuten: Server gesamt (CPU %, Load 1/5/15, RAM verfügbar, Swap belegt,
Platte `/`, Zombies) und pro Container (CPU %, RAM, Status, Neustarts).
- Täglich 03:00: Größe pro App und „Aufräumbar“-Werte.
- Fällt eine Messung aus, wird **kein** Wert geschrieben (Lücke statt falscher Null).
## Warnregeln
Wichtige Container („kritisch“): Traefik, Appwrite, Kundenportal, Ticketsystem,
ticket-integrations, Gitea, InvoiceNinja, n8n (Liste in `config/rules.json`).
**🔴 Critical – sofortige Mail**
- Platte `/` ≥ 90 %
- RAM verfügbar < 500 MB **und** Swap ≥ 90 %, 10 min lang
- Load (5 min) > 24, 15 min lang
- kritischer Container läuft nicht oder > 3 Neustarts pro Stunde
- Zombies ≥ 100
**🟠 Medium – Sammelmail täglich 07:00**
- Platte `/` ≥ 80 %
- Swap ≥ 75 % oder RAM verfügbar < 1,5 GB, jeweils 1 h lang
- Zombies ≥ 20
- App wächst in 7 Tagen um > 20 % oder > 2 GB
- Load (5 min) > 8, 1 h lang
- nicht-kritischer Container abgestürzt (exited ≠ 0 oder Restart-Schleife)
**🟡 Low – Wochenübersicht Mo 07:00**
- ungenutzte Docker-Images > 10 GB oder Build-Cache > 3 GB
- App wächst in der Woche um > 10 %
- Zombies (≥ 1) halten sich > 24 h
- immer enthalten: Top 5 größte Apps, Top 5 schnellstes Wachstum, Top 5 RAM
**Allgemein**
- Dieselbe Warnung (gleiche `id`) höchstens 1× pro 24 h erneut gemeldet.
- Beim Verschwinden: Mail „✅ behoben“ (in derselben Taktung wie die Stufe; bei
Critical sofort).
- Alle aktiven Warnungen stehen jederzeit auf der Seite.
- Wird eine Warnung höher eingestuft (Medium → Critical), gilt sofort die höhere Stufe.
## API
Alle Antworten JSON, Zeitstempel ISO/UTC.
| Methode + Pfad | Inhalt |
|---|---|
| `GET /health` | ohne Auth; `{ok, lastSample}` |
| `GET /overview` | aktuelle Serverwerte, 24-h-Minikurven, Trend ggü. gestern, aktive Warnungen, Zeitpunkt der letzten Messung |
| `GET /host?metric=cpu\|ram\|swap\|load\|disk\|zombies&range=24h\|7d\|30d\|90d\|1y` | Zeitreihe; Auflösung abhängig vom Zeitraum |
| `GET /apps` | Tabelle: Name, CPU %, RAM, Speicher, Δ 7 T, Δ 30 T, Speicher-Minikurve (30 T) |
| `GET /apps/:id?range=…` | Zeitreihen Speicher, RAM, CPU für eine App |
| `GET /cleanup` | ungenutzte Images, Build-Cache, gestoppte Container mit Größe |
Nur lesend. Es gibt **keine** Endpunkte zum Löschen, Stoppen oder Ändern.
## WOMS-Seite „Serverpuls“
- Navbar-Eintrag mit Pulssymbol, nur für `isAdmin`; roter/oranger Punkt bei aktiver
Critical/Medium-Warnung (aus `/overview`, beim Laden der App und alle 5 min).
- Route `/serverpuls`; Nicht-Admins werden umgeleitet.
- Aufbau:
1. **Kopf mit Ampel**: 🟢 Alles ok / 🟠 n Warnungen / 🔴 Critical, darunter die
aktiven Warnungen (Stufe, seit wann, Wert). Hinweis „letzte Messung vor X Min.“;
gelb, wenn älter als 15 min.
2. **Kacheln**: CPU, Load, RAM, Swap, Platte, Zombies – aktueller Wert, 24-h-Minikurve,
Trend ggü. gestern.
3. **Großes Diagramm** (uPlot): Zeitraum 24 h / 7 T / 30 T / 90 T / 1 J, Wert
wählbar, Tooltip mit exaktem Wert.
4. **Tabelle „Projekte“**: sortierbar, Suchfeld, Δ-Spalten grün/rot mit Pfeil,
Minikurve; Klick öffnet Detaildiagramm der App.
5. **„Aufräumbar“**: reine Anzeige.
- Aktualisiert sich jede Minute, solange sichtbar. Handy: Kacheln untereinander.
- Neue Abhängigkeit: `uplot`. Lockfile wie bisher in einem Wegwerf-`node:20-alpine`
erzeugen (Deploy-Image).
## Betrieb / Deploy
- Code: `/home/webklar/apps/serverpuls/` (eigenes Git-Repo, nur lokal).
- `docker-compose.yml` (Backup vorher): Dienste `serverpuls` (`node:22-alpine`,
`mem_limit: 128m`, `cpus: 0.5`, `init: true`; Host-`/proc` wird als `/host/proc:ro` gemountet,
kein `pid: host`) und `serverpuls-docker-proxy`
(`tecnativa/docker-socket-proxy`, nur lesend: `CONTAINERS=1`, `IMAGES=1`, `SYSTEM=1`
für `/system/df`, `POST=0`), beide im `webklar-network`, ohne Traefik-Route.
- Mounts serverpuls: `/proc:/host/proc:ro`, `/home/webklar/apps:/host/apps:ro`,
`/var/lib/docker/volumes:/host/volumes:ro`, `serverpuls-data:/data`.
- `.env`: `SERVERPULS_SMTP_USER=server@webklar.com`, `SERVERPULS_SMTP_PASS` – vom
Nutzer über eine Erweiterung von `scripts/mail-zugang.py` gesetzt (Claude sieht das
Passwort nicht).
- WOMS-nginx: `location /api/serverpuls/` → `http://serverpuls:8091` (wie
`/api/integrations/`).
- WOMS-Code auf `feature/serverpuls` (Worktree `dev-serverpuls`, Basis `origin/test`).
Live erst nach Push des Nutzers.
## Fehlerbehandlung
- Collector-Teilfehler (z. B. Proxy nicht erreichbar) → betroffene Werte fehlen, Rest
wird gespeichert; Fehler im Log.
- Größenmessung hat Zeitlimit (30 min); bricht sie ab, bleiben die Vortageswerte stehen
und die Seite zeigt deren Datum.
- SMTP-Fehler → `mail_queue`, erneuter Versuch alle 5 min bis 24 h.
- Appwrite nicht erreichbar → API 502, Seite zeigt Fehlerhinweis.
## Tests
- Unit: Regeln (Schwellen, Dauerbedingungen, Hoch-/Herabstufung, Wiederholungssperre,
behoben), Verdichtung, Wachstumsberechnung, `/proc`-Parser mit Beispieldateien.
- API: gemocktes Appwrite (Admin → 200, ohne Label → 403, ohne JWT → 401).
- UI: bewährtes esbuild-/Playwright-Harness unter RAM-Limit mit API-Fixtures.
- Live-Check: Container-RAM < 128 MB, erste Messwerte, Test-Mail an server@.
## Nicht enthalten
- Keine Aktionen (Löschen, Neustarten) aus der Seite heraus.
- Keine KI-Auswertung.
- Keine automatischen Tickets (Warnungen nur per Mail und auf der Seite).