Gateway+Dashboard in einen Container zusammenfassen (HERMES_DASHBOARD=1)
hermes-agent-dashboard als separater Container ist raus. Stattdessen supervised s6 Gateway und Dashboard jetzt als Geschwister-Prozesse im selben hermes-agent-Container (HERMES_DASHBOARD=1 + HERMES_DASHBOARD_HOST= 127.0.0.1) -- laut Startup-Log selbst "the recommended setup for the s6 container image". Das ist der wahrscheinliche Fix fuer zwei offene Bugs: Dashboard zeigte Gateway-Status immer als "Stopped" (lokale Prozess- Inspektion sah den Gateway-Prozess im getrennten Container nie) und der Restart-Button warf "no such gateway 'default'" (loeste s6-Services nur im eigenen Container auf). README + Architektur-Diagramm entsprechend aktualisiert.
This commit is contained in:
+50
-55
@@ -113,12 +113,15 @@ services:
|
||||
- hermes-net
|
||||
|
||||
# ─── Hermes Agent selbst (Nous Research) ───────────────────
|
||||
# Offizielle Service-Definition 1:1 aus NousResearch/hermes-agent/docker-compose.yml
|
||||
# (nur umbenannt gateway->hermes-agent, dashboard->hermes-agent-dashboard, damit
|
||||
# es nicht mit unserem eigenen "hermes-gateway" oben verwechselt wird — das ist
|
||||
# ein GANZ ANDERES Ding: Hermes' eigener Gateway-Begriff meint die Messaging-
|
||||
# Bruecke (Telegram/Discord/...) + optionalen OpenAI-API-Server, NICHT unseren
|
||||
# Auth-Proxy vor Claude).
|
||||
# Basiert auf der offiziellen Service-Definition aus
|
||||
# NousResearch/hermes-agent/docker-compose.yml (umbenannt gateway->hermes-agent,
|
||||
# damit's nicht mit unserem eigenen "hermes-gateway" oben verwechselt wird —
|
||||
# das ist ein GANZ ANDERES Ding: Hermes' eigener Gateway-Begriff meint die
|
||||
# Messaging-Bruecke (Telegram/Discord/...) + optionalen OpenAI-API-Server,
|
||||
# NICHT unseren Auth-Proxy vor Claude). Seit 20.07.2026 EIN Container fuer
|
||||
# Gateway + Dashboard zusammen (HERMES_DASHBOARD=1, siehe Kommentar unten
|
||||
# direkt vorm Service) statt zwei getrennter — kein eigener
|
||||
# "hermes-agent-dashboard"-Service mehr.
|
||||
#
|
||||
# VORAUSSETZUNG: der echte Hermes-Agent-Sourcecode muss danebenliegen, weil
|
||||
# das Image nicht auf Docker Hub existiert, sondern per `build:` aus dem Repo
|
||||
@@ -128,6 +131,28 @@ services:
|
||||
# network_mode: host wie im Original — manche Messaging-Plattformen brauchen
|
||||
# echte Host-Ports, und dadurch erreicht Hermes unser hermes-gateway einfach
|
||||
# ueber "http://localhost:${HERMES_GATEWAY_PORT}/v1" statt ueber Docker-DNS.
|
||||
# Kurskorrektur 20.07.2026: KEIN separater hermes-agent-dashboard-Container
|
||||
# mehr. Grund (in Hermes' eigener Docs + unserem eigenen Startup-Log
|
||||
# nachgelesen -- Log-Zeile "dashboard supervised alongside if HERMES_DASHBOARD
|
||||
# is set. This is the recommended setup for the s6 container image"): das
|
||||
# offizielle Docker-Image kann Gateway UND Dashboard als zwei GESCHWISTER-
|
||||
# Prozesse in DERSELBEN s6-Supervision, DEMSELBEN Container laufen lassen,
|
||||
# gesteuert per Env-Var HERMES_DASHBOARD=1. Das ist explizit "the recommended
|
||||
# setup" -- und loest genau unser strukturelles Problem:
|
||||
# - Dashboard erkennt den Gateway-Status ueber LOKALE Prozess-Inspektion
|
||||
# (psutil/PID-Check) im eigenen Container, NICHT ueber eine Netzwerk-
|
||||
# Health-URL. Mit zwei getrennten Containern (unser alter Aufbau) sieht
|
||||
# das Dashboard den Gateway-Prozess nie -> "Gateway Status: Stopped"
|
||||
# obwohl der Gateway echt lief.
|
||||
# - Der "Restart Gateway"-Button im Dashboard ruft intern `hermes gateway
|
||||
# restart` auf, das ueber s6-svc gegen die Service-Verzeichnisse IM
|
||||
# EIGENEN Container aufgeloest wird -- im getrennten Dashboard-Container
|
||||
# gab's dort keinen "default"-Gateway-Service, daher der Fehler "no such
|
||||
# gateway 'default'". Im kombinierten Container sollte der Button den
|
||||
# echten main-hermes-Service finden.
|
||||
# Kein `command:` mehr noetig (Default-CMD des Images uebernimmt "gateway
|
||||
# run" + s6 kuemmert sich per HERMES_DASHBOARD=1 automatisch ums Mitstarten
|
||||
# des Dashboards).
|
||||
hermes-agent:
|
||||
build: ./hermes-agent-src
|
||||
image: hermes-agent
|
||||
@@ -154,6 +179,14 @@ services:
|
||||
# Config-Laden aus os.environ — siehe hermes_cli/config.py _expand_env_vars).
|
||||
- HERMES_GATEWAY_PORT=${HERMES_GATEWAY_PORT:-8447}
|
||||
- HERMES_GATEWAY_TOKEN=${HERMES_GATEWAY_TOKEN:?HERMES_GATEWAY_TOKEN muss in .env gesetzt sein - siehe .env.example}
|
||||
# Dashboard als s6-supervisierten Geschwister-Prozess IM SELBEN Container
|
||||
# aktivieren (siehe Kommentar oben). HERMES_DASHBOARD_HOST=127.0.0.1
|
||||
# haelt den Bind lokal (Caddy ist die einzige Auth-/TLS-Schicht nach
|
||||
# aussen, siehe caddy-Service unten und README) -- ohne das wuerde Hermes
|
||||
# per Default auf 0.0.0.0 binden und sein eigenes Auth-Gate verlangen.
|
||||
- HERMES_DASHBOARD=1
|
||||
- HERMES_DASHBOARD_HOST=127.0.0.1
|
||||
- HERMES_DASHBOARD_PORT=9119
|
||||
# Optional: Hermes' EIGENER OpenAI-kompatibler API-Server, falls Du spaeter
|
||||
# einen mobilen Client (gpt_mobile, Maid, OpenWebUI, ...) direkt GEGEN
|
||||
# Hermes sprechen lassen willst (andere Richtung als unser Proxy oben!
|
||||
@@ -164,72 +197,34 @@ services:
|
||||
# - API_SERVER_KEY=${API_SERVER_KEY}
|
||||
command: ["gateway", "run"]
|
||||
|
||||
hermes-agent-dashboard:
|
||||
# Gleicher Build-Kontext wie oben bei "hermes-agent" (nicht nur "image:").
|
||||
# Grund: "hermes-agent" ist kein Docker-Hub-Image, sondern wird lokal aus
|
||||
# ./hermes-agent-src gebaut. Ohne eigenes build: hier versucht Compose
|
||||
# beim "up" trotzdem erst einen Registry-Pull fuer dieses Image, der mit
|
||||
# "pull access denied" fehlschlaegt UND (anders als beim hermes-agent-
|
||||
# Service oben, der einen build:-Fallback hat) hart abbricht statt lokal
|
||||
# zu bauen. Mit build: hier baut Compose denselben Kontext nochmal --
|
||||
# dank Docker-Layer-Cache praktisch instant, landet aber wieder unter
|
||||
# dem Tag "hermes-agent".
|
||||
build: ./hermes-agent-src
|
||||
image: hermes-agent
|
||||
pull_policy: build
|
||||
container_name: hermes-agent-dashboard
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
depends_on:
|
||||
- hermes-agent
|
||||
volumes:
|
||||
- ./hermes-data/agent-home:/opt/data
|
||||
environment:
|
||||
- HERMES_UID=${HERMES_UID:-10000}
|
||||
- HERMES_GID=${HERMES_GID:-10000}
|
||||
# HERMES_DASHBOARD_USER wird hier NICHT fuer Hermes' eigenes Auth-Gate
|
||||
# gebraucht (das Gate engagiert sich laut eigener Fehlermeldung nur bei
|
||||
# einem 0.0.0.0-Bind, der Service unten bindet aber fest auf 127.0.0.1
|
||||
# per `command:`) — steht nur der Vollstaendigkeit halber mit drin,
|
||||
# tatsaechlich genutzt wird die Variable von Caddy (siehe unten) fuer
|
||||
# dessen Basic-Auth. Absicherung nach aussen laeuft komplett ueber Caddy.
|
||||
- HERMES_DASHBOARD_USER=${HERMES_DASHBOARD_USER:-admin}
|
||||
# Kurskorrektur 19.07.2026, spaeter Abend: Stefan wollte erst 0.0.0.0
|
||||
# (SSH-Tunnel machte mit SSL Probleme), jetzt aber die richtige Loesung:
|
||||
# Dashboard bleibt auf 127.0.0.1 (Hermes' eigenes Auth-Gate verlangt dann
|
||||
# gar keinen registrierten Provider mehr, siehe Fehlermeldung "the auth
|
||||
# gate engages on non-loopback binds") und der Caddy-Reverse-Proxy unten
|
||||
# macht TLS + Basic-Auth auf Port 443 nach aussen. Das ist die einzige
|
||||
# Auth-Schicht die im Normalbetrieb wirklich noetig ist.
|
||||
command: ["dashboard", "--host", "127.0.0.1", "--no-open"]
|
||||
|
||||
# ─── Caddy (TLS-Reverse-Proxy + Basic-Auth vor dem Dashboard) ──────────
|
||||
# Stefans Entscheidung 19.07.2026: Dashboard bleibt intern auf 127.0.0.1,
|
||||
# Caddy uebernimmt TLS-Termination auf Port 443 UND die Basic-Auth davor.
|
||||
# Caddy ist die EINZIGE Auth-/TLS-Schicht (aufgeraeumt 20.07.2026): Hermes'
|
||||
# eigenes Dashboard-Auth-Gate (dashboard.basic_auth) wurde komplett entfernt,
|
||||
# weil es sich laut eigener Fehlermeldung ohnehin nur bei einem 0.0.0.0-Bind
|
||||
# engagiert — der Dashboard-Container bindet aber fest auf 127.0.0.1, das
|
||||
# Gate haette hier nie gegriffen. Ein zweiter, nie greifender Auth-Layer
|
||||
# haette nur Setup-Schritte gekostet, kein Sicherheitsgewinn. Nutzt
|
||||
# HERMES_DASHBOARD_USER (aus .env) als Login-Name + einen eigenen bcrypt-
|
||||
# Hash in CADDY_BASIC_AUTH_HASH (Caddy verlangt bcrypt, siehe .env.example
|
||||
# fuer die Erzeugung).
|
||||
# engagiert — der Dashboard-Bind (HERMES_DASHBOARD_HOST im hermes-agent-
|
||||
# Service) bleibt aber fest auf 127.0.0.1, das Gate haette hier nie
|
||||
# gegriffen. Ein zweiter, nie greifender Auth-Layer haette nur Setup-
|
||||
# Schritte gekostet, kein Sicherheitsgewinn. Nutzt HERMES_DASHBOARD_USER
|
||||
# (aus .env) als Login-Name + einen eigenen bcrypt-Hash in
|
||||
# CADDY_BASIC_AUTH_HASH (Caddy verlangt bcrypt, siehe .env.example fuer die
|
||||
# Erzeugung).
|
||||
#
|
||||
# Zertifikat: bewusst KEIN Let's Encrypt (bräuchte oeffentliche Domain +
|
||||
# Port-80-Challenge). Stefans Wunsch: ein selbstsigniertes Zertifikat mit
|
||||
# 100 Jahren Laufzeit, einmalig im Browser als Ausnahme akzeptieren, nie
|
||||
# wieder um Erneuerung kuemmern. Erzeugung siehe README Setup-Schritt.
|
||||
# network_mode: host aus demselben Grund wie bei hermes-agent/-dashboard:
|
||||
# muss 127.0.0.1:9119 (Dashboard) erreichen UND selbst auf dem Host-Port
|
||||
# 443 lauschen.
|
||||
# network_mode: host aus demselben Grund wie bei hermes-agent: muss
|
||||
# 127.0.0.1:9119 (Dashboard, jetzt Teil des hermes-agent-Containers)
|
||||
# erreichen UND selbst auf dem Host-Port 443 lauschen.
|
||||
caddy:
|
||||
image: caddy:2-alpine
|
||||
container_name: hermes-caddy
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
depends_on:
|
||||
- hermes-agent-dashboard
|
||||
- hermes-agent
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
# kein :ro mehr -- der Entrypoint unten schreibt das Zertifikat selbst
|
||||
|
||||
Reference in New Issue
Block a user