19 KiB
Konzept: Bare-Metal-Wiederaufbau + First-Run-Wizard (VOLLSTÄNDIG)
Zweck: Plan für den „hard crash"-Fall — die Box (
tobisniceaiarbeitstier, Ubuntu 26.04, AMD Ryzen AI MAX+ 395 / gfx1151, 122 GB RAM) muss von null wiederherstellbar sein. Anspruch: ALLES ist erfasst — Engine, Hermes-Konfig 1:1, 3D-Avatare, Voice/Klonstimme, Memory, Browser, MCP, Skills, Secrets. Pro Komponente entscheidet der Nutzer im Wizard: 1:1 zurück · neu/Default · weglassen.Dieses Dokument ist die Spezifikation für eine künftige Implementierungs-Session — es baut noch nichts. Stand: 2026-06-28.
1. Leitprinzip: 1:1 ODER modular — der Nutzer wählt
Der Wizard behandelt jede Komponente als eigene Kachel mit drei Modi:
| Modus | Bedeutung |
|---|---|
| 📦 1:1 aus Backup | Exakter alter Zustand wird zurückgespielt (Configs, Daten, Klonstimme, Avatare). |
| 🆕 Neu / Default | Frische Installation mit sinnvollen Defaults (z.B. entfesseltes Hermes-Profil, Default-Avatar). |
| ⏭️ Weglassen | Komponente wird (vorerst) nicht installiert. |
Ein „Alles 1:1"-Knopf wählt überall 📦 (wo ein Backup existiert), sonst 🆕. So bekommt der Nutzer entweder den exakten alten Stand oder kann gezielt entrümpeln.
2. Was es schon gibt (wiederverwenden)
| Asset | Datei | Deckt ab |
|---|---|---|
| Code-Deploy | deploy/deploy.sh |
git pull + venvs + Units + Restart. Setzt Engine/llama-swap/Dirs/venvs voraus. |
| Zustands-Backup | deploy/backup.sh + mc2-backup.{service,timer} |
Aktuell (live): mem0, ~/.hermes/{config.yaml,.env,plugins}, llama-swap-config. Retention 14. Für echtes 1:1 zu erweitern — fertiges Snippet in Anhang B (§5). |
| Restore | deploy/restore.sh |
Spielt Tarball zurück (mit Pre-Restore-Sicherung). |
| Engine | deploy/provision-engine.sh |
llama.cpp Vulkan/RADV-Build (root). |
| Voice-Setup | voice_service/install.sh |
venv + Piper-Binary + dt. Piper-Stimmen + Chatterbox (best-effort). |
| Updates | deploy/update-engine.sh, update-swap.sh |
Laufende Engine/Router-Updates. |
| Postchecks | deploy/stack-postcheck.sh, hermes-postcheck.sh |
Funktionsprüfung → Wizard-Verifikationsschritt. |
3. VOLLSTÄNDIGER Komponenten-Katalog
Scan-verifiziert (2026-06-28) gegen
backend/config.py, allebackend/services/*&routers/*,frontend/src/{nav.ts,views,components/voice},voice_service/app.py,mem0_service/,deploy/*. Alle persistenten Schreibpfade, Dienste, Secrets und Env-Vars sind unten erfasst.
Legende Restore-Quelle: 📦 = aus Backup-Tarball · ⬇️ = Re-Download/Install (Skript) · 🌐 = Git ·
🔑 = Secret (Nutzer/Generieren) · 🆕 = im Wizard neu gewählt.
„Im Backup?" = deckt der aktuelle backup.sh es ab.
A · OS & System (L0, root/sudo, einmalig)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
Ubuntu 26.04, User hitonabi, enable-linger |
— | ⬇️ manuell | n/a |
| System-Pakete: python3.14+venv, git, curl, jq, ttyd, uv | — | ⬇️ apt/curl | nein |
| Vulkan-Stack: mesa-vulkan-drivers, libvulkan1, vulkan-tools | — | ⬇️ apt | nein |
Chrome-Libs (Browser): agent-browser install --with-deps |
— | ⬇️ apt | nein |
Verzeichnis-Layout: /srv/models/{,mem0,mc2-backups,drafts}, /etc/llama-swap/ |
— | ⬇️ mkdir+chown | nein |
B · Inferenz-Engine + Router (L1, root)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
llama.cpp (Vulkan) → llama-server |
/opt/llamacpp-vulkan, /usr/local/bin/llama-server |
⬇️ provision-engine.sh / update-engine.sh (ggml-org Release) | nein (re-build) |
llama-swap Binary (Router :8080) |
/usr/local/bin/llama-swap |
⬇️ bekannt: mostlygeek/llama-swap-Release (Rezept in update-swap.sh) |
nein (re-download) |
| llama-swap systemd-System-Unit | /etc/systemd/system/llama-swap.service (+ .d/ Drop-ins) |
⬇️ Bootstrap legt sie an — kompletter Unit-Inhalt in Anhang A (von der Box abgegriffen; Drop-ins via provision-engine.sh) | nein |
| llama-swap-Config (Modelle/Rollen) | /etc/llama-swap/config.yaml |
📦 | ja |
| Draft-Modelle (Spec-Decoding) | /srv/models/drafts/ |
⬇️ Re-Download | nein |
C · MC2-App (L2, userspace)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| MC2-Code | ~/mission-control-v2 |
🌐 Git (Gitea) | n/a |
| Backend-venv (Python 3.14) | backend/.venv |
⬇️ deploy.sh | nein (rebuild) |
Frontend (gebaut, inkl. 3D-Avatar avatar.vrm) |
frontend/dist, frontend/public/avatar.vrm |
🌐 Git | n/a |
systemd-User-Dienst mission-control-2 (:9001) |
~/.config/systemd/user/ |
⬇️ deploy.sh | nein |
D · 3D-Avatar (Sprechen-Tab)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| Default-Avatar (VRM) | frontend/public/avatar.vrm (→ dist) |
🌐 Git | n/a |
| Renderer | frontend/src/components/voice/Avatar3D.tsx |
🌐 Git | n/a |
| Eigene/zusätzliche Avatare (falls Nutzer welche ablegt) | TODO: Ablageort definieren (z.B. /srv/models/avatars/ + DB-Verweis) |
📦/🆕 | nein (Lücke) |
Heute ist der Avatar fest (
avatar.vrm, kommt mit dem Git-Frontend zurück). Wenn künftig Nutzer-Avatare hochgeladen werden, brauchen sie einen persistenten Ablageort, der ins Backup geht.
E · Voice-Sidecar (STT + TTS + Klonstimme)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| Voice-venv (Python 3.12) | ~/.voice/venv |
⬇️ install.sh | nein (rebuild) |
| STT (faster-whisper Modell) | ~/.voice/ (Cache) |
⬇️ install.sh / 1. Start | nein |
| Piper-Binary + dt. Stimmen (thorsten/kerstin) | ~/.voice/piper, ~/.voice/voices |
⬇️ install.sh | nein |
| Chatterbox (Premium-TTS, CPU-torch) | venv | ⬇️ install.sh (best-effort) | nein |
| Klonstimme / Voice-Referenz-Audio (Nutzer) | ~/.voice/refs/ref.wav (VOICE_REFS_DIR, /api/voice/reference) |
📦 | nein → Anhang B |
| ElevenLabs-Key | ~/.hermes/.env |
🔑 | ja |
| Stimm-/Lautstärke-Wahl | Browser-localStorage (pro Gerät) |
🆕 client | n/a |
Dienst voice-service (:8650) |
systemd-User | ⬇️ deploy.sh | nein |
F · Mem0 (Langzeitgedächtnis)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| Mem0-venv (Python 3.12, uv) | ~/.mem0/venv |
⬇️ deploy.sh | nein (rebuild) |
| Gedächtnis-Daten (Chroma + history.db) | /srv/models/mem0/ |
📦 | ja |
| Hermes-Memory-Plugin | ~/.hermes/plugins/mc2-memory/ |
📦/🌐 | ja |
Dienst mem0-service (:8765) |
systemd-User | ⬇️ deploy.sh | nein |
G · Hermes-Agent (das Herz)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| Hermes-Code | ~/.hermes/hermes-agent |
🌐 Git (NousResearch) | nein (re-clone) |
| Bundled Node v22 | ~/.hermes/node/bin |
⬇️ (kommt mit Hermes) | nein |
| Hermes-venv | ~/.hermes/hermes-agent/venv |
⬇️ rebuild | nein |
config.yaml 1:1 (Toolsets, MCP, Engine, Browser, Personalities, alles) |
~/.hermes/config.yaml |
📦 | ja |
.env (Secrets: TELEGRAM_BOT_TOKEN, API_SERVER_KEY, ElevenLabs …) |
~/.hermes/.env |
📦/🔑 | ja |
| Plugins | ~/.hermes/plugins/ |
📦 | ja |
| Skills (eigene) | ~/.hermes/skills/ (45M; .hub-Cache re-downloadbar) |
📦 | nein → Anhang B (ohne .hub) |
| Sessions/History (optional) | ~/.hermes/sessions/ (856K) |
📦 | nein → Anhang B |
| Checkpoints (optional) | ~/.hermes/checkpoints/ (existiert nicht) |
⏭️ skip | nein |
| Token-/Ersparnis-Statistik | ~/.hermes/token_stats.json |
📦 | nein → Anhang B |
Dienst hermes-gateway (:8642) |
systemd-User | ⬇️ | nein |
Hermes-Terminal (ttyd → hermes chat, :7681) |
systemd-User hermes-terminal |
⬇️ deploy.sh (+ttyd apt) | nein |
H · MCP-Server (4)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
mission-control-memory, -stack (MC2-venv) |
~/mission-control-v2/mcp/*.py |
🌐 Git | über config.yaml |
hermes-pc-control, hermes-web-fetch (Hermes-venv) |
dito | 🌐 Git | über config.yaml |
| MCP-Verdrahtung | ~/.hermes/config.yaml → mcp_servers |
📦 | ja |
I · Browser-Stack
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| agent-browser (npm global) | ~/.local/..., symlink ~/.hermes/node/bin |
⬇️ npm i -g | nein |
| Chrome (engine) + System-Libs | ~/.agent-browser/browsers/ + apt-Libs |
⬇️ install --with-deps | nein |
| lightpanda (optional, leicht) | ~/.local/bin/lightpanda |
⬇️ Download | nein |
| Browser-Verdrahtung (engine=chrome, toolset) | ~/.hermes/config.yaml |
📦 | ja |
J · Modelle (GGUF — der große Brocken)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| GGUF-Modelle (Brain, fast, heavy, coder, vision, embedding …) | /srv/models/ |
⬇️ Re-Download aus llama-swap-Manifest | nein (zu groß, bewusst) |
K · Extern (anderer Rechner)
| Komponente | Ort | Quelle | Im Backup? |
|---|---|---|---|
| PC-Executor (Windows) | client/hermes-pc/ → Scheduled Task |
🌐 Git + Task | n/a (anderer Host) |
Hermes-WebUI (nesquena, optional, :8787) |
~/hermes-webui |
⬇️ git clone | nein |
4. Ziel-Architektur
4.1 deploy/bootstrap.sh — orchestrierter From-Zero-Lauf
- Idempotent & resumierbar (Schritt-Marker in
~/.mc2-bootstrap.state). - Getrennt nach sudo-Bedarf:
bootstrap-root.sh(L0+L1, bewusst mit sudo) +bootstrap.sh(L2+, sudo-frei = Kern istdeploy.sh). Passt zum Nordstern „Runtime ohne sudo". - Mündet in den Wizard: startet MC2 im First-Run-Modus, gibt Wizard-URL aus.
Phasen: 0 Vorflug → 1[sudo] System+Dirs → 2[sudo] Engine+llama-swap → 3 Code(MC2+Hermes+Node) → 4 venvs(backend/mem0/voice/hermes) → 5 Browser → 6 deploy.sh(Units/enable/restart) → 7 Restore(optional) → 8 Wizard hoch + postcheck.
4.2 First-Run-Wizard (browserbasiert, von MC2 serviert)
MC2 erkennt unkonfigurierten Zustand → Frontend-Route /setup statt Dashboard. Schritte:
- Systemcheck — Live-Ampel je Komponente aus §3 (
GET /api/setup/status+…/system/services). - Restore-Quelle wählen — Backup-Tarball erkennen → globaler Modus „Alles 1:1" / „selektiv" / „frisch".
- Komponenten-Auswahl (Kernstück) — pro Katalog-Eintrag aus §3 eine Kachel mit 📦/🆕/⏭️ (siehe §1). Zeigt Größe + ob Backup-Daten vorhanden.
- Netzwerk & Identität — Box-IP (→
HERMES_TERMINAL_URL,PC_EXECUTOR_URL), Hostname. - Secrets 🔑 —
TELEGRAM_BOT_TOKEN, erlaubte User-ID,API_SERVER_KEY(oder generieren), ElevenLabs-Key →~/.hermes/.env(chmod 600). Bei 📦 vorbefüllt aus Backup. - Hermes-Profil — Brain-Alias + Toolset-Profil (Default = entfesselt: vision/tts/memory/browser
an, image_gen/video aus — siehe project-hermes-setup). Bei 📦 = exakte alte
config.yaml. - Avatar & Voice — Avatar wählen (Default-VRM oder eigener), Stimme/Klonstimme (📦 Referenz-Audio zurück, oder neu aufnehmen/hochladen).
- Modelle — aus llama-swap-Manifest automatisch nachladen (
POST /api/models/install, FortschrittGET /api/jobs) ODER geführte Discover-Neuauswahl. Reihenfolge: Brain → heavy → Rest. - Externe Checkliste — PC-Executor (Windows-Task), Hermes-WebUI als Haken.
- Verifikation & Abschluss —
stack-postcheck.sh+hermes-postcheck.sh→ grün/rot-Liste → Dashboard.
Technik: neuer Router backend/routers/setup.py
(GET /api/setup/status, POST /api/setup/{secrets,network,hermes,components,finish}).
First-Run-Gate: MC2 prüft beim Boot Marker ~/.mc2-setup-done bzw. Pflicht-Secrets → leitet auf /setup.
5. Backup-Scope für echtes 1:1 ERWEITERN (umzusetzen — Snippet in Anhang B)
Der aktuelle backup.sh (live auf der Box, unverändert) reicht für „1:1" nicht. Für die Bau-Session
liegt das fertige Erweiterungs-Snippet in Anhang B — es ergänzt den Tarball um:
- Voice-Klonstimme →
~/.voice/refs/(ref.wav) - Token-/Ersparnis-Statistik →
~/.hermes/token_stats.json - Hermes-Skills →
~/.hermes/skills/(re-downloadbarer.hub-Cache pertar --excludeausgelassen) - Hermes-Sessions/History →
~/.hermes/sessions/
Restore soll skills/sessions mergen (frisch geladenen .hub nicht überschreiben) und voice-service
mit neu starten.
Offen bleibt: eigene Avatare (sobald Upload existiert — Ablageort heute undefiniert, siehe §3·D).
Bewusst NICHT im Backup (re-downloadbar/rebuildbar): Piper-Stimmen (install.sh), .hub-Skill-Cache,
/srv/models/mc2-discover.json (Cache), /srv/models/mc2-memory.db (Legacy-Migration), alle venvs, GGUF-Modelle.
→ Aufgabe der Bau-Session: backup.sh + restore.sh um diese Pfade erweitern (mit klarer
„opt-in für große/optionale Teile"-Logik), und den MANIFEST-Inhalt entsprechend.
6. Secrets-Strategie
- Single Source:
~/.hermes/.env(chmod 600), im Tarball (selbst 600). - Rebuild ohne Backup → Wizard-Schritt 5 erzeugt sie.
API_SERVER_KEYgenerierbar; Telegram/ElevenLabs liefert Nutzer. - Nie ins Git, nie in Logs, nie in die MC2-DB. Off-Box-Spiegelung des Tarballs noch offen (mc2-backup-restore).
7. Modell-Strategie
- A (empfohlen):
/etc/llama-swap/config.yaml(im Backup) listet alle Modelle → Wizard leitet Repos/Quants ab und lädt automatisch (/api/models/install). „Ein Klick, lädt über Nacht." - B: geführte Discover-Neuauswahl je Rolle. Reihenfolge Brain → heavy → Rest, danach
warmup.sh.
8. Implementierungs-Reihenfolge (neue Session)
- ✅ Box-Verifikation erledigt (2026-06-28, nur gelesen — nichts verändert): llama-swap.service-Inhalt in Anhang A; skills/sessions/refs/token_stats existieren (Pfade in §3 verifiziert); Backup-Erweiterung als fertiges Snippet in Anhang B. Keine offenen Box-Fragen mehr außer §10·3–6. → mit Schritt 2 starten.
backup.sh/restore.shum die 1:1-Lücken erweitern (§5).deploy/bootstrap.sh+bootstrap-root.sh(Phasen, State-Marker); llama-swap-Install skripten.backend/routers/setup.py+ First-Run-Gate.- Frontend
/setup-Wizard (Schritte 1–10), Komponenten-Auswahl als Kernstück; bestehende Views (Cockpit/AgentView/Sprechen) wiederverwenden. - Modell-Restore-aus-Manifest.
- Abnahme in frischer VM (§9).
Vorschlag: 2–4 zuerst (Skelett lauffähig), Wizard danach. Branch + PR.
9. Abnahmekriterien
- Frisches Ubuntu 26.04 →
bootstrap-root.sh+bootstrap.sh→ laufender Stack, kein Spezialwissen. - Postchecks grün; Telegram, Voice (inkl. Klonstimme bei 📦), 3D-Avatar, Browser funktionieren.
- „Alles 1:1" stellt mem0, Hermes-config.yaml, Secrets, Klonstimme, Skills exakt wieder her.
- Selektiver Modus: einzelne Komponenten ⏭️ überspringbar, Stack läuft trotzdem.
- Idempotenz: zweiter Lauf = No-op.
10. Offene Entscheidungen (vor dem Bau)
llama-swap systemd-Unit-Inhalt→ geklärt: kompletter Unit in Anhang A (in der Bau-Session anlegen).Voice-Referenz-Audio-Ort→ geklärt:~/.voice/refs/(Backup-Snippet in Anhang B, in der Bau-Session umsetzen).- Eigene Avatare: künftiger Upload-/Ablage-Mechanismus + Backup-Pfad (einziger offener 1:1-Daten-Punkt).
- Off-Box-Backup-Ziel (NAS/2. Platte/Cloud) — mc2-backup-restore.
- Python 3.14 auf frischem Ubuntu beschaffen (deadsnakes?).
- Bootstrap-sudo-Modell: getrenntes
bootstrap-root.sh(empfohlen) vs. interaktives sudo.
11. Referenzen
backend/config.py, project-mc2-architecture, project-stack-state- project-hermes-setup,
docs/HERMES_SETUP.md(entfesseltes Profil, Browser, PC-Executor) - voice-sprechen-feature (Voice + 3D-Avatar), mem0-memory-architecture, mc2-backup-restore
deploy/{deploy,backup,restore,provision-engine,stack-postcheck,warmup}.sh,voice_service/install.sh
Anhang A — llama-swap.service (1:1 von der Box abgegriffen, 2026-06-28)
Base-Unit nach /etc/systemd/system/llama-swap.service (root). User/GFX sind boxspezifisch
(hitonabi, gfx1151 → HSA 11.5.1) — auf anderer Hardware anpassen. Die .d/-Drop-ins
(vulkan.conf, warmup.conf) legt provision-engine.sh an.
[Unit]
Description=llama-swap (lokaler LLM Router)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=hitonabi
Environment=HSA_OVERRIDE_GFX_VERSION=11.5.1
Environment=PATH=/usr/local/bin:/usr/bin:/bin
ExecStart=/usr/local/bin/llama-swap --config /etc/llama-swap/config.yaml --listen 0.0.0.0:8080 --watch-config
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/llama-swap.service.d/vulkan.conf
[Service]
Environment=LD_LIBRARY_PATH=/opt/llamacpp-vulkan
# /etc/systemd/system/llama-swap.service.d/warmup.conf
[Service]
ExecStartPost=-/usr/local/bin/llama-swap-warmup.sh
Erstinstall-Reihenfolge: bash deploy/update-swap.sh (Binary) → Unit kopieren →
sudo bash deploy/provision-engine.sh (Engine+Drop-ins) → sudo systemctl enable --now llama-swap.
Anhang B — Backup-Scope-Erweiterung für echtes 1:1 (fertiges Snippet)
In deploy/backup.sh ergänzen (Variablen oben: VOICE="${VOICE_HOME:-$HOME/.voice}",
Stage zusätzlich "$STAGE/voice"):
# 1:1-Erweiterung (scan-verifiziert 2026-06-28):
[ -f "$HERMES/token_stats.json" ] && cp -a "$HERMES/token_stats.json" "$STAGE/hermes/" || true
[ -d "$HERMES/skills" ] && cp -a "$HERMES/skills" "$STAGE/hermes/skills" || true
[ -d "$HERMES/sessions" ] && cp -a "$HERMES/sessions" "$STAGE/hermes/sessions" || true
[ -d "$VOICE/refs" ] && cp -a "$VOICE/refs" "$STAGE/voice/refs" || true
tar-Aufruf um den re-downloadbaren Skill-Cache erleichtern:
tar --exclude='./hermes/skills/.hub' -czf "$OUT" -C "$STAGE" .
In deploy/restore.sh spiegelbildlich (skills/sessions mergen, nicht ersetzen) und
voice-service mit neustarten:
VOICE="${VOICE_HOME:-$HOME/.voice}"
SERVICES="mem0-service voice-service mission-control-2 hermes-gateway"
[ -f "$STAGE/hermes/token_stats.json" ] && cp -a "$STAGE/hermes/token_stats.json" "$HERMES/"
[ -d "$STAGE/hermes/skills" ] && { mkdir -p "$HERMES/skills"; cp -a "$STAGE/hermes/skills/." "$HERMES/skills/"; }
[ -d "$STAGE/hermes/sessions" ] && { mkdir -p "$HERMES/sessions"; cp -a "$STAGE/hermes/sessions/." "$HERMES/sessions/"; }
[ -d "$STAGE/voice/refs" ] && { mkdir -p "$VOICE/refs"; cp -a "$STAGE/voice/refs/." "$VOICE/refs/"; }