Hermes Agent selbst mit ins Compose: alles auf einer Maschine
Stefan-Entscheidung: Hermes Agent (Nous Research) laeuft auf derselben
Maschine wie der Claude-Max-Proxy, nicht mehr remote. Ergaenzt:
- hermes-agent + hermes-agent-dashboard Services (offizielle Definition,
gebaut aus separat geklontem hermes-agent-src/), network_mode: host
- hermes-agent-config/config.yaml.example: seedet Hermes' model:-Block
automatisch auf provider: custom -> unser hermes-gateway, per ${VAR}-
Expansion aus .env (kein manuelles Config-Editieren mehr)
- hermes-gateway bindet jetzt nur noch auf 127.0.0.1 statt 0.0.0.0, da
Hermes lokal mitlaeuft und kein Remote-Zugriff mehr noetig ist
- .gitignore fuer hermes-agent-src/, hermes-data/, .env (Secrets/Sourcecode
gehoeren nicht ins Repo)
- README auf Single-Machine-Architektur aktualisiert, inkl. Setup-Schritten
und Einordnung des optionalen API_SERVER (fuer spaeteren mobilen Client,
andere Richtung als unser Proxy)
This commit is contained in:
+21
-4
@@ -1,12 +1,29 @@
|
|||||||
# Nach /shared/projects/hermes_agent/.env kopieren und Werte anpassen.
|
# Nach /shared/projects/hermes_agent/.env kopieren und Werte anpassen.
|
||||||
# .env NICHT committen falls das Ganze mal in ein Git-Repo wandert.
|
# .env ist in .gitignore und wird NICHT committet.
|
||||||
|
|
||||||
# Shared Secret zwischen hermes-gateway und Hermes Agent (config.yaml -> api_key).
|
# Shared Secret zwischen hermes-gateway und Hermes Agent (config.yaml -> api_key).
|
||||||
# Mindestens 32 zufaellige Zeichen, z.B. erzeugen mit:
|
# Mindestens 32 zufaellige Zeichen, z.B. erzeugen mit:
|
||||||
# openssl rand -hex 32
|
# openssl rand -hex 32
|
||||||
HERMES_GATEWAY_TOKEN=
|
HERMES_GATEWAY_TOKEN=
|
||||||
|
|
||||||
# Port auf dem hermes-gateway auf dieser Maschine nach aussen lauscht.
|
# Port auf dem hermes-gateway auf dieser Maschine lauscht. Seit "alles auf
|
||||||
# Hermes Agent (auf der anderen Maschine) zeigt in config.yaml auf
|
# einer Maschine" nur noch auf 127.0.0.1 gebunden (siehe docker-compose.yml) -
|
||||||
# http://<diese-maschine>:<PORT>/v1
|
# Hermes Agent selbst (network_mode: host) erreicht das trotzdem ueber
|
||||||
|
# localhost, kein anderer Rechner kommt mehr direkt ran.
|
||||||
HERMES_GATEWAY_PORT=8447
|
HERMES_GATEWAY_PORT=8447
|
||||||
|
|
||||||
|
# UID/GID des Host-Users, dem hermes-data/agent-home gehoeren soll, damit
|
||||||
|
# Dateien die Hermes im Container schreibt (Sessions, Memory, Config) auf dem
|
||||||
|
# Host lesbar/schreibbar bleiben. Default 10000 (Hermes' eingebauter Default)
|
||||||
|
# ist ok wenn Dir das egal ist; setze es sonst auf `id -u`/`id -g` des Users
|
||||||
|
# der hermes-data/ auf dem Host verwaltet.
|
||||||
|
HERMES_UID=10000
|
||||||
|
HERMES_GID=10000
|
||||||
|
|
||||||
|
# Optional: NUR setzen wenn Du Hermes' EIGENEN OpenAI-kompatiblen API-Server
|
||||||
|
# aktivierst (siehe API_SERVER_HOST/API_SERVER_KEY-Kommentar im
|
||||||
|
# hermes-agent-Service in docker-compose.yml) — z.B. um einen mobilen Client
|
||||||
|
# wie gpt_mobile/Maid/OpenWebUI direkt gegen Hermes sprechen zu lassen, statt
|
||||||
|
# nur ueber CLI/Dashboard. Andere Richtung als HERMES_GATEWAY_TOKEN oben!
|
||||||
|
# Mindestens 32 zufaellige Zeichen, z.B. openssl rand -hex 32.
|
||||||
|
# API_SERVER_KEY=
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
# Echter Hermes-Agent-Sourcecode wird per README-Anleitung separat geklont
|
||||||
|
# (git clone https://github.com/NousResearch/hermes-agent.git hermes-agent-src)
|
||||||
|
# — eigenes Repo, gehoert nicht als Kopie/Submodule in dieses hier.
|
||||||
|
hermes-agent-src/
|
||||||
|
|
||||||
|
# Runtime-State: Claude-CLI-Login-Credentials, Hermes' ~/.hermes-Aequivalent
|
||||||
|
# (Sessions, Memory, ggf. Provider-API-Keys anderer Skills), Shared-Files.
|
||||||
|
# Enthaelt Secrets - niemals committen.
|
||||||
|
hermes-data/
|
||||||
|
hermes-shared/
|
||||||
|
|
||||||
|
# Secrets
|
||||||
|
.env
|
||||||
@@ -1,42 +1,45 @@
|
|||||||
# Hermes Agent — Claude-Max-Proxy Setup
|
# Hermes Agent — Claude-Max-Proxy + Hermes selbst, alles auf einer Maschine
|
||||||
|
|
||||||
Repliziert den Proxy-Trick, den wir fuer ARIA nutzen: `claude-max-api-proxy`
|
Repliziert den Proxy-Trick, den wir fuer ARIA nutzen: `claude-max-api-proxy`
|
||||||
(npm) wrappt die Claude Code CLI — angemeldet mit deiner Claude-Max-
|
(npm) wrappt die Claude Code CLI — angemeldet mit deiner Claude-Max-
|
||||||
Subscription — als OpenAI-kompatiblen `/v1/chat/completions`-Endpoint.
|
Subscription — als OpenAI-kompatiblen `/v1/chat/completions`-Endpoint.
|
||||||
[Hermes Agent](https://github.com/NousResearch/hermes-agent) (Nous Research,
|
[Hermes Agent](https://github.com/NousResearch/hermes-agent) (Nous Research,
|
||||||
CLI/Desktop-Agent, unterstuetzt laut Doku "your own endpoint" als
|
CLI/Desktop-Agent) redet darueber mit Claude, ohne API-Kosten — laeuft ueber
|
||||||
Model-Provider) kann darueber mit Claude reden, ohne API-Kosten — laeuft
|
die Subscription, nicht ueber Anthropic-API-Billing.
|
||||||
ueber die Subscription, nicht ueber Anthropic-API-Billing.
|
|
||||||
|
|
||||||
**Wichtig:** Hermes Agent selbst (das CLI/Desktop-Tool von Nous Research)
|
**Entscheidung (Stefan):** Hermes Agent selbst laeuft auf DERSELBEN Maschine
|
||||||
ist hier NICHT enthalten — Stefan deployt das selbst auf einer anderen
|
wie dieser Proxy-Stack — alles was zu Hermes gehoert auf eine Box, minimale
|
||||||
Maschine. Dieser Stack liefert nur die Proxy-Seite, die Hermes von dort
|
Latenz, nur ein Rechner zum Pflegen. ARIA bleibt komplett unangetastet
|
||||||
ansprechen kann. ARIA bleibt komplett unangetastet (eigenes Docker-Netz
|
(eigenes Docker-Netz `hermes-net`, eigenes Claude-CLI-Login-Volume, kein
|
||||||
`hermes-net`, eigenes Claude-CLI-Login-Volume, kein gemeinsamer Container).
|
gemeinsamer Container, laeuft ja ohnehin auf einer anderen Maschine als
|
||||||
|
Hermes).
|
||||||
|
|
||||||
## Architektur
|
## Architektur
|
||||||
|
|
||||||
```
|
```
|
||||||
Hermes Agent (andere Maschine)
|
hermes-agent (Nous Research, network_mode: host)
|
||||||
| HTTP(S), Authorization: Bearer <TOKEN>
|
| HTTP, Authorization: Bearer <TOKEN>, http://localhost:8447/v1
|
||||||
v
|
v
|
||||||
hermes-gateway (Port ${HERMES_GATEWAY_PORT:-8447}, nach aussen exposed)
|
hermes-gateway (Port 8447, NUR auf 127.0.0.1 gebunden)
|
||||||
| prueft Bearer-Token, sonst 401
|
| prueft Bearer-Token, sonst 401
|
||||||
v
|
v
|
||||||
hermes-proxy (Port 3456, NUR docker-intern erreichbar)
|
hermes-proxy (Port 3456, NUR docker-intern im hermes-net erreichbar)
|
||||||
| claude-max-api-proxy -> Claude Code CLI (Claude-Max-Login)
|
| claude-max-api-proxy -> Claude Code CLI (Claude-Max-Login)
|
||||||
v
|
v
|
||||||
Anthropic (ueber deine Claude-Max-Subscription)
|
Anthropic (ueber deine Claude-Max-Subscription)
|
||||||
|
|
||||||
|
hermes-agent-dashboard (127.0.0.1:9119, Hermes' eigenes Web-UI/Setup)
|
||||||
```
|
```
|
||||||
|
|
||||||
Warum das Gateway davor: `hermes-proxy` selbst hat keine Authentifizierung
|
Warum das Gateway trotzdem noch da ist, obwohl alles auf einer Maschine
|
||||||
(genau wie ARIAs Proxy) — das ist bei ARIA ok, weil der Proxy nie einen
|
laeuft: `hermes-proxy` selbst hat keine Authentifizierung (genau wie ARIAs
|
||||||
Netzwerk-Port bekommt. Hermes laeuft aber auf einer anderen Maschine, der
|
Proxy) — jeder andere Container im selben Docker-Host koennte sonst
|
||||||
Proxy muss also ueber Netzwerk erreichbar sein. Ohne Auth waere das ein frei
|
unbemerkt Deine Claude-Max-Subscription mitbenutzen. Das Gateway
|
||||||
nutzbarer Claude-Max-Zugang fuer jeden der den Port erreicht. Das Gateway
|
(`proxy-patches/gateway.js`, pure Node, keine Extra-Deps) prueft den
|
||||||
(`proxy-patches/gateway.js`, pure Node, keine Extra-Deps) prueft dafuer den
|
|
||||||
`Authorization: Bearer <TOKEN>`-Header gegen ein Shared Secret, bevor
|
`Authorization: Bearer <TOKEN>`-Header gegen ein Shared Secret, bevor
|
||||||
irgendwas an `hermes-proxy` weitergeleitet wird.
|
irgendwas an `hermes-proxy` weitergeleitet wird. Seit "alles auf einer
|
||||||
|
Maschine" bindet das Gateway nur noch auf `127.0.0.1`, nicht mehr nach
|
||||||
|
aussen — kein anderer Rechner kommt mehr direkt ran.
|
||||||
|
|
||||||
## Was uebernommen wurde (1:1 aus ARIAs Proxy-Setup)
|
## Was uebernommen wurde (1:1 aus ARIAs Proxy-Setup)
|
||||||
|
|
||||||
@@ -51,66 +54,104 @@ irgendwas an `hermes-proxy` weitergeleitet wird.
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. **`.env` anlegen:**
|
1. **Hermes-Agent-Sourcecode daneben klonen** (das offizielle Docker-Image
|
||||||
|
liegt nicht auf Docker Hub, sondern wird per `build:` aus dem Repo
|
||||||
|
gebaut):
|
||||||
|
```bash
|
||||||
|
cd /pfad/zum/deploy-ziel
|
||||||
|
git clone https://github.com/NousResearch/hermes-agent.git hermes-agent-src
|
||||||
|
```
|
||||||
|
(dieser Clone ist in `.gitignore` — bleibt lokal, wandert nicht in unser Repo)
|
||||||
|
|
||||||
|
2. **`.env` anlegen:**
|
||||||
```bash
|
```bash
|
||||||
cd /shared/projects/hermes_agent
|
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
openssl rand -hex 32 # Ausgabe in .env bei HERMES_GATEWAY_TOKEN eintragen
|
openssl rand -hex 32 # Ausgabe in .env bei HERMES_GATEWAY_TOKEN eintragen
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Stack starten:**
|
3. **Model-Config fuer Hermes seeden** (einmalig, VOR dem ersten Start —
|
||||||
|
danach fasst Hermes die Datei nicht mehr an):
|
||||||
|
```bash
|
||||||
|
mkdir -p hermes-data/agent-home
|
||||||
|
cp hermes-agent-config/config.yaml.example hermes-data/agent-home/config.yaml
|
||||||
|
```
|
||||||
|
Die Datei zeigt Hermes per `provider: custom` auf unseren
|
||||||
|
`hermes-gateway` (`http://localhost:${HERMES_GATEWAY_PORT}/v1`) —
|
||||||
|
`${HERMES_GATEWAY_PORT}`/`${HERMES_GATEWAY_TOKEN}` werden von Hermes selbst
|
||||||
|
beim Config-Laden aus den Container-Env-Vars expandiert, die kommen aus
|
||||||
|
Deiner `.env`. Kein manuelles Ausfuellen noetig.
|
||||||
|
|
||||||
|
4. **Stack starten:**
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
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) und `hermes-agent-dashboard`.
|
||||||
|
|
||||||
3. **Einmalig Claude-CLI-Login** (oeffnet Browser-OAuth mit deiner Claude-Max-Subscription):
|
5. **Einmalig Claude-CLI-Login** (oeffnet Browser-OAuth mit deiner Claude-Max-Subscription):
|
||||||
```bash
|
```bash
|
||||||
docker exec -it hermes-proxy claude
|
docker exec -it hermes-proxy claude
|
||||||
```
|
```
|
||||||
Danach liegen die Credentials persistent in `hermes-data/claude-config/.credentials.json`
|
Danach liegen die Credentials persistent in `hermes-data/claude-config/`
|
||||||
— ueberlebt Container-Restarts.
|
— ueberlebt Container-Restarts.
|
||||||
|
|
||||||
4. **Von der Hermes-Maschine aus testen:**
|
6. **Testen, dass der Proxy laeuft:**
|
||||||
```bash
|
```bash
|
||||||
curl -s http://<diese-maschine>:${HERMES_GATEWAY_PORT:-8447}/v1/chat/completions \
|
curl -s http://127.0.0.1:${HERMES_GATEWAY_PORT:-8447}/v1/chat/completions \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-H "Authorization: Bearer <HERMES_GATEWAY_TOKEN aus .env>" \
|
-H "Authorization: Bearer <HERMES_GATEWAY_TOKEN aus .env>" \
|
||||||
-d '{"model":"claude-sonnet-4","messages":[{"role":"user","content":"Sag Hallo"}]}'
|
-d '{"model":"sonnet","messages":[{"role":"user","content":"Sag Hallo"}]}'
|
||||||
```
|
```
|
||||||
Ohne oder mit falschem Bearer-Token gibt's `401 unauthorized` — Gateway
|
Ohne oder mit falschem Bearer-Token gibt's `401 unauthorized`.
|
||||||
arbeitet.
|
|
||||||
|
|
||||||
5. **Hermes Agent konfigurieren** (auf der Ziel-Maschine, `~/.hermes/config.yaml`):
|
7. **Mit Hermes chatten:**
|
||||||
```yaml
|
```bash
|
||||||
model:
|
docker exec -it hermes-agent hermes chat
|
||||||
provider: custom
|
|
||||||
model: "sonnet"
|
|
||||||
base_url: "http://<diese-maschine>:8447/v1"
|
|
||||||
api_key: "<derselbe HERMES_GATEWAY_TOKEN>"
|
|
||||||
```
|
```
|
||||||
`base_url` hat laut Hermes-Doku Vorrang vor `provider` — funktioniert wie
|
oder das Dashboard per SSH-Tunnel oeffnen:
|
||||||
bei selbst gehosteten/lokalen Endpoints (vLLM, Ollama etc.), die
|
```bash
|
||||||
Hermes-Doku beschreibt genau diesen Ansatz. Modellnamen `sonnet` / `opus`
|
ssh -L 9119:localhost:9119 <diese-maschine>
|
||||||
/ `haiku` werden vom Adapter (`openai-to-cli.js`, `MODEL_MAP`) auf die
|
```
|
||||||
`--model`-CLI-Flags gemappt.
|
dann im Browser `http://localhost:9119`.
|
||||||
|
|
||||||
|
## Mobiler Client (Android)?
|
||||||
|
|
||||||
|
Zwei GRUNDVERSCHIEDENE Richtungen, nicht verwechseln:
|
||||||
|
|
||||||
|
- **Unser Proxy oben** (`hermes-gateway` -> `hermes-proxy`): Claude ALS
|
||||||
|
Backend FUER Hermes. Kein Client redet direkt damit ausser Hermes selbst.
|
||||||
|
- **Hermes' EIGENER OpenAI-kompatibler API-Server** (`API_SERVER_HOST` /
|
||||||
|
`API_SERVER_KEY`, auskommentiert im `hermes-agent`-Service): Hermes ALS
|
||||||
|
Server FUER einen Chat-Client. Aktivieren + `API_SERVER_KEY` in `.env`
|
||||||
|
setzen, dann kann ein Client wie **gpt_mobile** oder **Maid** (Open Source,
|
||||||
|
Android, freier `base_url`+Key, kein Messenger — siehe Chat-Verlauf) sich
|
||||||
|
direkt gegen Hermes verbinden. Fuer sowas wie die ARIA-App (Wake-Word,
|
||||||
|
Sprachsteuerung, TTS) braeuchte man dagegen einen eigenen App-Build — kein
|
||||||
|
fertiges Produkt zum Runterladen.
|
||||||
|
|
||||||
## Sicherheitshinweis
|
## Sicherheitshinweis
|
||||||
|
|
||||||
Das Gateway schuetzt vor Fremdnutzung deiner Subscription (Bearer-Token-
|
`hermes-gateway` bindet jetzt nur noch auf `127.0.0.1` — von aussen kommt
|
||||||
Pflicht), **aber der Traffic selbst ist unverschluesseltes HTTP** — kein TLS
|
niemand mehr ran, solange Du nicht selbst was aendertst (z.B. fuer den
|
||||||
zwischen Hermes und dem Gateway. Solange beide Maschinen im selben
|
mobilen API-Server oben, oder falls Hermes doch mal auf eine zweite Maschine
|
||||||
vertrauenswuerdigen LAN oder per VPN verbunden sind: unkritisch. Wenn die
|
zieht). Wenn Du `HERMES_GATEWAY_PORT` oder `API_SERVER_HOST` doch mal nach
|
||||||
Hermes-Maschine ueber offenes Internet zugreifen soll: Port NICHT direkt
|
aussen exposest: der Traffic ist unverschluesseltes HTTP, kein TLS. Nicht
|
||||||
exposen, sondern per SSH-Tunnel, WireGuard/Tailscale oder einen TLS-
|
direkt ins offene Internet haengen — SSH-Tunnel, WireGuard/Tailscale oder
|
||||||
Reverse-Proxy davorschalten. Sag Bescheid, dann bauen wir das nach, sobald
|
einen TLS-Reverse-Proxy davorschalten.
|
||||||
klar ist wie die beiden Maschinen tatsaechlich verbunden sind.
|
|
||||||
|
## Verzeichnisse (nicht committet, siehe .gitignore)
|
||||||
|
|
||||||
|
- `hermes-agent-src/` — geklonter Hermes-Agent-Sourcecode (Docker-Build-Context)
|
||||||
|
- `hermes-data/claude-config/` — Claude-CLI-Login (Browser-OAuth-Session)
|
||||||
|
- `hermes-data/agent-home/` — Hermes' `~/.hermes`-Aequivalent: Config
|
||||||
|
(`config.yaml`, aus `hermes-agent-config/config.yaml.example` geseedet),
|
||||||
|
Sessions, Memory, Skills, `.env`
|
||||||
|
- `.env` — Secrets (Token, ggf. API_SERVER_KEY)
|
||||||
|
|
||||||
## Wo deployen?
|
## Wo deployen?
|
||||||
|
|
||||||
Diese Compose-Datei ist ortsunabhaengig — lief bisher nirgends deployed,
|
Diese Compose-Datei ist ortsunabhaengig. Stefan deployt sie selbst auf der
|
||||||
liegt nur unter `/shared/projects/hermes_agent/` (Code-Editor-Sync). Du
|
Ziel-Maschine (nicht aria-wohnung — komplett getrennt von ARIA). Repo klonen,
|
||||||
kannst sie 1:1 dahin kopieren, wo der Proxy tatsaechlich laufen soll (z.B.
|
die drei Setup-Schritte oben (Hermes-Source klonen, `.env`, Config seeden),
|
||||||
aria-wohnung als eigener isolierter Stack neben ARIA, oder eine ganz andere
|
dann `docker compose up -d`.
|
||||||
Maschine mit Zugriff auf deine Claude-Max-Subscription). Wichtig ist nur:
|
|
||||||
egal wo, `HERMES_GATEWAY_PORT` muss von der Hermes-Maschine aus erreichbar
|
|
||||||
sein.
|
|
||||||
|
|||||||
+85
-32
@@ -72,30 +72,19 @@ services:
|
|||||||
# offen im Netz haengt.
|
# offen im Netz haengt.
|
||||||
# Zum manuellen Testen direkt im Container: docker exec -it hermes-proxy curl -s localhost:3456/v1/chat/completions ...
|
# Zum manuellen Testen direkt im Container: docker exec -it hermes-proxy curl -s localhost:3456/v1/chat/completions ...
|
||||||
|
|
||||||
# ─── Hermes Gateway (Auth + Netzwerk-Expose) ───────────────
|
# ─── Hermes Gateway (Auth vor dem Claude-Proxy) ────────────
|
||||||
# Stefan deployt den eigentlichen Hermes-Agent-Client (Nous Research,
|
# Stefan hat entschieden: Hermes Agent selbst laeuft auf DERSELBEN Maschine
|
||||||
# https://github.com/NousResearch/hermes-agent, CLI/Desktop-App) SELBST
|
# wie dieser Proxy-Stack (alles zu Hermes gehoerige auf eine Box). Trotzdem
|
||||||
# auf einer ANDEREN Maschine — hier steht daher kein hermes-agent-Service,
|
# bleibt dieses Gateway davor — hermes-proxy selbst hat keine Authentifizierung
|
||||||
# nur die Proxy-Seite, die Hermes von aussen ansprechen kann.
|
# (genau wie ARIAs Proxy) und ein anderer Container im selben Docker-Host
|
||||||
|
# (oder spaeter doch mal ein zweiter Rechner) soll nicht ungefragt an die
|
||||||
|
# Claude-Max-Subscription rankommen. Das Gateway (proxy-patches/gateway.js,
|
||||||
|
# pure Node, keine Extra-Deps) prueft den Authorization: Bearer <TOKEN>
|
||||||
|
# Header, leitet nur bei Match an hermes-proxy weiter. Alles andere -> 401.
|
||||||
#
|
#
|
||||||
# Weil "von aussen" heisst: der Proxy braucht einen echten Netzwerk-Port.
|
# Der Hermes-Agent-Service unten ist per ${HERMES_GATEWAY_TOKEN} + diesem
|
||||||
# hermes-proxy selbst hat aber keine Authentifizierung eingebaut (siehe
|
# Gateway vorverdrahtet (siehe hermes-agent-config/config.yaml.example) —
|
||||||
# Kommentar oben) — ein offener Port waere ein frei nutzbarer Claude-Max-
|
# kein manuelles config.yaml-Editieren mehr noetig.
|
||||||
# Zugang fuer jeden der ihn erreicht. Deshalb dieses schlanke Gateway
|
|
||||||
# (proxy-patches/gateway.js, pure Node, keine Extra-Deps): prueft den
|
|
||||||
# Authorization: Bearer <TOKEN> Header, leitet nur bei Match an
|
|
||||||
# hermes-proxy weiter. Alles andere -> 401.
|
|
||||||
#
|
|
||||||
# In Hermes' ~/.hermes/config.yaml traegst du ein:
|
|
||||||
# model:
|
|
||||||
# provider: custom
|
|
||||||
# model: "sonnet" # oder "opus" / "haiku" — siehe MODEL_MAP
|
|
||||||
# # in proxy-patches/openai-to-cli.js
|
|
||||||
# base_url: "http://<diese-maschine>:${HERMES_GATEWAY_PORT:-8447}/v1"
|
|
||||||
# api_key: "<HERMES_GATEWAY_TOKEN aus .env>"
|
|
||||||
# OpenAI-kompatible Clients schicken api_key automatisch als
|
|
||||||
# "Authorization: Bearer <api_key>" — genau das prueft das Gateway, kein
|
|
||||||
# Extra-Schritt auf Hermes-Seite noetig.
|
|
||||||
hermes-gateway:
|
hermes-gateway:
|
||||||
image: node:22-alpine
|
image: node:22-alpine
|
||||||
container_name: hermes-gateway
|
container_name: hermes-gateway
|
||||||
@@ -110,19 +99,83 @@ services:
|
|||||||
- UPSTREAM_PORT=3456
|
- UPSTREAM_PORT=3456
|
||||||
- LISTEN_PORT=8080
|
- LISTEN_PORT=8080
|
||||||
ports:
|
ports:
|
||||||
# Bindet auf ALLE Interfaces, damit Hermes von der anderen Maschine
|
# Seit "alles auf einer Maschine": nur noch auf localhost binden, nicht
|
||||||
# rankommt. HERMES_GATEWAY_PORT in .env setzen (Default 8447).
|
# mehr auf allen Interfaces. Hermes Agent laeuft ja jetzt selbst hier
|
||||||
# WICHTIG (lies auch README "Sicherheitshinweis"): wenn diese Maschine
|
# (network_mode: host, siehe unten) und erreicht localhost direkt.
|
||||||
# direkt im Internet haengt statt in einem vertrauenswuerdigen
|
# Falls Du spaeter doch von einer ANDEREN Maschine ranwillst (z.B. fuer
|
||||||
# LAN/VPN, den Port zusaetzlich per Firewall auf Hermes' IP
|
# einen mobilen Client direkt gegen Hermes' eigenen API-Server, siehe
|
||||||
# einschraenken oder per VPN/SSH-Tunnel statt direktem Expose fahren
|
# Kommentar unten bei API_SERVER_*): "127.0.0.1:" vorne weglassen, dann
|
||||||
# — Bearer-Token schuetzt vor Fremdnutzung, aber der Traffic selbst
|
# bindet's wieder auf 0.0.0.0 — aber dann auch das Sicherheitshinweis-
|
||||||
# laeuft hier unverschluesselt (HTTP, kein TLS).
|
# Kapitel im README zu TLS/VPN beachten.
|
||||||
- "${HERMES_GATEWAY_PORT:-8447}:8080"
|
- "127.0.0.1:${HERMES_GATEWAY_PORT:-8447}:8080"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- hermes-net
|
- 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).
|
||||||
|
#
|
||||||
|
# VORAUSSETZUNG: der echte Hermes-Agent-Sourcecode muss danebenliegen, weil
|
||||||
|
# das Image nicht auf Docker Hub existiert, sondern per `build:` aus dem Repo
|
||||||
|
# gebaut wird. Einmalig VOR dem ersten `docker compose up -d`:
|
||||||
|
# git clone https://github.com/NousResearch/hermes-agent.git hermes-agent-src
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
hermes-agent:
|
||||||
|
build: ./hermes-agent-src
|
||||||
|
image: hermes-agent
|
||||||
|
container_name: hermes-agent
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: host
|
||||||
|
depends_on:
|
||||||
|
- hermes-gateway
|
||||||
|
volumes:
|
||||||
|
# ~/.hermes-Aequivalent: Config, Sessions, Memory, Skills - alles persistent
|
||||||
|
# hier drin. hermes-agent-config/config.yaml.example wird VOR dem ersten
|
||||||
|
# Start einmalig hierher kopiert (siehe README) und dann von Hermes
|
||||||
|
# NICHT mehr angefasst (nur geseedet wenn's fehlt).
|
||||||
|
- ./hermes-data/agent-home:/opt/data
|
||||||
|
environment:
|
||||||
|
- HERMES_UID=${HERMES_UID:-10000}
|
||||||
|
- HERMES_GID=${HERMES_GID:-10000}
|
||||||
|
# Fuer die ${HERMES_GATEWAY_PORT}/${HERMES_GATEWAY_TOKEN}-Platzhalter in
|
||||||
|
# hermes-data/agent-home/config.yaml (Hermes expandiert ${VAR} beim
|
||||||
|
# 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}
|
||||||
|
# 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!
|
||||||
|
# Das hier ist Hermes ALS Server fuer einen Chat-Client, nicht Claude ALS
|
||||||
|
# Backend fuer Hermes). Zum Aktivieren beide Zeilen einkommentieren und
|
||||||
|
# API_SERVER_KEY in .env setzen:
|
||||||
|
# - API_SERVER_HOST=0.0.0.0
|
||||||
|
# - API_SERVER_KEY=${API_SERVER_KEY}
|
||||||
|
command: ["gateway", "run"]
|
||||||
|
|
||||||
|
hermes-agent-dashboard:
|
||||||
|
image: hermes-agent
|
||||||
|
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}
|
||||||
|
# Bindet nur auf localhost (Hermes' eigene Empfehlung, speichert API-Keys).
|
||||||
|
# Fuer Zugriff von aussen: `ssh -L 9119:localhost:9119 <diese-maschine>`.
|
||||||
|
command: ["dashboard", "--host", "127.0.0.1", "--no-open"]
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
hermes-net:
|
hermes-net:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Hermes Agent Model-Config — zeigt auf UNSEREN Claude-Max-Proxy statt auf
|
||||||
|
# OpenRouter/Nous Portal/direkte Provider-Keys.
|
||||||
|
#
|
||||||
|
# WICHTIG: das ist NICHT die volle ~/.hermes/config.yaml (die hat noch
|
||||||
|
# hunderte weitere optionale Blöcke — terminal, toolsets, memory, etc., siehe
|
||||||
|
# hermes-agent-src/cli-config.yaml.example fürs Referenz-Full-File). Diese
|
||||||
|
# Datei hier enthält bewusst NUR den model:-Block. Hermes seedet beim ersten
|
||||||
|
# Container-Start automatisch alle fehlenden Felder aus seinen eingebauten
|
||||||
|
# Defaults (Stage2-Hook: seed_one() kopiert cli-config.yaml.example NUR wenn
|
||||||
|
# config.yaml noch nicht existiert — diese Datei hier gewinnt also, wird
|
||||||
|
# NICHT überschrieben, solange sie schon liegt).
|
||||||
|
#
|
||||||
|
# ${HERMES_GATEWAY_PORT} / ${HERMES_GATEWAY_TOKEN} werden von Hermes selbst
|
||||||
|
# beim Config-Laden aus den Container-Env-Vars expandiert (nicht von Docker
|
||||||
|
# Compose) — die kommen im hermes-agent-Service aus .env durch. Deshalb hier
|
||||||
|
# NICHT hardcoden, auch nicht "zum Testen".
|
||||||
|
model:
|
||||||
|
# sonnet/opus/haiku werden vom Proxy-Adapter (proxy-patches/openai-to-cli.js,
|
||||||
|
# MODEL_MAP) auf die claude --model Flags gemappt. Unbekannte Namen fallen
|
||||||
|
# dort automatisch auf "opus" zurück.
|
||||||
|
default: "sonnet"
|
||||||
|
|
||||||
|
# "custom" = jeder OpenAI-kompatible Endpoint, der nicht einer der
|
||||||
|
# named Provider (openrouter/nous/anthropic/...) ist — genau unser Fall.
|
||||||
|
provider: "custom"
|
||||||
|
|
||||||
|
# localhost, weil Hermes Agent laut Stefan auf DERSELBEN Maschine läuft wie
|
||||||
|
# unser hermes-gateway (network_mode: host im hermes-agent-Service).
|
||||||
|
base_url: "http://localhost:${HERMES_GATEWAY_PORT}/v1"
|
||||||
|
|
||||||
|
# Gateway prüft das als "Authorization: Bearer <api_key>" — der OpenAI SDK
|
||||||
|
# (den Hermes intern nutzt) setzt den Header automatisch aus diesem Feld.
|
||||||
|
api_key: "${HERMES_GATEWAY_TOKEN}"
|
||||||
Reference in New Issue
Block a user