The vault is the project's source of truth, so a link to a page that does not
exist is a promise the repo cannot keep. Three were dangling:
- Dankclaw/Gitea.md pointed twice at dankclaw/compose.yaml — **which this
session retired**. The clean cutover obligation from my own change: the page
now describes the unit that publishes 3000 and the canonical Caddy unit, and
records why the compose file is gone.
- Dankclaw/Hermes-Dashboard.md linked [[LAN DNS]]; the page is [[LAN-DNS]].
- LLM/frank-medium-radiance-mxfp4.md linked [[Observability on Dankclaw]]; the
page is [[Observability]].
scripts/check-vault-links.py + a seam keep it that way. The checker models
Obsidian's rules, which took three corrections to get right — and each was a
false positive that would have sent me editing healthy docs:
1. Wikilinks are case-insensitive. A case-sensitive matcher reported 45
breaks; 39 were `[[qBittorrent]]` vs qbittorrent.md.
2. `[[folder/Note]]` resolves by path suffix, not by stem.
3. `%20` in a markdown link is URL-encoding, not a filename.
Validating the linter against the resolver it models is the prerequisite for
trusting any of its output — the same discipline that caught a bad assertion of
my own earlier tonight.
4.1 KiB
Hermes-Dashboard
The Hermes web dashboard is a browser UI for managing the agent. It shows config, API keys, and sessions. It is a management tool. It is not a chat window. Chat happens over Signal or the CLI. See Hermes.
Host: Dankclaw — Port: 9119 (published) — URL: https://hermesadmin.franksdank.cloud (internal-only; direct Caddy proxy, no guard chain) or http://192.168.0.143:9119
Facts
| Item | Value |
|---|---|
| Image | docker.io/nousresearch/hermes-agent:latest (same as the gateway) |
| Command | hermes dashboard --host 0.0.0.0 --port 9119 --no-open --skip-build |
| Port | 9119 (published to the LAN) |
| Auth | HTTP basic auth (username + scrypt password hash) |
| Data | bind mount /home/dank/Containers/hermes/data → /data, shared with the gateway; plus a fresh anonymous volume at /opt/data per recreation |
Why a separate container
The gateway container runs hermes gateway run (the Signal platform). That
entrypoint does not start the dashboard. The dashboard is a separate process, so
it runs in its own Quadlet unit
(dankclaw/hermes/quadlet/hermes-dashboard.container:
image localhost/hermes-agent:latest, Pull=never, Exec=hermes dashboard --host 0.0.0.0 --port 9119 --no-open --skip-build, Restart=always,
RestartSec=5). All three Hermes containers mount the same /data bind mount.
Unlike its two siblings — hermes.container and hermes-webui.container both
run with Network=host — the dashboard is the only Hermes container on a bridge
network (Network=dankclaw_default, subnet 10.89.1.0/24, gateway 10.89.1.1).
That has a functional consequence: from inside its namespace it can dial only
published ports via the gateway IP, and host.containers.internal
(169.254.1.2) is an alias on the default podman network that this container
is not attached to, so probes to it time out. It therefore never talks to the
gateway, the webui, or the CDP daemon over the network — it shares their state
through the bind mount instead. See Container Network Namespaces.
Authentication
The dashboard refuses to bind to a non-loopback address without an auth provider. There is no unauthenticated public bind. This repo uses basic auth:
dashboard.basic_auth.usernameanddashboard.basic_auth.password_hashlive in the live/data/config.yaml(host path/home/dank/Containers/hermes/data/config.yaml); the tracked backup atdankclaw/hermes/config.yaml.exampleintentionally omits the password hash.- The stored value is a one-way scrypt hash. The plaintext password is never written to a file or the repo.
- The hash is generated with
plugins.dashboard_auth.basic.hash_password.
Access
Two paths reach the same process, both gated by the dashboard's own basic-auth login — there is no unauthenticated bind:
https://hermesadmin.franksdank.cloud— Caddy vhost added 2026-09-02 that reverse-proxies192.168.0.143:9119directly, with no Anubis/Outpost guard chain in front of it (exempt-by-construction: the app carries its own complete auth). The name deliberately has no public DNS record, so the vhost resolves on the LAN only; WAN clients get NXDOMAIN. See LAN-DNS.http://192.168.0.143:9119— the raw published port. Still reachable from any LAN host (the container binds0.0.0.0inside its namespace and publishes9119:9119), so treat the LAN as a trusted boundary here, not as a gate. See Container Network Namespaces for why this container is on a bridge network rather than the host namespace like its two siblings.
Gotchas
- The dashboard and the gateway share one data volume. A config change made in the dashboard takes effect when the gateway restarts.
- If the shared password is reused elsewhere, treat it as exposed. Rotate it and regenerate the hash.
--skip-builduses the prebuilt web assets in the image. Do not remove it unless the assets are rebuilt.
See Also
- Hermes-WebUI — the phone-facing API server (Hermex)
- Container Network Namespaces — why this container cannot dial the gateway, webui, or CDP daemon