Files
mission-control-v2/docs/BETRIEB.md
T

16 KiB
Raw Blame History

Betrieb — Handgriffe, Meldungen, Wächter, Deploy, Sicherung, Notfall

Stand 24.09.2026, Code in main = 75611be. Für Techniker und Agenten. Gilt für die Instanz auf der KI-Box (Rolle box); die Homelab-Instanz ist noch nicht eingerichtet. Die Bedienung für den User steht in BEDIENUNG.md, die Update-Kette in UPDATES.md, das Modell-Radar in RADAR.md.

Handgriffe (SSH auf die Box)

ssh hitonabi@192.168.178.151
export XDG_RUNTIME_DIR=/run/user/$(id -u)              # sonst sieht systemctl --user nichts
systemctl --user status mission-control-2 mc2-gateway mc2-steward
systemctl --user list-timers                            # Radar, Sicherung, Updates, Morgenmeldung, projekte-sync
journalctl --user -u mc2-steward -n 100                 # Wächter; ebenso mc2-radar, mc2-autoupdate, mc2-backup
curl -s http://127.0.0.1:9001/api/health                # Gesamtzustand, Rolle und Instanz
curl -s http://127.0.0.1:9001/api/partner               # Lebenszeichen der anderen Instanz (falls eingerichtet)
curl -s http://127.0.0.1:9010/gw/health                 # Gateway und Motor
bash -lc 'hermes cron list'                             # Hermes-Jobs (hermes ist über SSH nicht im PATH)
tail -n 50 ~/mc2-notify.log                             # was zuletzt gemeldet wurde
tail -n 5 /srv/models/mc2-deploy.log                    # welcher Stand seit wann live ist
sudo journalctl -u llama-swap -n 100                    # Motor (System-Dienst)

Meldungen

  • Ein Weg: bash ~/mission-control-v2/deploy/notify.sh [-d] [-s "[Betreff]"] "Text" legt die Meldung in Lucys Briefkasten und schickt sie an Telegram. Protokoll: ~/mc2-notify.log, je Meldung eine Zeile mit OK telegram, OK telegram direkt, QUEUED für Morgen-Digest oder FALLBACK (…). Den Wortlaut nicht ändern: backend/services/update_verlauf.py liest ihn.
  • Zwei Wege zu Telegram (seit 24.09.): zuerst hermes send. Scheitert das oder fehlt Hermes, geht die Meldung direkt an die Telegram-Bot-API; die Zugangsdaten (TELEGRAM_BOT_TOKEN, TELEGRAM_HOME_CHANNEL, optional TELEGRAM_HOME_CHANNEL_THREAD_ID) liest notify.sh aus der Datei in MC_TELEGRAM_ENV (Standard ~/.hermes/.env). Das Token steht dabei nicht in der Prozessliste. Live bewiesen am 24.09. um 15:41.
  • Nachtruhe: 00:00–06:59 landet alles Nicht-Dringende in ~/.hermes/night-queue.txt. Dringend ist -d, ein Betreff mit „Alarm" oder „Notfall" oder ein Text, der mit „KRITISCH" beginnt.
  • Morgenmeldung: mc2-morgenmeldung.timer (07:00) startet deploy/morgenmeldung.sh. Es schickt eine Nachricht „Guten Morgen, Commander. Heute Nacht gab es N Meldungen" mit höchstens 3500 Zeichen. Drei Versuche im Abstand von 60 s; scheitert Telegram, bleibt der Stapel als night-queue.txt.senden liegen und kommt mit der nächsten Morgenmeldung. Zuletzt Gesendetes: night-queue.txt.zuletzt-gesendet. Das Skript kürzt außerdem ~/mc2-notify.log ab 3 MB auf die letzten 2 MB.
  • Scheitern beide Wege, steht die Meldung mit FALLBACK im Protokoll und geht per wall an die Box-Konsolen (MC_NOTIFY_OHNE_WALL=1 schaltet wall ab).
  • Testen: bash ~/mission-control-v2/deploy/notify.sh -s "[Test]" "Testmeldung"; nachts landet sie in der Warteschlange, mit -d kommt sie sofort.
