diff --git a/README.md b/README.md index df4c14a..b503412 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ WireGuard-Isolation. bewusst nicht standardmäßiges Uncensored-Spezialprofil - `/ultra`: getestetes text-only 256K-Profil (IQ4_XS Pure, beide GPUs, 80:20); etwa 68 Token/s und erfolgreicher 220K-Prompt-Fülltest -- Open WebUI als einzige normale Oberfläche +- Open WebUI als einfache Chat-Oberfläche und Hermes Agent als zweite, + agentische Oberfläche für lange, werkzeugintensive Aufgaben - native OpenWebUI-Websuche für allgemeine Recherche; SearXNG/Web-MCP als manueller Spezialadapter ohne externen API-Schlüssel - zentrale MCP-Werkzeugebene: getrennte Container für Athena-Plattformwissen, @@ -51,6 +52,8 @@ Neustart an; danach wird derselbe Befehl erneut ausgeführt. | Dienst | Erreichbarkeit | Zweck | |---|---|---| | Open WebUI | `:8080` | Chat und Administration | +| Hermes Dashboard | `:9119` | agentischer Chat, Sitzungen, Skills und MCP-Verwaltung | +| Hermes API | `:8642` | authentifizierte Agent-API | | Profile Router | `:8081` | OpenAI-kompatible API, Profilwahl | | llama.cpp | nur Docker-intern | Inferenz und integrierte Vision | | Profile Controller | nur Docker-intern | eng begrenzter Profil-/FLUX-Hot-Swap | @@ -70,6 +73,11 @@ Pi, Hermes und andere Clients verwenden die direkten WireGuard-Ports aus Infrastruktur-Secrets. Die Bildanalyse ist Bestandteil des multimodalen Qwen-Modells. +Hermes läuft als eigener, per OCI-Digest gepinnter Container direkt neben +OpenWebUI. Beide sprechen dieselbe Router-API und damit dieselben Qwen-Profile; +Hermes ist kein zusätzlicher Modellserver. Seine Sitzungen, Skills, +Konfiguration und isolierte Arbeitsfläche liegen unter `/data/hermes`. + Open WebUI erhält über die vorgesehenen statischen Anpassungspunkte ein globales Dark-Theme namens **Midnight Aurora**. CSS und Start-Loader liegen unter `platform/openwebui/theme/` und werden schreibgeschützt in den Container @@ -123,6 +131,7 @@ config/install.env.example öffentliche Konfigurationsvorlage compose.yaml produktiver Stack platform/docker/llama-cpp/Dockerfile CUDA-llama.cpp-Build platform/docker/profile-controller/ sichere Profilsteuerung +platform/hermes/ Hermes-Konfiguration und Installer router/ OpenAI-kompatibler Profile Router ``` diff --git a/compose.yaml b/compose.yaml index ceb67fc..c0e8cdb 100644 --- a/compose.yaml +++ b/compose.yaml @@ -784,6 +784,33 @@ services: condition: service_healthy security_opt: ["no-new-privileges:true"] + hermes: + image: ${HERMES_IMAGE:-nousresearch/hermes-agent@sha256:143bdb9086bb2db645346179f11091e621ef6b7f4f9e5049ae7454bfeb3a0495} + container_name: mike-ai-hermes + restart: unless-stopped + command: [gateway, run] + env_file: + - /data/hermes/.env + volumes: + - /data/hermes:/opt/data + - /data/hermes/workspace:/workspace + environment: + HERMES_HOME: /opt/data + dns: ["${AI_DNS:-1.1.1.1}"] + networks: [frontend, tools, tools-egress] + depends_on: + wireguard-gateway: + condition: service_healthy + router: + condition: service_healthy + security_opt: ["no-new-privileges:true"] + healthcheck: + test: [CMD, curl, -fsS, "http://127.0.0.1:8642/health"] + interval: 15s + timeout: 5s + retries: 20 + start_period: 45s + networks: frontend: internal: false diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 9321d4c..c488a0b 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -15,6 +15,8 @@ Heimnetz / VPN-Clients | :8080 Open WebUI :8081 Profile Router API + :9119 Hermes Dashboard + :8642 Hermes Agent API :8201-08 direkte MCP-Endpunkte | Docker-intern @@ -42,6 +44,7 @@ Heimnetz / VPN-Clients |---|---|---| | WireGuard Gateway | VPN-Adresse, feste Portmatrix | Tunnel und direkte TCP-Proxys für UI, API und Werkzeuge | | Open WebUI | nur Docker-intern | Chat-Oberfläche | +| Hermes Agent | nur Docker-intern; Dashboard/API über VPN-Gateway | agentische Oberfläche, Skills, Sitzungen und MCP-Client | | Profile Router | nur Docker-intern | OpenAI-API und Profilwahl | | Profile Controller | nein | startet ausschließlich fest erlaubte Profile | | llama.cpp Profile | nein | Inferenz, Tool Calling, integrierte Vision | diff --git a/docs/BARE_METAL_RECOVERY.md b/docs/BARE_METAL_RECOVERY.md index 2828920..01c77ab 100644 --- a/docs/BARE_METAL_RECOVERY.md +++ b/docs/BARE_METAL_RECOVERY.md @@ -12,6 +12,7 @@ Dokumentation. | Qwen-, Projektor- und Bildmodelle | dokumentierte URLs und SHA256 in `config/install.env.example` beziehungsweise der gesicherten Installationskonfiguration | | Navidrome-MCP 2.2.0 samt llama.cpp-Schemafix | `platform/mcp/Dockerfile.navidrome` | | OpenWebUI-Benutzer, Chats, Arbeitsbereichsmodelle, Filter und Verbindungen | verschlüsseltes Recovery-Bundle | +| Hermes-Sitzungen, Skills, Konfiguration und Arbeitsfläche | `/data/hermes` im verschlüsselten Recovery-Bundle | | Router-, WireGuard-, HA-, ARR-, Unraid- und Navidrome-Zugangsdaten | verschlüsseltes Recovery-Bundle | | Last.fm API-Key | `/etc/mike-ai/navidrome-mcp.env` im verschlüsselten Bundle | | Navidrome-Bibliothek und Benutzer | bleiben auf dem separaten Unraid-Server | @@ -54,6 +55,8 @@ Das Skript nimmt ausschließlich auf: - das produktive Dokumentations-Overlay unter `/opt/mike-ai/stack/docs`, - Vorschläge, Sicherungen und Auditstatus des Platform Context MCP unter `/data/mike-ai-platform-context`, +- Hermes-Sitzungen, Skills, Konfiguration und Arbeitsfläche unter + `/data/hermes`, - das vollständige OpenWebUI-Datenvolume, - Prüfsummen und den eingesetzten Git-Commit. diff --git a/docs/COMPONENTS.md b/docs/COMPONENTS.md index 834f915..77d2520 100644 --- a/docs/COMPONENTS.md +++ b/docs/COMPONENTS.md @@ -6,6 +6,7 @@ | llama.cpp | ggml-org/llama.cpp, festgeschriebener Commit | Buildskript und Commit | Kern | | Qwen-Profile | `platform/profiles/` | vollständig, Modelle ausgenommen | Kern | | MCP-Tool-Stack | `platform/mcp/compose.yaml` | vollständig | Kern | +| Hermes Agent | NousResearch Hermes Agent 0.20.5, OCI-Digest gepinnt | eigener Clientcontainer, Dashboard/API, persistente Daten unter `/data/hermes` | Kern | | Websuche | SearXNG + TinySearch/Crawl4AI | intern, ohne veröffentlichten Port | Kern | | Allgemeines Web | OpenWebUI native Suche; TinySearch-Upstream-MCP auf VPN-Port 8203 für andere Clients | site-unabhängig; keine neue Implementierung pro Website | Kern | | Frühere Web-MCP-Fassade | `platform/web-search/web_search_mcp.py` | nur Rollback-Profil `legacy-web` | Altbestand | diff --git a/docs/CURRENT_REFERENCE.md b/docs/CURRENT_REFERENCE.md index 8dffc1d..ffbc3ac 100644 --- a/docs/CURRENT_REFERENCE.md +++ b/docs/CURRENT_REFERENCE.md @@ -83,6 +83,20 @@ Der Router übernimmt: - Piper als automatischer CPU-Fallback - Zustands- und Modellendpunkte +## Hermes Agent + +- Container: `mike-ai-hermes` +- Version: 0.20.5, offizielles Image per OCI-Digest gepinnt +- Standardmodell: `qwen-medium`, 160.000 Kontext, über den Profile Router +- Dashboard: WireGuard-Port 9119 mit Basic-Auth +- Agent-API: WireGuard-Port 8642 mit eigenem Bearer-Key +- persistenter Zustand: `/data/hermes` +- lokales Terminal: ausschließlich `/data/hermes/workspace` im Container +- MCPs: Athena-Plattform, Athena-Operator, allgemeines Web, GitHub, Home + Assistant, ARR, Navidrome und ein gemeinsamer MUA-Unraid-Zugang +- kein Docker-Socket, kein Host-Root-Mount und keine Veröffentlichung auf der + Universitätsadresse + ## Vision | Bereich | Referenz | diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 8f3dd0b..decd38c 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -63,6 +63,8 @@ werden nicht ausgegeben. Sie liegen root-only unter `/etc/mike-ai`. - Open WebUI: `http://:8080` - Router: `http://:8081` +- Hermes Dashboard: `http://:9119` +- Hermes API: `http://:8642` - SSH fallback: `ssh root@` (key-only, forwarded to host sshd) - llama.cpp-WebUI: absichtlich deaktiviert und nicht veröffentlicht @@ -72,9 +74,23 @@ sudo docker inspect -f '{{.State.Health.Status}}' mike-ai-wireguard-gateway sudo docker compose --env-file /etc/mike-ai/stack.env \ -f /opt/mike-ai/stack/compose.yaml ps curl http://:8081/health +curl http://:8642/health ssh -o BatchMode=yes root@ true ``` +Hermes verwendet standardmäßig `qwen-medium` mit 160K Kontext und dieselbe +Router-API wie OpenWebUI. Das Dashboard meldet sich mit Benutzer `michael` an; +das zufällig erzeugte Kennwort wird ausschließlich lokal angezeigt: + +```bash +sudo cat /etc/mike-ai/hermes-dashboard-password +``` + +Der Schlüssel der Agent-API liegt entsprechend unter +`/etc/mike-ai/hermes-api-key`. Beide Werte gehören weder in Git noch in Chats. +Hermes' lokales Terminal sieht nur `/data/hermes/workspace` im Container. Für +Athena und Unraid verwendet es die dokumentierten Operator-/MUA-MCPs. + Der SSH-Fallback lauscht ausschließlich auf der IPv4-Adresse von `wg0` im WireGuard-Gateway-Container. Er wird nicht als Docker-Port auf dem Standort-Interface veröffentlicht. Das Gateway leitet die Verbindung an den diff --git a/docs/PLATFORM_OVERVIEW.md b/docs/PLATFORM_OVERVIEW.md index 6b5853c..a611c76 100644 --- a/docs/PLATFORM_OVERVIEW.md +++ b/docs/PLATFORM_OVERVIEW.md @@ -7,7 +7,8 @@ operative Änderungen gilt zusätzlich `QWEN_OPERATOR_CONTEXT.md`. Athena ist ein selbst betriebener, datenschutzorientierter KI-Host. Er steht physisch an einem entfernten Standort ohne KVM und wird ausschließlich remote -administriert. Open WebUI ist die Benutzeroberfläche. Ein eigener Profile +administriert. Open WebUI ist die einfache Benutzeroberfläche; Hermes Agent +ist der zweite Client für lange agentische Aufgaben. Ein eigener Profile Router stellt eine OpenAI-kompatible API bereit und schaltet zwischen mehreren reproduzierbaren llama.cpp-Profilen um. Fachwerkzeuge laufen als getrennte MCP- Container; Zugangsdaten gelangen weder in llama.cpp noch in Modellprompts. @@ -43,7 +44,7 @@ bezeichnen als Index 0 von `nvidia-smi` auf dem Host. ## Hauptfluss ```text -Browser / API-Client +Browser / OpenWebUI / Hermes Agent | | WireGuard, ausschließlich VPN v @@ -64,6 +65,12 @@ Open WebUI ---> Profile Router ---> Profile Controller ---> genau ein llama.cpp- +-- Unraid ``` +Hermes hängt parallel zu OpenWebUI direkt am Router und an denselben +MCP-Containern. Es betreibt kein zweites Qwen und verändert die Profilmatrix +nicht. Dashboard und Agent-API sind nur über WireGuard erreichbar; dauerhafte +Hermes-Daten liegen unter `/data/hermes` und sind Bestandteil des +verschlüsselten Recovery-Bundles. + Deemix läuft bereits als Container auf dem Unraid-HomeServer. Eine künftige Deemix-MCP-Integration auf Athena verwendet dieses Backend über WireGuard und erzeugt nicht ungefragt eine zweite Deemix-Instanz. diff --git a/docs/VPN_SERVICE_PORTS.md b/docs/VPN_SERVICE_PORTS.md index 65e9234..c66d8fd 100644 --- a/docs/VPN_SERVICE_PORTS.md +++ b/docs/VPN_SERVICE_PORTS.md @@ -15,6 +15,8 @@ Aktuelle VPN-Adresse: `192.168.1.212` | 8085 | TTS-Gateway | `http://192.168.1.212:8085` | | 8091 | Piper direkt | `http://192.168.1.212:8091` | | 8092 | XTTS direkt | `http://192.168.1.212:8092` | +| 9119 | Hermes Dashboard | `http://192.168.1.212:9119` | +| 8642 | Hermes Agent API | `http://192.168.1.212:8642` | | 8201 | Athena Platform Context MCP | `http://192.168.1.212:8201/mcp` | | 8202 | Athena Operator MCP einschließlich Terminal | `http://192.168.1.212:8202/mcp` | | 8203 | Allgemeiner TinySearch-MCP | `http://192.168.1.212:8203/mcp` | diff --git a/install.sh b/install.sh index e7c3c87..5416732 100755 --- a/install.sh +++ b/install.sh @@ -315,6 +315,7 @@ WEBUI_SECRET_KEY=$(<$SECRETS_DIR/webui-secret) OPENWEBUI_IMAGE=${OPENWEBUI_IMAGE:-mike-ai/openwebui:main-01f4282-tool-final-v3} OPENWEBUI_ENABLE_SIGNUP=${OPENWEBUI_ENABLE_SIGNUP:-false} OPENWEBUI_ENABLE_FOLLOW_UP_GENERATION=${OPENWEBUI_ENABLE_FOLLOW_UP_GENERATION:-false} +HERMES_IMAGE=${HERMES_IMAGE:-nousresearch/hermes-agent@sha256:143bdb9086bb2db645346179f11091e621ef6b7f4f9e5049ae7454bfeb3a0495} PIPER_TTS_VERSION=${PIPER_TTS_VERSION:-1.6.0} PIPER_VOICE=${PIPER_VOICE:-de_DE-thorsten-high} XTTS_IMAGE=${XTTS_IMAGE:-ghcr.io/coqui-ai/xtts-streaming-server:latest-cuda121@sha256:f7fb3b1f9d4bc88af94da1b5959d8002f1e0b003c97557164034eb8a29f01b90} @@ -478,11 +479,12 @@ build_and_start() { # Web search always starts; HA/ARR/Unraid only start when their root-only # secret files and required local artifacts are present. "$STACK_DIR/platform/mcp/install-tools.sh" + "$STACK_DIR/platform/hermes/install-hermes.sh" docker compose --env-file "$SECRETS_DIR/stack.env" --profile inference create \ llama-fast llama-medium llama-large llama-ultra llama-experimental docker compose --env-file "$SECRETS_DIR/stack.env" --profile image create flux-worker docker compose --env-file "$SECRETS_DIR/stack.env" up -d --build \ - xtts piper tts-gateway profile-controller router open-webui + xtts piper tts-gateway profile-controller router open-webui hermes if [[ ${WIREGUARD_MODE:-container} == container ]]; then systemctl restart mike-ai-container-vpn-guard.service @@ -558,6 +560,7 @@ fi cat <&2; exit 1; } +[[ $EUID -eq 0 ]] || die "Bitte als root ausführen." +[[ -s $SECRETS_DIR/router-api-key ]] || die "Router-API-Key fehlt." +[[ -s $STACK_DIR/platform/hermes/config.yaml ]] || die "Hermes-Konfiguration fehlt im Stack." + +install -d -m 0700 "$HERMES_DATA_DIR" +install -d -m 0750 "$HERMES_DATA_DIR/workspace" +[[ -s $SECRETS_DIR/hermes-api-key ]] || openssl rand -base64 48 >"$SECRETS_DIR/hermes-api-key" +[[ -s $SECRETS_DIR/hermes-dashboard-password ]] || openssl rand -base64 24 >"$SECRETS_DIR/hermes-dashboard-password" +[[ -s $SECRETS_DIR/hermes-dashboard-secret ]] || openssl rand -base64 48 >"$SECRETS_DIR/hermes-dashboard-secret" +chmod 0600 "$SECRETS_DIR/hermes-api-key" \ + "$SECRETS_DIR/hermes-dashboard-password" \ + "$SECRETS_DIR/hermes-dashboard-secret" + +router_key=$(<"$SECRETS_DIR/router-api-key") +mua_url=http://127.0.0.1:9/mcp +mua_token=not-configured +if [[ -s $MUA_ENV ]]; then + mua_url=$(sed -n 's/^MUA_MCP_URL=//p' "$MUA_ENV" | head -n 1) + mua_token=$(sed -n 's/^MUA_MCP_BEARER_TOKEN=//p' "$MUA_ENV" | head -n 1) + [[ -n $mua_url && -n $mua_token ]] || die "MUA URL oder Token fehlt." +fi + +cat >"$HERMES_DATA_DIR/.env" <