doku: Monitoring mit Verlauf in ARCHITEKTUR und BETRIEB

Aufbau (Speicher, Taktgeber, Ausfuehrer-Faden, Schnittstellen, Waechter),
Ablage und Groesse der Dateien, Aufbewahrung, Handgriffe zum Nachsehen und
der Hinweis, dass der Ausfuehrer mit ausfuehrer-einrichten.sh kommt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-24 22:41:53 +02:00
co-authored by Claude Opus 5.5
parent 704c21d839
commit f840995078
2 changed files with 111 additions and 9 deletions
+70 -5
View File
@@ -58,7 +58,7 @@ Client an MC2 vorbei direkt auf `:8080`. Nur den Radar-Kandidaten startet der Ra
|---|---|---|---|
| `mission-control-2` (`:9001`) | `backend/app.py` | Oberfläche aus `frontend/dist`; 62 `/api`-Routen; reicht `/v1` roh an den Gateway weiter (`MC_V1_UPSTREAM`); reicht das Hermes-Dashboard unter `/hermes-ui/` durch (HTTP und WebSocket); Erinnerungen; startet Update- und Download-Aufträge als eigene systemd-Einheiten `mc2-job-<id>` (`services/jobengine.py`) | Briefkasten, Erinnerungen, Routing-Policy, Hugging-Face-Zugang, ausgeblendete Hinweise |
| `mc2-gateway` (`127.0.0.1:9010`) | `backend/gateway_app.py` | `/v1` mit `model: auto` und Bild-Weiche, Kontext-Warnung, `/gw/health` | Token-Zähler (`~/.hermes/token_stats.json`) |
| `mc2-steward` | `backend/steward.py` | Re-Warm (alle 90 s, lädt das Hirn nach, wenn nichts geladen ist), Config-Watch (5 s), Wächter (jede Minute) | `mc2-waechter.json` (einziger Schreiber) |
| `mc2-steward` | `backend/steward.py` | Re-Warm (alle 90 s, lädt das Hirn nach, wenn nichts geladen ist), Config-Watch (5 s), Wächter (jede Minute), Messwerte (ein Punkt je Minute, seit 24.09.) | `mc2-waechter.json` (einziger Schreiber), `mc2-messwerte/box-*.jsonl` |
| `mc2-radar` (Timer 00:30) | `backend/radar_lauf.py` | Suche und Nachttest neuer Modelle | `mc2-radar.json`, Baseline, `/srv/models/radar/` |
| Bash-Schicht | `deploy/*.sh` | Updates (`autoupdate.sh` mit `update-swap.sh`, `update-engine.sh`, Postchecks, `self-repair.sh`), Sicherung (`backup.sh`, `restore.sh`), Meldungen (`notify.sh`, `morgenmeldung.sh`), Vorwärmen (`warmup.sh`), `projekte-sync.sh`, Deploy (`deploy.sh`, `pruefen.sh`) | Pins, Meldeprotokoll, Nacht-Warteschlange, Deploy-Log |
@@ -172,6 +172,7 @@ Fremde Dienste, die der Box-Wart nur steuert oder überwacht: `llama-swap` (Syst
| `/srv/models/mc2-deploy.log` | `deploy.sh` | eine Zeile je Deploy, auch gescheiterte |
| `~/mc2-notify.log` | `notify.sh` (anhängen), `morgenmeldung.sh` (über 3 MB auf 2 MB kürzen) | Quelle des Update-Verlaufs für Läufe vor dem 24.09.; der Wortlaut „QUEUED für Morgen-Digest" muss bleiben |
| `/srv/models/mc2-update-verlauf.jsonl` | `autoupdate.sh`, MC2 (Update-Knöpfe) | nur anhängen, eine JSON-Zeile je Baustein |
| `/srv/models/mc2-messwerte/box-JJJJ-MM-TT.jsonl` | nur der Steward (Box); im Homelab `/var/lib/mc2/mc2-messwerte/<gerät>-…` nur MC2 | nur anhängen unter `flock`, eine Zeile je Minute; Tage älter als 8 löscht der Schreiber selbst (siehe „Monitoring“) |
| `~/.hermes/night-queue.txt` | `notify.sh` (anhängen), `morgenmeldung.sh` (übernehmen, senden) | nicht gesendeter Stapel bleibt als `.senden` liegen |
## Meldeweg
@@ -201,6 +202,7 @@ Partner-Instanz. In der Rolle `homelab` gibt es nur `/api/health` und die Partne
| Modelle (`routers/models.py`) | `GET /models`, `GET /discover`, `POST /models/register`, `GET /hf/search`, `GET /hf/quants`, `POST /models/install`, `GET /jobs`, `POST /jobs/{id}/cancel`, `POST /models/{id}/role`, `POST /models/unload`, `POST /models/{id}/unload`, `POST /models/{id}/load`, `DELETE /models/{id}` |
| Wartung (`routers/maintenance.py`) | `GET /maintenance/updates`, `GET /maintenance/update-details`, `POST` `check-updates`, `os-update`, `engine-update`, `swap-update`, `hermes-update`, `update-all`, `restart`; `GET /maintenance/logs`; `GET`/`POST /maintenance/geheimnisse` |
| System (`routers/system.py`) | `GET /system/status`, `GET /system/services`, `POST /system/backup`, `GET /system/backups`, `POST /system/restart`, `GET /system/token-stats` |
| Messwerte (`routers/messwerte.py`, seit 24.09.) | `GET /messwerte?zeitraum=1h\|24h\|7d` |
| Lucy und Sprache (`routers/voice.py`) | `POST /alarm`, `POST /voice/announce`, `GET /voice/announcements`, `POST /voice/stt`, `POST /voice/turn`, `POST /voice/chat`, `GET /lucy/stimme/health`, `POST /lucy/stimme/tts`, `POST /lucy/stimme/tts/stream` |
| Sonstiges | `GET /health`, `GET /stream` (Live-Strom, SSE), `GET /routing`, `GET`/`POST /reminders`, `DELETE /reminders/{id}`, `GET /zeitmaschine`, `POST /zeitmaschine/restore` |
| Partner (`routers/partner.py`) | `GET /partner` (Lebenszeichen), `/partner/{pfad}` (Durchreiche, alle Methoden) |
@@ -234,7 +236,7 @@ flowchart LR
feste Liste von Aktionen aus (`bericht`, `snapshot`, `update`, `os_update`, `suchen`, `zurueck`,
`snapshot_loeschen`, `sichern`, `sicherung_zurueck`, `sicherung_loeschen`, `host_update`, `host_neustart`) und
prüft selbst, ob ein Gast das Etikett `community-script` oder `watcher` trägt und nicht `watcher-aus` — dem Server
vertraut er dabei nicht.
vertraut er dabei nicht. Seit 24.09. schickt er außerdem jede Minute Messwerte (eigener Faden, siehe „Monitoring“).
- **Bericht** (nur lesend, auch von Hand: `python3 ausfuehrer.py --bericht`): Host-Version und Paket-Updates, je
Gast Status, IP, Etiketten, Snapshots, ob ein Snapshot geht (Bind-Mounts wie beim PBS verhindern ihn), die
Community-Script-Kennung (aus `/usr/bin/update` im Gast), die App-Version (je App eigener Weg: `/root/.<app>`,
@@ -257,7 +259,8 @@ flowchart LR
`apps.py` (App-Katalog: Name, GitHub-Quelle, Weboberfläche, Update-Weg), `inventar.py` (Bericht + neueste Versionen
von GitHub + eigene Webprüfung → Ziele im gemeinsamen Modell; Paketlisten älter als 14 Tage = „unklar“ mit Knopf
„Nach Updates suchen“), `karenz.py` (Wartezeit nach einer Skriptänderung), `updates.py` („Jetzt updaten“),
`pflege.py` (wöchentliches Suchen). Schnittstellen `routers/homelab.py` unter `/api/homelab/…`.
`pflege.py` (wöchentliches Suchen), `messwerte.py` (Minutenpunkte des Ausführers, siehe „Monitoring“).
Schnittstellen `routers/homelab.py` unter `/api/homelab/…`.
- **„Jetzt updaten“** (nur per Knopf): Snapshot, wo keiner geht Sicherung (wo auch die nicht geht: ohne Rückweg, mit
Warnung in der Rückfrage; scheitert der Schritt, beginnt das Update nicht) → `update` des Community-Scripts
(`PHS_SILENT=1`) bzw. Pakete → 20 s warten → frischer Bericht → Prüfung (Gast läuft, Weboberfläche antwortet,
@@ -284,8 +287,9 @@ flowchart LR
mit `MC_ARCANE_ECHT=1`. Die Arcane-VM braucht dafür kein Etikett, weil der Ausführer nicht beteiligt ist.
- **Wächter** in der Rolle `homelab`: Platte, Partner (die KI-Box), Ausführer (kein Bericht seit 30 min = rot),
jede Weboberfläche der freigegebenen Gäste (außer mitten in ihrem Update-Lauf; das Ergebnis meldet der Lauf), die
Platten der laufenden Container (ab 80 % gelb, ab 90 % rot — ext4 hält 5 % für root zurück; der Ausführer schickt `platte` mit) und das
wöchentliche Suchen (gelb, wenn es wiederholt scheitert).
Platten der laufenden Container (ab 80 % gelb, ab 90 % rot — ext4 hält 5 % für root zurück; der Ausführer schickt `platte` mit), das
wöchentliche Suchen (gelb, wenn es wiederholt scheitert) und seit 24.09. den Proxmox-Host selbst aus den Messwerten
(gelb, wenn er 10 Minuten lang über 95 % RAM oder 90 °C CPU liegt).
- **Oberfläche** (Bereich „Homelab“, nur Daten aus `/api/homelab/…`):
- **Cockpit** (`/homelab`): oben die Lage wie das Warnpanel der KI-Box — die große Leuchte (Störung vor Hinweis vor
laufendem Update vor offenen Updates) und eine Lampe je Gerät —, darunter die Hinweise des Homelab-Wächters und
@@ -298,3 +302,64 @@ flowchart LR
(`/etc/mc2/telegram.env`), nachts sammelt eine eigene Morgenmeldung („[Morgenmeldung Homelab]“).
- **Einrichtung** (Reihenfolge, jeder Schritt braucht das User-OK): `container-anlegen.sh` → `ausrollen.sh <ip>` →
`ausfuehrer-einrichten.sh <ip>` → `box-partner.sh <ip>`; Details in [BETRIEB.md](BETRIEB.md).
## Monitoring: Messwerte mit Verlauf (seit 24.09.)
Der Live-Strom der KI-Box (`/api/stream`, jede Sekunde ein Messpunkt) zeigt nur den Augenblick. Für den Verlauf
schreiben beide Bereiche jede Minute einen Punkt, gelesen wird er für die letzte Stunde, den letzten Tag oder die
letzte Woche.
```mermaid
flowchart LR
ST["mc2-steward (Box)<br/>jede Minute"] -->|box-…jsonl| MR[("mc2-messwerte/<br/>kern/messreihen.py")]
AF["Ausführer (pve)<br/>eigener Faden, jede Minute"] -->|POST …/ausfuehrer/messwerte| HL["Homelab-Teil<br/>services/homelab/messwerte.py"]
HL -->|pve-…, ct-…, vm-…jsonl| MR2[("mc2-messwerte/<br/>im Container")]
MR -->|GET /api/messwerte| UI["Oberfläche"]
MR2 -->|GET /api/homelab/messwerte| UI
MR2 -->|RAM, Temperatur| W["Wächter (homelab)"]
```
- **Speicher** `backend/kern/messreihen.py` (beide Rollen): je Quelle und Tag eine Datei
`<Datenordner>/mc2-messwerte/<quelle>-JJJJ-MM-TT.jsonl` (Tag nach Berliner Zeit), eine JSON-Zeile je Minute
(`{"t": Unix-Sekunden, "cpu": …, …}`, `null` = nicht gemessen). Schreiben hängt eine Zeile an, unter Thread-Sperre
und `flock`; fehlt am Dateiende der Zeilenumbruch (Absturz), beginnt die neue Zeile auf einer eigenen. Das erste
Schreiben eines neuen Tages löscht Dateien, deren Tag mehr als 8 Tage zurückliegt. Lesen verdichtet: `1h` in
60-s-Schritten, `24h` als 5-min-Mittel, `7d` als 30-min-Mittel (60, 288 bzw. 336 Werte, Schritte auf vollen
Vielfachen, der letzte ist der laufende). Ein Schritt ohne Messung bleibt `null`, nichts wird aufgefüllt; kaputte
Zeilen werden übersprungen. Die Summen vergangener Tage merkt sich der Prozess je Datei, solange sie sich nicht
ändert. Gemessen wird zur halben Minute, damit jeder 60-s-Schritt genau einen Punkt bekommt.
- **KI-Box** (`services/messwerte.py`, Taktgeber im Steward; `MC_MESSWERTE_ENABLED=0` schaltet ab, ein Trocken- oder
Probelauf schreibt nie mit): `cpu` = Mittel der Minute (aus eigenen `psutil.cpu_times`-Ständen gerechnet wie
`cpu_percent`, denn psutil merkt sich den letzten Aufruf je Thread), `ram` und `platte` (Modell-Laufwerk) beim Messen,
`gpu`, `temp_cpu`, `temp_gpu` als Mittel von Proben alle 5 s (`MC_MESSWERTE_PROBE_S`), `netz_rx`/`netz_tx` in
Bytes/s über alle Schnittstellen außer `lo`, `tokens` = Prompt- plus Antwort-Tokens pro Minute (Differenz der
Gesamtzähler aus `services/token_stats.py`). Ein Zähler, der kleiner wird, ergibt in dieser Minute `null`.
- **Homelab:** Der Ausführer schickt in einem eigenen Faden jede Minute `POST /api/homelab/ausfuehrer/messwerte`
(gleiche Anmeldung wie seine anderen Endpunkte), unabhängig vom 10-min-Bericht und von Aufträgen, die bis zu einer
Stunde laufen. Host-Werte liest er selbst aus `/proc` (`stat` für das CPU-Mittel der Minute, `meminfo`, `loadavg`,
`uptime`) und `statvfs("/")`, denn `pvesh get /nodes/<node>/status` liefert in einem frischen pvesh-Prozess immer
`cpu: 0` (nachgesehen am 24.09.); belegt wie bei Proxmox: RAM = gesamt − verfügbar, rootfs = gesamt − frei. Netz des
Hosts = Summe der physischen Schnittstellen aus `/proc/net/dev` (wie die Knoten-Anzeige in Proxmox; `vmbr0` sähe den
Verkehr der Gäste nach draußen nicht), ohne physische Schnittstelle `vmbr0`. CPU-Temperatur aus hwmon (`k10temp`
bzw. `zenpower` mit Tdie vor Tctl, `coretemp` mit „Package id 0“), sonst `null`; auf dem Proxmox-PC gibt es nur
`k10temp`/Tctl, kein `thermal_zone` und kein lm-sensors. Die Gäste kommen aus einem einzigen Aufruf
`pvesh get /cluster/resources --type vm` (`cpu` schon auf die eigenen Kerne gerechnet, `mem`, `disk`, …), ihre
Netz-Zähler aber aus denselben `/proc/net/dev`-Zeilen (`veth<vmid>iN`, `tap<vmid>iN`; die Stände in
`/cluster/resources` sind bis zu 10 s alt und verzerrten die Minutenrate). Fehler bleiben still; ein Fehler steht
einmal im Journal, bis wieder ein Punkt durchgeht. Von Hand: `python3 ausfuehrer.py --messwerte`.
- **Homelab-Teil** (`services/homelab/messwerte.py`): rechnet die kumulativen Zähler in Bytes/s um. Keine Rate
(`null`) gibt es, wenn der Zähler oder die Laufzeit kleiner wurde (Neustart von Gast oder Host), der vorige Stand
fehlt (Neustart des Homelab-Teils; die Stände liegen nur im Speicher) oder mehr als 5 Minuten zurückliegt, oder der
Sprung über 5 GB/s liegt. Gestoppte Gäste haben keine Messwerte (`null`, keine Nullen); die Platte einer VM sieht
Proxmox nicht (`null`). Der eigene Container (Etikett `mc2`) wird wie im Inventar nicht erfasst. Quellen `pve`,
`ct-<vmid>`, `vm-<vmid>`.
- **Schnittstellen:** `GET /api/messwerte?zeitraum=1h|24h|7d` (nur Rolle `box`) liefert
`{zeitraum, schritt_s, reihen: {cpu, ram, gpu, temp_cpu, temp_gpu, platte, netz_rx, netz_tx, tokens}, aktuell}`;
`GET /api/homelab/messwerte?zeitraum=…` liefert `{zeitraum, schritt_s, geraete: [{id, name, art, reihen, aktuell}]}`
mit den Geräten wie im Inventar (Host, dann die Gäste nach Nummer; Namen aus `apps.py`). Jede Reihe ist eine Liste
`[t, wert]` (t = Beginn des Schritts); `temp_cpu` gibt es als Reihe nur beim Host, in `aktuell` stehen `temp_cpu`
und `load1` bei Gästen auf `null`. `aktuell` ist der letzte Minutenpunkt, solange er höchstens 3 Minuten alt ist,
sonst lauter `null`. Ein unbekannter Zeitraum ergibt 400. Neue Punkte stößt der Live-Strom nicht an: Die Oberfläche
fragt die Messwerte selbst nach (einmal je Minute genügt).
- **Wächter** (Rolle `homelab`, `pruefe_host`): gelb, wenn der Proxmox-Host in den letzten 10 Minuten (mindestens 8
Minutenpunkte) durchgehend über 95 % RAM (`MC_WAECHTER_HOST_RAM`) oder über 90 °C CPU (`MC_WAECHTER_HOST_TEMP`) lag.
+41 -4
View File
@@ -81,11 +81,13 @@ soll kein Alarm sein).
| Festgehaltene Updates | – | jeder Pin |
| Partner-Instanz (nur mit `MC_PARTNER_URL`) | „<Name> antwortet nicht" | – |
| Sicherung (seit 24.09.) | – | `pbs-backup` scheitert; Probe-Wiederherstellung rot, älter als 40 Tage oder noch nie gelaufen (sobald ihr Timer eingerichtet ist) |
| Proxmox-Host (nur Rolle `homelab`, seit 24.09.) | – | 10 Minuten lang über 95 % RAM oder über 90 °C CPU (aus den Messwerten, mindestens 8 Minutenpunkte) |
| Abgestürzte Prüfung | – | „Eine Prüfung des Wächters lief nicht" |
In der Rolle `homelab` prüft der Wächter Platte, Partner, den Ausführer und die Weboberflächen der freigegebenen
Gäste (einen Gast mitten in seinem Update-Lauf nicht: Das Ergebnis meldet der Lauf selbst) und meldet mit
„[Homelab-Problem]". Im selben Takt stößt er das wöchentliche Suchen an (siehe „Homelab-Teil im Betrieb“); scheitert
In der Rolle `homelab` prüft der Wächter Platte, Partner, den Ausführer, die Weboberflächen der freigegebenen
Gäste (einen Gast mitten in seinem Update-Lauf nicht: Das Ergebnis meldet der Lauf selbst) und seit 24.09. RAM und
CPU-Temperatur des Proxmox-Hosts (gelb, Schwellen über `MC_WAECHTER_HOST_RAM` und `MC_WAECHTER_HOST_TEMP` in
`/etc/mc2/homelab.env`) und meldet mit „[Homelab-Problem]". Im selben Takt stößt er das wöchentliche Suchen an (siehe „Homelab-Teil im Betrieb“); scheitert
es für einen Gast zweimal hintereinander, gibt es einen gelben Hinweis „<App>: Die Suche nach Updates scheitert“.
- **Selbstreparatur:** Nur ein abgestürzter Dienst (`ActiveState=failed`) wird neu gestartet, höchstens 2× je Stunde
@@ -257,6 +259,41 @@ laufen lassen. Achtung: `ausfuehrer-einrichten.sh` schreibt `/etc/mc2-ausfuehrer
nach dem Start. Stand in `/var/lib/mc2/homelab-pflege.json` (Nacht, je Gast: letzter Tag, Fehlschläge, letzter
Fehler). Schreibt nur der Steward; zum Zurücksetzen die Datei löschen und `systemctl restart mc2-homelab-steward`.
## Messwerte (Monitoring, seit 24.09.)
Jede Minute ein Punkt je Gerät, gelesen als letzte Stunde, letzter Tag oder letzte Woche (Aufbau in
[ARCHITEKTUR.md](ARCHITEKTUR.md), Abschnitt „Monitoring“).
- **Wo:** Box `/srv/models/mc2-messwerte/box-JJJJ-MM-TT.jsonl` (schreibt `mc2-steward`). Homelab
`/var/lib/mc2/mc2-messwerte/pve-…`, `ct-<vmid>-…`, `vm-<vmid>-…` (schreibt `mc2-homelab`, was der Ausführer jede Minute
schickt; Eigentümer `mc2`). Je Tag (Berliner Zeit) eine Datei, eine JSON-Zeile je Minute.
- **Wie groß:** eine Zeile hat rund 140 Bytes (Box, Gäste) bzw. 175 Bytes (Proxmox-Host), am Tag 1440 Zeilen. Box:
rund 0,2 MB je Tag, höchstens rund 2 MB. Homelab mit Host und 7 Gästen: rund 1,7 MB je Tag, höchstens rund 15 MB;
jeder weitere Gast rund 0,2 MB je Tag.
- **Wie lange:** Das erste Schreiben eines neuen Tages löscht die Tagesdateien, deren Tag mehr als 8 Tage zurückliegt;
es bleiben höchstens 9 je Gerät (heute und die 8 Tage davor). Nicht in der Sicherung (`backup.sh` nimmt nur
`mc2-*.json`); das Aufräumen der Modell-Platte bietet den Ordner nie zum Löschen an. Den Ordner von Hand zu löschen
ist harmlos: Er entsteht mit dem nächsten Punkt neu, der Verlauf beginnt von vorn.
- **Lücken:** Läuft der Steward, die Box oder der Ausführer nicht, bleiben die Minuten leer (`null`) und werden nicht
aufgefüllt. Nach einem Neustart des Homelab-Teils fehlt für eine Minute die Netz-Rate; nach dem Neustart eines Gasts
oder des Hosts ebenso (die Zähler beginnen von vorn).
- **Ansehen:**
```bash
tail -n 3 /srv/models/mc2-messwerte/box-$(date +%F).jsonl # Box: die letzten Minuten
curl -s 'http://127.0.0.1:9001/api/messwerte?zeitraum=1h' | jq '.aktuell' # Box: letzter Punkt
curl -s 'http://192.168.178.31:9001/api/homelab/messwerte?zeitraum=1h' | jq '.geraete[] | {id, aktuell}'
python3 /usr/local/lib/mc2/ausfuehrer.py --messwerte # auf pve: ein Punkt, nur lesend (CPU über eine Sekunde)
journalctl -u mc2-ausfuehrer -n 50 | grep Messwerte # auf pve: steht hier etwas, gingen Punkte nicht durch
```
- **Ausführer:** Ein neuer Stand kommt nicht mit dem Deploy, sondern mit `bash deploy/homelab/ausfuehrer-einrichten.sh
<ip>` (danach ein von Hand gesetztes `sicherung_speicher` wieder eintragen, siehe oben). Ein alter Ausführer schickt
keine Messwerte; dann bleibt der Homelab-Verlauf leer, sonst ändert sich nichts.
- **Schalter:** `MC_MESSWERTE_ENABLED=0` im Steward der Box schaltet das Schreiben ab; `MC_MESSWERTE_PROBE_S` (Standard
5) ist der Abstand der Proben für GPU-Last und Temperaturen. Ein Trocken- oder Probelauf (`MC_WAECHTER_TROCKEN=1`,
`MC_PROBELAUF=1`) schreibt nie mit.
## Sicherung
- **Wann:** `mc2-backup.timer` täglich 03:30 (+≤5 min); außerdem vor jedem Hermes-Update, vor jedem Zurückspielen und
@@ -383,7 +420,7 @@ Update erneut.
| `~/mission-control-v2` | Checkout von `main` (nur über `deploy.sh` ändern) |
| `~/mission-control-v2/backend/.venv` | Python-Umgebung des Box-Warts (Python 3.14) |
| `~/.config/systemd/user/` | User-Units und Drop-ins |
| `/srv/models/` | Modelle, Box-Wart-Zustand (`mc2-*.json`, darunter `mc2-einstellungen.json` und `mc2-stand.json`), Sicherungen (`mc2-backups/`), Radar-Downloads (`radar/`) |
| `/srv/models/` | Modelle, Box-Wart-Zustand (`mc2-*.json`, darunter `mc2-einstellungen.json` und `mc2-stand.json`), Sicherungen (`mc2-backups/`), Radar-Downloads (`radar/`), Messwerte (`mc2-messwerte/`) |
| `~/.config/systemd/user/mc2-autoupdate.timer.d/zeitfenster.conf` | Update-Zeitfenster aus der Oberfläche (nur MC2 schreibt es) |
| `/etc/llama-swap/config.yaml` | lebende llama-swap-Config (+ `.bak-*`) |
| `/opt/llamacpp-vulkan/`, `/usr/local/bin/llama-server` | Motor (llama.cpp Vulkan) |