All checks were successful
images / hermes (push) Successful in 37s
The image's command selects mode; no command = interactive CLI which crash-loops under systemd. Switched to the supported headless setup: one container running `gateway run` with the dashboard supervised alongside via HERMES_DASHBOARD=1 (same netns so the dashboard can reach the gateway, which two bridge-networked containers could not). Image fails closed on a 0.0.0.0 dashboard bind, so HERMES_DASHBOARD_INSECURE=1 opts into the chosen trusted-LAN exposure on :5100. Verified live on bob: gateway stable, dash HTTP 200 across the LAN, inference endpoint reachable, enrolled in podman-auto-update.timer. Dropped the redundant separate dashboard quadlet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011D3YeWKpjg5bT488fVanCH
75 lines
3.3 KiB
Markdown
75 lines
3.3 KiB
Markdown
# hermes
|
|
|
|
[NousResearch Hermes Agent](https://github.com/NousResearch/hermes-agent) — a
|
|
self-improving AI agent — packaged for lair infra and published to
|
|
`git.lair.cafe/lair/hermes`.
|
|
|
|
## How it's built
|
|
|
|
Upstream ships its own `Dockerfile` (debian 13 + s6-overlay), so there is **no
|
|
vendored Containerfile here**. The `images` workflow (and `build.sh`) build
|
|
straight from the upstream git context at the latest release tag:
|
|
|
|
```
|
|
podman build github.com/NousResearch/hermes-agent.git#<tag> \
|
|
-t git.lair.cafe/lair/hermes:<version> -t git.lair.cafe/lair/hermes:latest
|
|
```
|
|
|
|
Builds are **release-triggered** (daily poll of the GitHub releases API; a build
|
|
runs only when that version isn't already in our registry) and **self-healing**
|
|
(a failed build leaves the version absent, so the next poll retries). Force a
|
|
rebuild via the workflow's `force` dispatch input, or locally:
|
|
|
|
```
|
|
HERMES_REF=v0.2.0 ./build.sh
|
|
```
|
|
|
|
## How it runs (single container, gateway + dashboard)
|
|
|
|
The image is an s6-overlay supervisor. The **command selects the mode** — the
|
|
default (no command) is the *interactive CLI*, which exits without a TTY under
|
|
systemd and crash-loops. The supported headless setup (per the image's own
|
|
startup guidance) is **one container running `gateway run` with the dashboard
|
|
supervised alongside** via `HERMES_DASHBOARD`:
|
|
|
|
- `Exec=gateway run` → the agent daemon (`hermes gateway run --replace`), s6-supervised.
|
|
- `HERMES_DASHBOARD=1` → the dashboard web UI (binds `0.0.0.0:9119`) in the **same**
|
|
container — which is what lets it reach the gateway (two bridge-networked
|
|
containers could not, unlike upstream's host-networked compose).
|
|
- The image **fails closed** on a non-loopback dashboard bind: it refuses
|
|
`0.0.0.0` unless OAuth is configured *or* `HERMES_DASHBOARD_INSECURE=1` is set.
|
|
We expose on the trusted LAN without auth, so we opt in. ⚠ Anyone on the LAN
|
|
can reach the API-key-storing UI — switch to `HERMES_DASHBOARD_OAUTH_CLIENT_ID`
|
|
for real auth if that's not acceptable.
|
|
|
|
Persistent state — `config.yaml`, `.env`, sessions, memory, skills — all lives
|
|
under `/opt/data` (the single `:Z` volume). Keys/backend go in those mounted
|
|
files, never in the image or quadlet.
|
|
|
|
## Deploying on bob
|
|
|
|
See [`hermes.container`](hermes.container) — a rootful quadlet matching the
|
|
existing `agent-zero` / `open-webui` services. As deployed:
|
|
|
|
1. Publish `git.lair.cafe/lair/hermes:latest` (the `images` workflow).
|
|
2. `sudo install -d -o 10000 -g 10000 /var/lib/hermes`
|
|
3. Drop `config.yaml` into `/var/lib/hermes` (owned `10000:10000`) — **LLM backend
|
|
→ local sovereign inference** via Hermes' `custom` OpenAI-compatible provider:
|
|
|
|
```yaml
|
|
# /var/lib/hermes/config.yaml
|
|
model:
|
|
provider: "custom"
|
|
base_url: "http://hanzalova.internal:31313/v1" # same endpoint open-webui uses
|
|
api_key: "<your-inference-key>"
|
|
default: "<model-id>" # see: curl …/v1/models
|
|
# context_length / max_tokens optional
|
|
```
|
|
|
|
Other secrets (web-search/tool keys, messaging tokens) go in
|
|
`/var/lib/hermes/.env`.
|
|
4. Install `hermes.container` to `/etc/containers/systemd/`, `daemon-reload`,
|
|
`start hermes.service`. Dashboard then serves on the LAN at
|
|
`http://bob.hanzalova.internal:5100/`; `AutoUpdate=registry` enrolls it in the
|
|
host's `podman-auto-update.timer`.
|