Betreff Absender Inhalt
[Box-Update] autoupdate.sh, jobs/sonntags-update.sh Ergebnis je Baustein, Wochenbericht, Neustart-Ankündigung; beginnt der Text mit „KRITISCH", ist es dringend
[Box-Problem] Wächter neuer roter Hinweis; nach 6 h erneut mit „Immer noch:"
[Box wieder ok] Wächter ein gemeldeter roter Hinweis ist erledigt
[Homelab-Problem] / [Homelab wieder ok] Wächter der Homelab-Instanz wie oben, sobald diese Instanz läuft
[Modell-Radar] backend/radar_lauf.py ein Kandidat hat den Nachttest bestanden
[Stack-Radar] jobs/stack-radar.sh Samstagsbericht
[Morgenmeldung] morgenmeldung.sh Sammelmeldung der Nacht, 07:00
[Alarm] Deploy deploy.sh Deploy gescheitert, der alte Stand läuft wieder (dringend)
ohne Betreff jobs/news-melden.sh Daily News Report, danach die Sprachnachricht

Wächter (backend/services/waechter.py, im mc2-steward)

Takt jede Minute, der erste 60 s nach dem Start. Ein Befund wird nach 2 Takten zum Hinweis; Timer-, Job-, Platten- und Pin-Befunde sofort, die Partner-Instanz erst nach 5 Takten (MC_WAECHTER_PARTNER_TAKTE, ein Neustart soll kein Alarm sein).

Prüfung Rot Gelb
Dienste (systemd) llama-swap, hermes-gateway, mc2-gateway, mission-control-2 voice-service, lucy-stimme, hermes-builtin-ui
Timer-Läufe mc2-backup, mc2-morgenmeldung, mc2-autoupdate projekte-sync, mc2-radar
Hermes-Jobs fehlgeschlagener Job mit „update" im Namen andere fehlgeschlagene Jobs; Werkzeugfehler im letzten Lauf
Kern (HTTP) Motor, Hirn, Hermes, MC2, Gateway antworten nicht; die Spracherkennung nur, wenn sie nicht schläft –
Platte (MC_DATEN_DIR, auf der Box /srv/models) ab 90 % ab 80 %
Festgehaltene Updates – jeder Pin
Partner-Instanz (nur mit MC_PARTNER_URL) „ antwortet nicht" –
Abgestürzte Prüfung – „Eine Prüfung des Wächters lief nicht"

In der Rolle homelab prüft der Wächter bisher nur Platte und Partner und meldet mit „[Homelab-Problem]".

  • Selbstreparatur: Nur ein abgestürzter Dienst (ActiveState=failed) wird neu gestartet, höchstens 2× je Stunde und Hinweis. Ein gestoppter Dienst (inactive) wird nur gemeldet. Ein schlafender Dienst (inactive und disabled) ist kein Befund.
  • Während eines Updates (ein Prozess autoupdate.sh, update-engine.sh, update-swap.sh oder hermes … update läuft) prüft er Dienste und Kern nicht und repariert nichts. Die Oberfläche zeigt dann „Update läuft".
  • Meldungen: Rote Hinweise gehen an Telegram und in den Briefkasten, bei Fortbestand alle 6 h erneut; nachts gilt die Nachtruhe. Gelbe Hinweise stehen nur in der Oberfläche.
  • Knöpfe am Hinweis: „Neu starten" bzw. „Starten", „Protokoll", „Jetzt erneut laufen lassen" (Timer), „Erneut ausführen" (hermes cron run), „Freigeben" (Pin), „Ausblenden bis zum nächsten Lauf" (Werkzeugfehler eines Jobs; MC2 merkt sich den Lauf in /srv/models/mc2-quittiert.json, hat der nächste Lauf wieder Fehler, erscheint der Hinweis erneut).
  • Der Wächter ist der einzige Schreiber von /srv/models/mc2-waechter.json. Ist sein letzter Takt älter als 5 Minuten, zeigt die Startseite „Wächter schweigt".

