hermes
Hermes Agent: an autonomous AI 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.
Setup
- Set
HERMES_DASHBOARD_PUBLIC_URL,HERMES_DASHBOARD_PASSWORD,HERMES_DASHBOARD_SECRETandOPENROUTER_API_KEY. - Map the domain to port
9119and deploy. - Open the domain and log in with
HERMES_DASHBOARD_USERNAME/HERMES_DASHBOARD_PASSWORD.
Health check: GET /api/status, also the compose healthcheck.
Environment
| Variable | Default | Purpose |
|---|---|---|
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 |
ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY |
optional | Other model providers |
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.
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.
The uid/gid are pinned to 1000 in compose.yml; the Dockerfile depends on
that (see Storage).
Storage
| Volume | Mount | Holds |
|---|---|---|
hermes-data |
/opt/data |
HERMES_HOME: config, .env, sessions, memory, skills, logs |
hermes-workspace |
/workspace |
Files the agent works on |
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.
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.
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.