Files
homelab-infra/ops/hermes-agent/README.md
T
Micha 7161da00b3 hermes infos
hermes infos
2026-05-06 20:26:29 +02:00

520 lines
18 KiB
Markdown

# Hermes Agent for the Homelab
## Phase 1 - Documentation Analysis
### What Hermes Agent is
Hermes Agent is an autonomous AI agent from Nous Research with:
- CLI/TUI usage
- a messaging gateway for Telegram, Discord, Slack, WhatsApp, Signal, Email, Home Assistant and others
- persistent memory and session search under `~/.hermes/`
- scheduled jobs via the gateway
- multiple terminal backends (`local`, `docker`, `ssh`, `modal`, `daytona`, `singularity`)
The official docs describe it as an agent that lives on a server, remembers what it learns, and can be reached from different chat surfaces.
### Official installation paths
Officially documented paths:
- Linux/macOS/WSL2 installer via `curl ... install.sh | bash`
- official Docker image `nousresearch/hermes-agent`
- Nix / NixOS module
- source / development install from the Git repository
For this repository and your current Unraid + Compose operating model, the Docker image is the cleanest officially documented runtime path.
### Requirements from the docs
- Git is the only prerequisite for the standard installer
- the installer provisions `uv`, Python 3.11, Node.js v22, `ripgrep`, and `ffmpeg`
- Hermes requires an LLM with at least 64k context
- at least one provider must be configured
- API keys and secrets belong in `~/.hermes/.env`
- non-secret settings belong in `~/.hermes/config.yaml`
### Operating modes relevant for homelab use
- interactive CLI/TUI
- persistent messaging gateway
- optional OpenAI-compatible API server
- optional dashboard
- terminal execution backend selection
- Home Assistant integration via token plus event filters
### Security-relevant findings from the docs
- the gateway denies unknown users by default unless they are allowlisted or paired
- dangerous command approval applies to `local` and `ssh` terminal backends
- the official Docker terminal backend is considered a strong isolation boundary and skips dangerous-command approval
- the API server is localhost-only by default and becomes high-risk if bound to `0.0.0.0` without auth
- persistent memory is injected into the prompt and is security-scanned before acceptance
- the runtime Docker container itself runs as root by default according to the official Docker docs
- the official Docker docs explicitly warn against running two gateway containers against the same data directory
### Homelab relevance
Useful:
- Docker runtime container
- messaging gateway
- API server only on an internal network
- Home Assistant integration
- persistent memory, sessions, cron, logs
- SSH backend for separating tool execution from the NAS
- OpenAI-compatible backends such as OpenAI API and Ollama
Usually not first choice for this homelab:
- native installer directly on the NAS host
- mounting the host Docker socket into the Hermes runtime container
- internet-exposed API server
- `local` backend on the NAS host
- browser-heavy features unless explicitly needed
## Phase 2 - Architecture Decision
### Model A - Docker/Compose on NAS, `terminal.backend=local`
| Criterion | Assessment |
|---|---|
| Stability | High |
| Security | Medium |
| Wartability | High |
| Homelab integration | Very high |
| Complexity | Low |
Pros:
- fully official Docker runtime path
- best match to current Unraid/Compose/GitOps model
- easiest deployment and upgrade
Cons:
- terminal commands run inside the main Hermes service container
- no second isolation layer between agent runtime and tool execution
- package installs done by the agent are not a clean, persistent operating model
### Model B - Native Hermes install in dedicated Linux VM/LXC, `terminal.backend=docker`
| Criterion | Assessment |
|---|---|
| Stability | High |
| Security | Very high |
| Wartability | Medium |
| Homelab integration | Medium |
| Complexity | High |
Pros:
- closest match to the official security guidance for a production gateway
- clean separation between Hermes runtime and Docker sandboxed commands
- no NAS Docker socket exposed to a chat-facing container
Cons:
- separate lifecycle from your current Compose-centric homelab
- more moving parts to patch, back up, and monitor
### Model C - Docker/Compose gateway on NAS, `terminal.backend=ssh` to dedicated Linux runner
| Criterion | Assessment |
|---|---|
| Stability | High |
| Security | High |
| Wartability | High |
| Homelab integration | High |
| Complexity | Medium |
Pros:
- official Docker runtime path for Hermes itself
- official SSH backend for command execution
- no host Docker socket in the gateway container
- clean separation between chat-facing service and execution environment
- fits your existing NAS/Compose/GitOps model
Cons:
- requires a dedicated runner VM/LXC
- dangerous-command approval still applies on the SSH backend
## Phase 3 - Clear Recommendation
### Recommended target image
Use **Model C**:
- Hermes gateway and dashboard as official Docker containers on the NAS
- terminal execution via the official `ssh` backend to a dedicated Linux runner
- primary LLM via GPT/OpenAI API
- Ollama on the gaming PC as optional secondary provider, not as required infrastructure
- no Docker socket inside the Hermes gateway container
- dashboard behind Traefik + Authelia
- API server only on the internal `hermes_net`
### Why this is the best fit here
This gives you the official containerized deployment the docs support, while avoiding the least-auditable shortcut: giving a chat-facing agent container direct host Docker control.
For the model layer, the most robust setup for your homelab is a hybrid:
- OpenAI API as the primary inference backend
- Ollama on the gaming PC as an optional alternate backend
Reason:
- Hermes officially supports OpenAI-compatible endpoints, including Ollama
- your gaming PC is useful compute, but it should not be the only dependency for the agent's baseline availability
- with this split, Hermes still works when the gaming PC is off
Important inference:
The official docs clearly distinguish between:
1. running Hermes **in** Docker
2. using Docker as the **terminal backend**
I did **not** find an official deployment pattern that explicitly documents mounting the NAS Docker socket into the Hermes runtime container so that the runtime container itself manages sibling Docker sandboxes. The official runtime image docs list Python, Node, Playwright, `ripgrep`, and `ffmpeg`, but not the Docker CLI. Based on that, I treat "runtime container + host docker.sock for terminal backend" as a weakly documented path and do not recommend it for your production homelab.
## Phase 4 - Implementation
### Repository files
- `ops/hermes-agent/docker-compose.yml`
- `ops/hermes-agent/stack.env.example`
- `ops/hermes-agent/hermes.env.example`
- `ops/hermes-agent/config/hermes/config.yaml`
### Host paths used by this setup
- `/mnt/user/appdata/hermes-agent/data`
- `/mnt/user/appdata/hermes-agent/ssh`
- `/mnt/user/appdata/secrets/hermes_runner_id_ed25519`
### Deployment layout
- `hermes-gateway` stores state in `/opt/data`
- repo-managed `config.yaml` is bind-mounted read-only into `/opt/data/config.yaml`
- dashboard reads the same data volume but has no direct access to the SSH private key
- only the dashboard joins `frontend_net`
- the gateway stays off `frontend_net` and only exposes port `8642` internally on `hermes_net`
### Reverse proxy
Use Traefik only for the dashboard.
- yes for the dashboard
- no for the gateway API by default
- no public publish of `8642`
### Docker socket
Do **not** mount `/var/run/docker.sock`.
### Runner preparation
On the dedicated Linux VM/LXC:
```bash
sudo useradd --create-home --shell /bin/bash hermes
sudo mkdir -p /srv/hermes-workspace
sudo chown hermes:hermes /srv/hermes-workspace
sudo chmod 755 /srv/hermes-workspace
sudo -u hermes mkdir -p /home/hermes/.ssh
sudo -u hermes chmod 700 /home/hermes/.ssh
```
Add the NAS-side public key to `/home/hermes/.ssh/authorized_keys`:
```bash
sudo -u hermes sh -c 'cat >> /home/hermes/.ssh/authorized_keys'
sudo -u hermes chmod 600 /home/hermes/.ssh/authorized_keys
```
Recommended runner packages:
```bash
sudo apt-get update
sudo apt-get install -y bash ca-certificates curl git jq python3 python3-venv ripgrep ffmpeg
```
Do **not** grant `sudo` unless you have a concrete use case and a reviewed sudoers policy.
### NAS-side prep
```bash
mkdir -p /mnt/user/appdata/hermes-agent/data
mkdir -p /mnt/user/appdata/hermes-agent/ssh
chmod 700 /mnt/user/appdata/hermes-agent/ssh
```
Create the runner keypair on the NAS and keep the private key outside Git:
```bash
ssh-keygen -t ed25519 -f /mnt/user/appdata/secrets/hermes_runner_id_ed25519 -C hermes-runner
chmod 600 /mnt/user/appdata/secrets/hermes_runner_id_ed25519
chmod 644 /mnt/user/appdata/secrets/hermes_runner_id_ed25519.pub
```
### First-time configuration
1. Copy `stack.env.example` to `stack.env`.
2. Copy `hermes.env.example` to `/mnt/user/appdata/hermes-agent/data/.env`.
3. Fill the OpenAI API key and your chosen OpenAI model ID as the primary model.
4. Optionally add the Ollama endpoint from the gaming PC as an alternate model profile.
5. Fill API server key, messaging token(s), and SSH runner settings.
4. Deploy the stack.
Example local validation before shipping to Komodo:
```bash
docker compose --env-file stack.env config
docker compose --env-file stack.env up -d
```
## Phase 5 - Validation
### 1. Container health
```bash
docker compose --env-file stack.env ps
docker compose --env-file stack.env logs --tail=100 hermes-gateway
docker compose --env-file stack.env logs --tail=100 hermes-dashboard
```
### 2. API server / dashboard path
From the NAS:
```bash
docker exec hermes-gateway python3 -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8642/health', timeout=3).read().decode())"
```
Expected: `{"status":"ok"}` or equivalent health JSON.
### 3. Hermes self-check
```bash
docker exec -it hermes-gateway hermes doctor
docker exec -it hermes-gateway hermes config
```
Use `hermes doctor` first whenever provider or backend setup is suspect.
### 4. SSH backend check
Inside Hermes, issue a harmless command such as:
```text
Run `hostname` and `pwd`.
```
Expected:
- hostname is the runner VM/LXC, not the NAS
- working directory is `/srv/hermes-workspace`
### 5. Model/provider check
Inside Hermes:
```text
Tell me which provider and model you are using.
```
Then run one simple, no-tool prompt and one tool-using prompt. If the base provider works but web tools fail, the likely issue is missing web-tool credentials rather than a broken main model.
Recommended operator check:
- first validate with the primary GPT/OpenAI backend
- then temporarily switch to the Ollama endpoint and confirm Hermes can still answer and call tools
- treat Ollama as optional capacity, not as required uptime dependency
### 6. Persistence / memory check
After at least one session and one saved memory:
```bash
ls -la /mnt/user/appdata/hermes-agent/data
ls -la /mnt/user/appdata/hermes-agent/data/memories
```
Check for:
- `config.yaml`
- `.env`
- `memories/`
- `sessions/`
- `logs/`
- `state.db`
### 7. Home Assistant check
If `HASS_TOKEN` is set:
- verify Hermes sees the `homeassistant` toolset
- ask it to list a few entities
- trigger a watched entity and confirm the gateway receives an event
If no HA events arrive, first check `watch_domains`, `watch_entities`, and `ignore_entities`.
### Common misconfiguration signals
- dashboard unhealthy: API server not enabled or not reachable on `0.0.0.0:8642`
- Hermes cannot run terminal commands: SSH key, host, user, or remote permissions are wrong
- web tools missing: no supported web-search provider configured
- HA tools missing: `HASS_TOKEN` not set
- unknown users can message the bot: allowlist or pairing policy not configured
## Phase 6 - Hardening
### Minimal rights
- keep `cap_drop: [ALL]`
- keep `no-new-privileges:true`
- keep the gateway off `frontend_net`
- do not mount the Docker socket
- do not run Hermes directly on the NAS host
- do not grant the runner user blanket `sudo`
### Secrets handling
- keep provider keys and bot tokens in `/mnt/user/appdata/hermes-agent/data/.env`
- keep the SSH private key in `/mnt/user/appdata/secrets/hermes_runner_id_ed25519`
- limit file permissions to `600`
- if Komodo injects secrets as stack env vars, use that only where Hermes upstream requires env-only config
### Tool isolation
- terminal execution goes only to the dedicated runner
- use the Home Assistant token only if HA control is needed
- reduce enabled tools with `hermes tools` once the base deployment is stable
### Network boundaries
- expose only the dashboard through Traefik
- keep `8642` internal unless you intentionally integrate a frontend such as Open WebUI
- if you later expose the API server beyond `hermes_net`, keep bearer auth enabled and scope it tightly
### Model strategy
- keep GPT/OpenAI as the default production path
- use Ollama when you explicitly want local inference or lower marginal cost
- do not design the base service around the assumption that the gaming PC is always on
### Updates
- current official Docker tag used here: `nousresearch/hermes-agent:v2026.4.16`
- update deliberately, test with `hermes doctor`, then roll forward
- avoid `latest` in production if you want reproducibility
### Backups
Back up at least:
- `/mnt/user/appdata/hermes-agent/data/.env`
- `/mnt/user/appdata/hermes-agent/data/config.yaml`
- `/mnt/user/appdata/hermes-agent/data/auth.json`
- `/mnt/user/appdata/hermes-agent/data/memories/`
- `/mnt/user/appdata/hermes-agent/data/sessions/`
- `/mnt/user/appdata/hermes-agent/data/cron/`
- `/mnt/user/appdata/hermes-agent/ssh/known_hosts`
- `/mnt/user/appdata/secrets/hermes_runner_id_ed25519`
## Phase 7 - Ops Monitor (homelab-ops-monitor)
### Was es ist
Ein Skill + Script das Hermes zum kontextuellen Ops-Assistenten macht.
Wenn ein Service ausfaellt, bekommt er nicht eine rohe Fehlermeldung, sondern einen
angereicherten Alert: Abhaengigkeiten, letzter Backup-Dump, erster Diagnoseschritt.
### Laufzeit-Architektur (Stand 2026-05-06)
- Hermes laeuft als Docker-Container auf dem Unraid-Host (hermes-gateway, hermes_net)
- Terminal-Backend SSH-Ziel: `192.168.178.143` (dedizierte Linux-VM, Model C)
- Hermes-User auf der VM: `hermes`
- Repo-Clone auf der VM: `/srv/hermes-workspace/homelab-infra/`
- Workspace-Verzeichnis auf der VM: `/srv/hermes-workspace/`
Wichtig fuer KI-Agenten und Betreiber: Das Terminal laeuft auf der VM, nicht auf dem
Unraid-Host. `/mnt/user/...`-Pfade sind von der VM aus nicht direkt erreichbar.
Docker-CLI ist auf der VM nicht vorhanden und wird nicht benoetigt.
### Dateien
| Datei | Pfad im Repo | Pfad auf VM |
|---|---|---|
| Wissensbasis | `ops/hermes-agent/services.json` | `/srv/hermes-workspace/homelab-infra/ops/hermes-agent/services.json` |
| Health-Script | `ops/hermes-agent/scripts/check_health.py` | `/srv/hermes-workspace/homelab-infra/ops/hermes-agent/scripts/check_health.py` |
| Skill-Prompt | `ops/hermes-agent/skills/homelab-ops-monitor.md` | `/srv/hermes-workspace/homelab-infra/ops/hermes-agent/skills/homelab-ops-monitor.md` |
### check_health.py
- Keine externen Abhaengigkeiten — nur Python-Standardbibliothek (`json`, `urllib`, `ssl`)
- Kein Docker CLI, kein pip, kein Root noetig
- Prueft Services mit URL via HTTP GET (2xx/3xx/4xx = healthy, 5xx/Timeout = unhealthy)
- Interne Services ohne URL (Datenbanken, Redis) werden als `"internal"` markiert — kein Fehler
- Dump-Timestamps werden gelesen falls `/mnt/user/backups/borg/dumps/latest` erreichbar ist (optional)
- services.json wird relativ zum Script-Verzeichnis gesucht (`../services.json`)
Verwendung auf der VM:
```bash
cd /srv/hermes-workspace/homelab-infra
python3 ops/hermes-agent/scripts/check_health.py --summary # Tier 1+2
python3 ops/hermes-agent/scripts/check_health.py paperless-ngx # gezielt
python3 ops/hermes-agent/scripts/check_health.py --all # alle Tiers
```
### services.json
Maschinenlesbare Wissensbasis abgeleitet aus `docs/SERVICE_CATALOG.md`.
Enthaelt fuer jeden Service: Tier, Container-Name, Abhaengigkeiten, Dump-Dateiname,
Datenpfade, first_check-Hinweis und betriebliche Notizen.
Bei Aenderungen am Service Catalog: `services.json` und `services.yaml` parallel aktualisieren.
### Skill importieren
```
„Bitte erstelle einen neuen Skill namens homelab-ops-monitor. Lies dazu die Datei
/srv/hermes-workspace/homelab-infra/ops/hermes-agent/skills/homelab-ops-monitor.md
und lege den Skill mit diesem Inhalt an."
```
Nach Repo-Aenderungen auf der VM pullen:
```bash
cd /srv/hermes-workspace/homelab-infra && git pull
```
### Bekannte Einschraenkungen
- Interne Services (PostgreSQL, Redis, MongoDB) koennen nicht extern geprueft werden
- Dump-Timestamps nur lesbar wenn `/mnt/user/backups/` per NFS oder Mount erreichbar ist
- Docker-Healthstatus der Container ist von der VM aus nicht pruefbar (kein Docker-Socket)
- Alerting via ntfy erfordert dass ntfy selbst healthy ist (Fallback: Telegram)
---
## Official sources used
- Repository README: <https://github.com/NousResearch/hermes-agent>
- Installation: <https://hermes-agent.nousresearch.com/docs/getting-started/installation/>
- Quickstart: <https://hermes-agent.nousresearch.com/docs/getting-started/quickstart/>
- Configuration: <https://hermes-agent.nousresearch.com/docs/user-guide/configuration/>
- Docker: <https://hermes-agent.nousresearch.com/docs/user-guide/docker/>
- Security: <https://hermes-agent.nousresearch.com/docs/user-guide/security/>
- Tools and Toolsets: <https://hermes-agent.nousresearch.com/docs/user-guide/features/tools/>
- Built-in tools reference: <https://hermes-agent.nousresearch.com/docs/reference/tools-reference/>
- Persistent memory: <https://hermes-agent.nousresearch.com/docs/user-guide/features/memory/>
- Messaging gateway: <https://hermes-agent.nousresearch.com/docs/user-guide/messaging/>
- Home Assistant integration: <https://hermes-agent.nousresearch.com/docs/user-guide/messaging/homeassistant/>
- AI providers: <https://hermes-agent.nousresearch.com/docs/integrations/providers/>
- FAQ: <https://hermes-agent.nousresearch.com/docs/reference/faq/>
- Nix / NixOS setup: <https://hermes-agent.nousresearch.com/docs/getting-started/nix-setup/>
- Official Docker tags: <https://hub.docker.com/r/nousresearch/hermes-agent/tags>