Dienste schlafen legen und wecken

  • Schlafen legen: systemctl --user disable --now <unit> (seit 24.09.: box-console, voice-service).
  • Wecken bis zum nächsten Neustart der Box: Knopf „Wecken" unter „Dienste und Protokolle" oder systemctl --user start <unit>.
  • Dauerhaft wecken: systemctl --user enable --now <unit>; für einen Neuaufbau die Unit zusätzlich in AKTIV in deploy/deploy.sh eintragen.

Deploy

Voraussetzung: Der Stand liegt in main auf Gitea (Branch, Prüftor grün, Merge). Dann auf der Box:

bash ~/mission-control-v2/deploy/deploy.sh

Stufe 1 (die bisherige Fassung des Skripts): Sperre gegen einen zweiten Deploy (flock auf $XDG_RUNTIME_DIR/mc2-deploy.lock). Läuft ein Update-Auftrag (Gruppe maintenance in /api/jobs), bricht der Deploy ab — das Update führt Skripte aus diesem Checkout aus. Downloads laufen weiter: Aufträge sind eigene systemd-Einheiten und überleben den Neustart von MC2. Dann den alten Stand merken, git fetch und git merge --ff-only origin/main und die neue Fassung als Stufe 2 starten.

Stufe 2 (die neue Fassung):

  1. pip install aus backend/requirements.txt und backend/requirements-dev.txt.
  2. Prüftor deploy/pruefen.sh.
  3. llama-swap-Config nur, wenn sich deploy/llama-swap.config.yaml in diesem Deploy geändert hat: Sicherung /etc/llama-swap/config.yaml.bak-<Zeit> (die letzten 5 bleiben), dann ersetzen. llama-swap lädt dank --watch-config selbst neu. Weicht die lebende Datei nur ab, gibt es einen Hinweis und sonst nichts.
  4. Alle Repo-Units nach ~/.config/systemd/user/, dazu die Drop-ins mc2-steward.service.d/warmset.conf und mission-control-2.service.d/override.conf; daemon-reload; enable für die Units in AKTIV; Timer starten (den Update-Timer nur, wenn er noch nicht läuft).
  5. Cron-Skripte deploy/jobs/*.sh und *.py nach ~/.hermes/scripts/.
  6. Skills deploy/skills/* nach ~/.hermes/skills/<name_mit_unterstrich>/, abgelöste Skills nach ~/.hermes/skills-archiv/. Plugins deploy/hermes-plugins/* nach ~/.hermes/plugins/; aktiviert werden sie einmalig von Hand, Hermes startet der Deploy nicht neu.
  7. Neustart von mc2-gateway, mission-control-2 und mc2-steward, dann bis zu 60 s Nachprüfung: /api/health, /gw/health, Steward aktiv.

Erfolg: eine Zeile in /srv/models/mc2-deploy.log und „Deploy ist live". Scheitert ein Schritt: git reset --hard auf den alten Stand, llama-swap-Config zurück (falls ersetzt), Dienste neu, Zeile GESCHEITERT im Log und die dringende Meldung „[Alarm] Deploy".

Schalter: MC_DEPLOY_TROTZDEM=1 (trotz laufendem Update-Auftrag), MC_DEPLOY_OHNE_TESTS=1 (Prüftor überspringen, nur im Notfall), MC_DEPLOY_SKIP_SWAP_CONFIG=1 (llama-swap-Config nie anfassen).

Nicht Teil des Deploys: das Frontend bauen (frontend/dist kommt fertig aus Git), die Root-Kopie von warmup.sh, Neustarts von llama-swap und Hermes.

Prüftor deploy/pruefen.sh (am PC vor dem Push, auf der Box im Deploy): Shell-Syntax (bash -n für deploy/*.sh und deploy/jobs/*.sh), Python-Syntax aller versionierten .py außerhalb von frontend/, ruff check . (nur wo ruff installiert ist; requirements-dev.txt bringt nur pytest mit), Import von app, gateway_app, steward und radar_lauf, dann pytest backend/tests. Die Frontend-Prüfungen (npm run lint, npm test, npm run build) laufen nur am PC.

Probelauf auf der Box deploy/probelauf-box.sh (am PC, vor dem Merge nach main): schickt den lokalen HEAD als Abzug nach /tmp auf der Box und lässt dort das Prüftor mit dem Python des Box-Checkouts laufen. Ändert auf der Box sonst nichts. Grund: Unter Linux zeigen sich Wettläufe, die am Windows-PC durchgehen (24.09.).

Sicherung

  • Wann: mc2-backup.timer täglich 03:30 (+≤5 min); außerdem vor jedem Hermes-Update, vor jedem Zurückspielen und per Knopf „Jetzt sichern". Von Hand: bash ~/mission-control-v2/deploy/backup.sh.
  • Wohin: /srv/models/mc2-backups/mc2-state-<Zeit>.tar.gz, Rechte 600 (enthält ~/.hermes/.env), die letzten 14 bleiben. Danach Spiegel per rsync --delete auf den Proxmox-Host (/var/lib/vz/mc2-backups, eigener Schlüssel ~/.ssh/mc2_offsite; Ziel und Schlüssel über MC_BACKUP_OFFSITE und MC_BACKUP_OFFSITE_KEY). Scheitert der Spiegel, gilt die lokale Sicherung trotzdem.
  • Inhalt:
    • aus ~/.hermes: config.yaml, .env, plugins/, cron/, state/; seit 24.09. auch memories/ (Lucys Gedächtnis), SOUL.md, skills/ und scripts/; dazu Reste der früheren Desktop-Anbindung (agent-hooks/, shell-hooks-allowlist.json, desktop-gateway-token, pc-paths.yaml, Drop-in session-token.conf);
    • /etc/llama-swap/config.yaml;
    • der Box-Wart-Zustand /srv/models/mc2-*.json;
    • die Units aus ~/.config/systemd/user/ und /etc/systemd/system/llama-swap.service.d/ (nur zum Nachschlagen, restore.sh spielt sie nicht zurück);
    • Lucys Stimmreferenz ~/.lucy-stimme/app/ref.wav;
    • known-good/: pip freeze je venv, Versionen (OS, Kernel, MC2- und Hermes-Commit, llama.cpp, llama-swap) und die Liste der Modelldateien.
  • Eine Sicherung ist seit 24.09. rund 12 MB groß.
  • Nicht enthalten: Modelle (neu ladbar), Code (Git), venvs, ~/.ssh (auch nicht der Spiegel-Schlüssel).
  • Weitere Schichten: Die Sicherung der Box nach PBS (pbs-backup.timer) ist seit 21.08. aus. PBS sichert die Proxmox-Container, das QNAP macht Snapshots; beides läuft auf den anderen Geräten und ist hier nicht geprüft.

Zurückspielen

  • Per Oberfläche: Updates → Sicherungen → „Zurückspielen". MC2 startet restore.sh --yes <Datei> als eigene systemd-Unit (mc2-restore-<Zeit>), weil restore.sh MC2 selbst stoppt.
  • Per SSH:
cd ~/mission-control-v2
bash deploy/restore.sh --list                     # lokal und auf dem Proxmox-Host
bash deploy/restore.sh --dry-run latest           # zeigt, was passieren würde
bash deploy/restore.sh latest                     # mit Rückfrage; --yes ohne
bash deploy/restore.sh --mit-gedaechtnis latest   # Gedächtnis und Zustand auch überschreiben
bash deploy/restore.sh --pull-offsite             # alle Sicherungen vom Proxmox-Host holen

Ablauf: Sicherheits-Sicherung des jetzigen Stands → Dienste mission-control-2, mc2-gateway, mc2-steward, hermes-gateway stoppen → Hermes-Config, .env, Plugins, cron/, state/, llama-swap-Config und die Desktop-Reste zurück → Gedächtnis, SOUL.md, Skills, Cron-Skripte und mc2-*.json nur, wenn sie fehlen oder mit --mit-gedaechtnis → Dienste starten → /api/health. Fehlt eine Sicherung lokal, holt restore.sh sie vom Proxmox-Host. Sicherungen von vor dem 27.08. enthalten noch das Verzeichnis des abgelösten Gedächtnis-Dienstes; es wird nicht zurückgespielt.

Notfall

Box tot oder Oberfläche weg:

  1. Strom und Netz prüfen, die Box einmal per Knopf neu starten. Alles startet von selbst (systemd, Linger). Nach 2–3 Minuten http://192.168.178.151:9001 öffnen.
  2. Oberfläche immer noch weg: per SSH systemctl --user status mission-control-2 und journalctl --user -u mission-control-2 -n 100. Hilft ein Neustart der Dienste nicht: bash ~/mission-control-v2/deploy/restore.sh latest.
  3. Totalschaden (neue Platte, neue Hardware): WIEDERAUFBAU.md.

Deploy kaputt: deploy.sh rollt selbst zurück. Von Hand: den vorigen Commit aus /srv/models/mc2-deploy.log nehmen, git -C ~/mission-control-v2 reset --hard <commit> und systemctl --user restart mc2-gateway mission-control-2 mc2-steward.

llama-swap-Config kaputt: ls -t /etc/llama-swap/config.yaml.bak-*, die passende Sicherung nach /etc/llama-swap/config.yaml kopieren; llama-swap lädt selbst neu. Ältere Stände stecken in jeder Sicherung.

Motor startet keine Modelle: sudo journalctl -u llama-swap -n 100. Nach einem Engine-Sprung ist die typische Ursache ein gestrichenes Flag (wissen/FALLEN.md). Den vorigen Build hebt update-engine.sh in /opt/llamacpp-vulkan.bak auf, die vorige llama-swap-Version update-swap.sh in /usr/local/bin/llama-swap.bak.

Hermes kaputt: journalctl --user -u hermes-gateway -n 100, dann bash ~/mission-control-v2/deploy/hermes-postcheck.sh. Rückweg wie in UPDATES.md: alter Commit in ~/.hermes/hermes-agent, Config aus der letzten Sicherung, systemctl --user restart hermes-gateway.

Festgehaltener Baustein: Knopf „Freigeben" (Startseite oder Updates-Seite); der nächste Sonntagslauf versucht das Update erneut.

Wo was liegt (Box)

Pfad Inhalt
~/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), Sicherungen (mc2-backups/), Radar-Downloads (radar/)
/etc/llama-swap/config.yaml lebende llama-swap-Config (+ .bak-*)
/opt/llamacpp-vulkan/, /usr/local/bin/llama-server Motor (llama.cpp Vulkan)
/usr/local/bin/llama-swap, /usr/local/bin/llama-swap-warmup.sh Router und Vorwärm-Skript (Root-Kopie)
~/.hermes/ Hermes: Code (hermes-agent/), config.yaml, .env, SOUL.md, memories/, skills/, scripts/, cron/, logs/
~/.lucy-stimme/ Lucys Stimme (pocket-tts), Referenz app/ref.wav
~/.voice/ Umgebung der Spracherkennung (voice_service/install.sh)
~/projekte/ Spiegel der Gitea-Repos (projekte-sync)
~/mc2-notify.log, ~/.hermes/night-queue.txt Meldeprotokoll, Nacht-Warteschlange