mirror of
https://github.com/tiennm99/composes.git
synced 2026-10-11 03:13:16 +00:00
refactor: align openclaw and hermes with their official Docker guides
This commit is contained in:
1 parent
77c12d5397
commit
1cbbf271ce
6 files changed
+80
-73
No files matched your search
+29
-36
@@ -4,19 +4,19 @@
|
||||
agent with persistent memory, scheduling and chat-platform gateways, from Nous
|
||||
Research's official image, with its built-in web dashboard.
|
||||
|
||||
One container. `gateway run` starts the agent gateway, and the image's s6
|
||||
supervisor also starts the dashboard on port `9119`: chat (the Hermes
|
||||
terminal UI in the browser), sessions, config, cron, skills and logs.
|
||||
Laid out after upstream's
|
||||
[Docker guide](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/user-guide/docker.md):
|
||||
one container, one data volume at `/opt/data`, `gateway run` as the command,
|
||||
and `HERMES_DASHBOARD=1` so the image's s6 supervisor also runs the dashboard
|
||||
on port `9119`.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Set `HERMES_DASHBOARD_PUBLIC_URL`, `HERMES_DASHBOARD_PASSWORD`,
|
||||
`HERMES_DASHBOARD_SECRET` and `OPENROUTER_API_KEY`.
|
||||
1. Set `HERMES_DASHBOARD_PUBLIC_URL`, `HERMES_DASHBOARD_PASSWORD` and
|
||||
`HERMES_DASHBOARD_SECRET`.
|
||||
2. Map the domain to port `9119` and deploy.
|
||||
3. Open the domain and log in with `HERMES_DASHBOARD_USERNAME` /
|
||||
`HERMES_DASHBOARD_PASSWORD`.
|
||||
|
||||
Health check: `GET /api/status`, also the compose healthcheck.
|
||||
3. Open the domain, log in with `HERMES_DASHBOARD_USERNAME` /
|
||||
`HERMES_DASHBOARD_PASSWORD`, and add a model provider under Config.
|
||||
|
||||
## Environment
|
||||
|
||||
@@ -25,50 +25,43 @@ Health check: `GET /api/status`, also the compose healthcheck.
|
||||
| `HERMES_DASHBOARD_PUBLIC_URL` | — | Full public URL, e.g. `https://hermes.example.com` |
|
||||
| `HERMES_DASHBOARD_USERNAME` / `HERMES_DASHBOARD_PASSWORD` | `hermes` / — | Dashboard login |
|
||||
| `HERMES_DASHBOARD_SECRET` | — | Signs dashboard sessions |
|
||||
| `OPENROUTER_API_KEY` | empty | Model provider |
|
||||
| `TELEGRAM_BOT_TOKEN` | empty | Telegram bot; empty leaves Telegram off |
|
||||
| `TELEGRAM_ALLOWED_USERS` / `TELEGRAM_GROUP_ALLOWED_CHATS` | empty | Telegram users and group chats allowed to use the bot |
|
||||
| `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY` | optional | Other model providers |
|
||||
| `OPENROUTER_API_KEY`, `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY` | optional | Provider keys passed from the environment |
|
||||
|
||||
`HERMES_DASHBOARD=1` turns the dashboard on. Bound to `0.0.0.0`, it refuses to
|
||||
start without an auth provider, so the password is required. The image's
|
||||
username/password provider is the one that needs no outside identity service;
|
||||
upstream describes it as meant for trusted networks and recommends OAuth (Nous
|
||||
Portal) or self-hosted OIDC for a public domain.
|
||||
The dashboard refuses to start on a non-loopback bind without an auth
|
||||
provider, so the password is required. The username/password provider is the
|
||||
one that needs no outside identity service; upstream describes it as meant
|
||||
for trusted networks and recommends OAuth (Nous Portal) or self-hosted OIDC
|
||||
for a public domain.
|
||||
|
||||
`HERMES_DASHBOARD_PUBLIC_URL` adds the domain to the dashboard's Host and
|
||||
WebSocket Origin guard, which rejects requests for any other host.
|
||||
|
||||
`HERMES_DASHBOARD_SECRET` keeps sessions valid across restarts; without it
|
||||
each restart signs with a new random key and logs everyone out.
|
||||
each restart signs with a new random key.
|
||||
|
||||
The uid/gid are pinned to `1000` in `compose.yml`; the `Dockerfile` depends on
|
||||
that (see Storage).
|
||||
Provider keys are commented out because upstream keeps them in
|
||||
`/opt/data/.env`, written from the dashboard, so they survive without being
|
||||
repeated in Coolify. An environment variable, when set, wins over that file.
|
||||
|
||||
## Storage
|
||||
|
||||
| Volume | Mount | Holds |
|
||||
| --- | --- | --- |
|
||||
| `hermes-data` | `/opt/data` | `HERMES_HOME`: config, `.env`, sessions, memory, skills, logs |
|
||||
| `hermes-workspace` | `/workspace` | Files the agent works on |
|
||||
| `hermes-data` | `/opt/data` | `HERMES_HOME`: config, `.env`, sessions, memory, skills, logs, and the agent's working files |
|
||||
|
||||
The image hard-blocks the agent's file tools from writing outside
|
||||
`HERMES_WRITE_SAFE_ROOT`, which it sets to `/opt/data` alone, so
|
||||
`compose.yml` adds `/workspace` to it. `TERMINAL_CWD` starts gateway and cron
|
||||
terminal sessions in `/workspace`. Upstream marks that variable deprecated in
|
||||
favour of `terminal.cwd` in `config.yaml`; it is used here so the setting stays
|
||||
in the compose file rather than on the volume.
|
||||
`/opt/data` is the image's own home for all mutable state: it is the `hermes`
|
||||
user's home directory, the image declares it a volume, and the dashboard's
|
||||
start script uses it directly. The agent's file tools may only write under
|
||||
it. The `hermes` user keeps the image's default uid, `10000`, and the image fixes
|
||||
the volume's ownership for that user at start.
|
||||
|
||||
The `Dockerfile` exists only to make `/workspace` writable. The image does not
|
||||
ship that directory and its init chowns only `/opt/data`, so a named volume on
|
||||
`/workspace` would come up `root:root`. Creating the directory in the image,
|
||||
owned by `1000:1000`, fixes that: Docker seeds an empty named volume from the
|
||||
image directory, ownership included.
|
||||
## Resources
|
||||
|
||||
The 4 GB memory and 2 CPU limits are upstream's own compose example.
|
||||
|
||||
## Image
|
||||
|
||||
`nousresearch/hermes-agent:latest` moves only on stable releases, roughly
|
||||
weekly; upstream publishes no major tag. The agent's code lives in the image,
|
||||
not a volume, so a new release takes effect on the next pull and recreate. The
|
||||
first start after an upgrade migrates `config.yaml`, keeping a timestamped
|
||||
backup.
|
||||
not a volume, so a new release takes effect on the next pull and recreate.
|
||||
Reference in new issue
Block a user