diff --git a/.env.example b/.env.example index d6dfa38..2e47563 100644 --- a/.env.example +++ b/.env.example @@ -20,20 +20,28 @@ HERMES_GATEWAY_PORT=8447 HERMES_UID=10000 HERMES_GID=10000 -# Pflicht seit 19.07.2026, SOBALD hermes-agent-dashboard auf 0.0.0.0 bindet: -# Hermes verweigert sonst den Start hart ("no auth providers are registered"). -# HERMES_DASHBOARD_USER ist Klartext (frei waehlbar), HERMES_DASHBOARD_PASSWORD_HASH -# ist NIEMALS das Klartext-Passwort, sondern der Hash daraus. Erzeugen (einmalig): +# NICHT MEHR NOETIG im Normalbetrieb (seit dem Caddy-Umbau, 19.07.2026 spaeter +# Abend): das Dashboard bindet nur noch auf 127.0.0.1, Hermes' eigenes +# Auth-Gate engagiert sich laut eigener Fehlermeldung NUR bei einem 0.0.0.0- +# Bind. Caddy (siehe CADDY_BASIC_AUTH_HASH unten) macht die eigentliche +# Absicherung nach aussen. Einfach leer lassen. +# +# Nur falls der Dashboard-Bind mal wieder auf 0.0.0.0 gestellt wird, ist ein +# Wert hier noetig (sonst verweigert Hermes den Start hart mit "no auth +# providers are registered") — dann zusaetzlich den dashboard:-Block in +# hermes-agent-config/config.yaml.example (bzw. der echten config.yaml) +# einkommentieren. HERMES_DASHBOARD_USER ist Klartext (frei waehlbar), +# HERMES_DASHBOARD_PASSWORD_HASH ist NIEMALS das Klartext-Passwort, sondern +# der Hash daraus. Erzeugen (einmalig, gegen den "hermes-agent"-Container, +# NICHT "hermes-agent-dashboard" — der braucht den Hash schon zum Hochfahren, +# Henne-Ei-Problem): # docker exec -it hermes-agent python -c \ # "from plugins.dashboard_auth.basic import hash_password; print(hash_password('DEIN-PASSWORT'))" -# WICHTIG: gegen den "hermes-agent"-Container, NICHT "hermes-agent-dashboard" — -# der braucht HERMES_DASHBOARD_PASSWORD_HASH schon zum Hochfahren (Henne-Ei- -# Problem, siehe docker-compose.yml), "hermes-agent" laeuft auch ohne. # Den Output (nicht das Passwort selbst!) hier eintragen. # -# ACHTUNG DOLLARZEICHEN-FALLE: der erzeugte Hash hat das Format -# "pbkdf2:sha256:$$" - also ZWEI rohe "$"-Zeichen drin. -# Docker Compose interpretiert "$xyz" in .env-Werten selbst als +# ACHTUNG DOLLARZEICHEN-FALLE falls Du's doch brauchst: der erzeugte Hash hat +# das Format "pbkdf2:sha256:$$" - also ZWEI rohe "$"-Zeichen +# drin. Docker Compose interpretiert "$xyz" in .env-Werten selbst als # Variablen-Referenz und ersetzt nicht aufloesbare Teile stillschweigend # durch Leerstring (sichtbar als "WARN The "xyz" variable is not set" # beim "docker-compose up"). Ergebnis: ein verstuemmelter Hash, das @@ -44,6 +52,8 @@ HERMES_GID=10000 # pbkdf2:sha256:260000$f2kwriK6aYVRG5$BRps7npu2Tzg... # wird # pbkdf2:sha256:260000$$f2kwriK6aYVRG5$$BRps7npu2Tzg... +# Am schnellsten mit dem sed-Trick: +# sed -i '/^HERMES_DASHBOARD_PASSWORD_HASH=/ s/\$/$$/g' .env HERMES_DASHBOARD_USER=admin HERMES_DASHBOARD_PASSWORD_HASH= diff --git a/README.md b/README.md index a8df176..23043d7 100644 --- a/README.md +++ b/README.md @@ -83,75 +83,24 @@ aussen — kein anderer Rechner kommt mehr direkt ran. beim Config-Laden aus den Container-Env-Vars expandiert, die kommen aus Deiner `.env`. Kein manuelles Ausfuellen noetig. -4. **Dashboard-Auth einrichten** (Pflicht seit 19.07.2026 — `hermes-agent-dashboard` - laeuft mit `--host 0.0.0.0` und Hermes verweigert diesen Bind hart, wenn - kein Auth-Provider registriert ist: `Refusing to bind dashboard to - 0.0.0.0 — the auth gate engages on non-loopback binds, but no auth - providers are registered`. Ohne diesen Schritt kommt der Dashboard- - Container beim naechsten Schritt gar nicht hoch): - ```bash - # HERMES_DASHBOARD_USER in .env ist Klartext, HERMES_DASHBOARD_PASSWORD_HASH - # ist NIEMALS das Klartext-Passwort, sondern der Hash daraus. Erzeugen kannst - # Du den erst NACHDEM Schritt 5 unten (docker compose up -d) mindestens - # hermes-agent hochgefahren hat -- gegen "hermes-agent", NICHT - # "hermes-agent-dashboard" (der braucht den Hash schon zum Start, Henne-Ei): - docker exec -it hermes-agent python -c \ - "from plugins.dashboard_auth.basic import hash_password; print(hash_password('DEIN-PASSWORT'))" - ``` - **ACHTUNG DOLLARZEICHEN-FALLE:** der Hash hat das Format - `pbkdf2:sha256:$$` — zwei rohe `$`-Zeichen drin. Docker - Compose interpretiert `$xyz` in `.env`-Werten selbst als Variablen- - Referenz und ersetzt nicht aufloesbare Teile stillschweigend durch - Leerstring (sichtbar als `WARN The "xyz" variable is not set` beim - `docker-compose up`). Ohne Escaping kommt im Container ein - verstuemmelter Hash an und das Dashboard bleibt bei "no auth providers - are registered" haengen, obwohl alles "richtig" eingetragen aussieht. - **Jedes `$` im Hash durch `$$` ersetzen**, bevor Du ihn in `.env` - eintraegst (z.B. `260000$abc$def` → `260000$$abc$$def`). Anfuehrungszeichen - um den Wert helfen dabei NICHT — Compose expandiert `$` in `.env`-Werten - unabhaengig davon ob sie gequotet sind. +4. **Dashboard-Auth: NICHT mehr noetig, ueberspringen.** (Historie: war + zwischenzeitlich Pflicht, solange `hermes-agent-dashboard` mit `--host + 0.0.0.0` lief — Hermes verweigert diesen Bind hart ohne registrierten + Auth-Provider: `Refusing to bind dashboard to 0.0.0.0 — the auth gate + engages on non-loopback binds, but no auth providers are registered`. + Seit Schritt 5 unten (Caddy) bindet das Dashboard aber nur noch auf + `127.0.0.1` — Hermes' Auth-Gate engagiert sich laut eigener Fehlermeldung + NUR bei einem 0.0.0.0-Bind, hier greift's also gar nicht. Caddy macht die + eigentliche Absicherung nach aussen. `HERMES_DASHBOARD_USER`/ + `_PASSWORD_HASH` in `.env` koennen leer bleiben, kein Hash-Erzeugen mehr + noetig.) - Am einfachsten den Hash direkt per `sed` in der Zeile escapen, statt ihn - von Hand nochmal abzutippen (verdoppelt NUR die `$` in genau dieser einen - Zeile): - ```bash - sed -i '/^HERMES_DASHBOARD_PASSWORD_HASH=/ s/\$/$$/g' .env - ``` - Zur Kontrolle, ob noch unverdoppelte `$` uebrig sind (sollte leer sein): - ```bash - grep -o '\$[^$]' .env - ``` - - Output (den escapeten Hash, nicht das Passwort) in `.env` bei - `HERMES_DASHBOARD_PASSWORD_HASH` eintragen, `HERMES_DASHBOARD_USER` - nach Belieben setzen (Default `admin`). - Der `dashboard.basic_auth`-Block dazu liegt schon fertig in - `hermes-agent-config/config.yaml.example` (Platzhalter, die Hermes selbst - aus den Container-Env-Vars expandiert — kein manuelles Ausfuellen noetig, - siehe Schritt 3). - - **WICHTIG, wenn Du Schritt 3 schon VOR dem 19.07.2026 gemacht hast:** - Schritt 3 kopiert `config.yaml.example` nur EINMALIG nach - `hermes-data/agent-home/config.yaml` — kein automatischer Re-Sync danach. - Der `dashboard:`-Block wurde erst nachtraeglich in die `.example`-Datei - ergaenzt, landet also NICHT von selbst in einer bereits existierenden - `config.yaml`. Ohne ihn bleibt Hermes bei "no auth providers are - registered" haengen, egal wie sauber `.env` escaped ist (weil Hermes den - Block ja gar nicht sieht). Pruefen: - ```bash - grep -A3 '^dashboard:' hermes-data/agent-home/config.yaml - ``` - Kommt nichts zurueck → Block manuell anhaengen: - ```bash - cat >> hermes-data/agent-home/config.yaml <<'EOF' - - dashboard: - basic_auth: - username: "${HERMES_DASHBOARD_USER}" - password_hash: "${HERMES_DASHBOARD_PASSWORD_HASH}" - EOF - ``` - Danach neu hochziehen: `docker compose up -d --build hermes-agent-dashboard` + Nur falls Du den Dashboard-Bind mal wieder direkt auf `0.0.0.0` stellst + (z.B. um ohne Caddy zu testen), brauchst Du das wieder — dann in + `hermes-agent-config/config.yaml.example` (bzw. Deiner echten + `config.yaml`) den auskommentierten `dashboard:`-Block reaktivieren und + `HERMES_DASHBOARD_PASSWORD_HASH` in `.env` setzen (Anleitung dazu direkt + im Kommentar über dem Block, inkl. Dollarzeichen-Escaping-Falle). 5. **TLS-Reverse-Proxy (Caddy) einrichten — macht Port 443 von aussen erreichbar, Dashboard bleibt intern auf `127.0.0.1`:** @@ -200,10 +149,10 @@ aussen — kein anderer Rechner kommt mehr direkt ran. Baut beim ersten Mal das Hermes-Image aus `hermes-agent-src` (dauert ein paar Minuten), startet dann `hermes-proxy`, `hermes-gateway`, `hermes-agent` (Gateway/Messaging-Prozess), `hermes-agent-dashboard` und - `caddy`. Falls `HERMES_DASHBOARD_PASSWORD_HASH` oder `CADDY_BASIC_AUTH_HASH` - noch leer sind: der jeweilige Service bricht beim Start ab, die anderen - laufen trotzdem — Werte nachtragen, dann - `docker compose up -d hermes-agent-dashboard caddy`. + `caddy`. Falls `CADDY_BASIC_AUTH_HASH` noch leer ist: `caddy` bricht beim + Start ab, die anderen laufen trotzdem — Wert nachtragen (Schritt 5b), dann + `docker compose up -d caddy`. `HERMES_DASHBOARD_PASSWORD_HASH` darf leer + bleiben (siehe Schritt 4). 7. **Einmalig Claude-CLI-Login** (oeffnet Browser-OAuth mit deiner Claude-Max-Subscription): ```bash diff --git a/docker-compose.yml b/docker-compose.yml index b094744..e6e2b4f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -187,22 +187,25 @@ services: environment: - HERMES_UID=${HERMES_UID:-10000} - HERMES_GID=${HERMES_GID:-10000} - # Pflicht seit 19.07.2026: Hermes verweigert den 0.0.0.0-Bind mit hartem - # Exit, wenn kein Auth-Provider registriert ist ("Refusing to bind - # dashboard to 0.0.0.0 — ... no auth providers are registered"). Diese - # beiden Werte fuettern den dashboard.basic_auth-Block in - # hermes-agent-config/config.yaml.example (dort auch die Anleitung zum - # Hash-Erzeugen). + # NICHT MEHR PFLICHT seit dem Caddy-Umbau (19.07.2026, spaeter Abend): + # Hermes' eigenes Auth-Gate "engagiert sich" laut seiner eigenen + # Fehlermeldung NUR bei einem 0.0.0.0-Bind ("the auth gate engages on + # non-loopback binds"). Der Service unten bindet per `command:` auf + # 127.0.0.1 — das Gate greift also gar nicht, Caddy (siehe unten) macht + # die eigentliche Absicherung nach aussen (TLS + eigene Basic-Auth). + # HERMES_DASHBOARD_PASSWORD_HASH ist daher optional: leer lassen ist ok, + # kein Hash-Erzeugen mehr noetig fuer den Normalbetrieb. Nur falls der + # Dashboard-Bind mal wieder auf 0.0.0.0 wandert, braucht's wieder einen + # Wert (siehe .env.example fuer die Erzeugung). - HERMES_DASHBOARD_USER=${HERMES_DASHBOARD_USER:-admin} - - HERMES_DASHBOARD_PASSWORD_HASH=${HERMES_DASHBOARD_PASSWORD_HASH:?HERMES_DASHBOARD_PASSWORD_HASH muss in .env gesetzt sein - siehe .env.example. Ohne Auth-Provider verweigert Hermes den 0.0.0.0-Bind komplett.} + - HERMES_DASHBOARD_PASSWORD_HASH=${HERMES_DASHBOARD_PASSWORD_HASH:-} # 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. HERMES_DASHBOARD_USER/ - # _PASSWORD_HASH bleiben trotzdem gesetzt (schadet nicht, falls der Bind - # doch mal wieder auf 0.0.0.0 wandert). + # 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) ────────── diff --git a/hermes-agent-config/config.yaml.example b/hermes-agent-config/config.yaml.example index 6720712..a9d0450 100644 --- a/hermes-agent-config/config.yaml.example +++ b/hermes-agent-config/config.yaml.example @@ -32,26 +32,27 @@ model: # (den Hermes intern nutzt) setzt den Header automatisch aus diesem Feld. api_key: "${HERMES_GATEWAY_TOKEN}" -# ─── Dashboard-Auth ───────────────────────────────────────────────────── -# Seit 19.07.2026 Pflicht: Hermes verweigert den Bind des Dashboards auf -# 0.0.0.0 komplett, wenn kein Auth-Provider registriert ist ("Refusing to -# bind dashboard to 0.0.0.0 — the auth gate engages on non-loopback binds, -# but no auth providers are registered"). Ohne diesen Block bindet's nur -# noch auf 127.0.0.1 (Tunnel), egal was im docker-compose `command:` steht. +# ─── Dashboard-Auth (standardmaessig AUSKOMMENTIERT) ──────────────────── +# Hermes' eigenes Auth-Gate verweigert den Bind des Dashboards auf 0.0.0.0 +# komplett, wenn kein Auth-Provider registriert ist ("Refusing to bind +# dashboard to 0.0.0.0 — the auth gate engages on non-loopback binds, but +# no auth providers are registered") — greift aber laut derselben Meldung +# NUR bei einem 0.0.0.0-Bind. Unser docker-compose.yml bindet das Dashboard +# bewusst auf 127.0.0.1 und stellt es per Caddy-Reverse-Proxy (TLS + eigene +# Basic-Auth) nach aussen bereit — das Gate hier engagiert sich dabei gar +# nicht erst, dieser Block ist im Normalbetrieb also NICHT noetig. # -# Hash EINMALIG erzeugen (NICHT das Klartext-Passwort committen oder in .env -# schreiben — nur den Hash). Gegen den "hermes-agent"-Container, NICHT -# "hermes-agent-dashboard" — der braucht HERMES_DASHBOARD_PASSWORD_HASH schon -# zum Hochfahren (Henne-Ei-Problem: ohne Hash kein Start, ohne laufenden -# Container kein Hash). "hermes-agent" teilt sich dasselbe Image und laeuft -# auch ohne den Wert: +# Nur falls Du den Dashboard-Bind mal direkt auf 0.0.0.0 stellst (z.B. ohne +# Caddy testen): Block unten einkommentieren + HERMES_DASHBOARD_PASSWORD_HASH +# in .env setzen. Hash EINMALIG erzeugen (NICHT das Klartext-Passwort +# committen oder in .env schreiben — nur den Hash), gegen den "hermes-agent"- +# Container, NICHT "hermes-agent-dashboard" (der braucht den Hash schon zum +# Hochfahren, Henne-Ei-Problem): # docker exec -it hermes-agent python -c \ # "from plugins.dashboard_auth.basic import hash_password; print(hash_password('DEIN-PASSWORT'))" # Ergebnis nach .env als HERMES_DASHBOARD_PASSWORD_HASH eintragen. # -# ${HERMES_DASHBOARD_USER} / ${HERMES_DASHBOARD_PASSWORD_HASH} werden wie -# oben von Hermes selbst aus den Container-Env-Vars expandiert. -dashboard: - basic_auth: - username: "${HERMES_DASHBOARD_USER}" - password_hash: "${HERMES_DASHBOARD_PASSWORD_HASH}" +# dashboard: +# basic_auth: +# username: "${HERMES_DASHBOARD_USER}" +# password_hash: "${HERMES_DASHBOARD_PASSWORD_HASH}"