| name | hermes-webui-ops |
| description | Deploy, verify, and operate the Hermes WebUI (nesquena/hermes-webui) as a service on codex-klava. Use when asked to set up, check, restart, or troubleshoot the web/phone UI for the Hermes agent. |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| platforms | ["linux"] |
| metadata | {"hermes":{"tags":["Hermes","WebUI","systemd","Deployment","Ops","Tailscale"],"related_skills":["claude-code","hermes-autonomy-ops","healthcheck"]}} |
Hermes WebUI — Deploy & Operate (codex-klava)
Hermes WebUI is a lightweight dark-themed
web/phone frontend for the Hermes agent. It runs the agent in-process, reading
the existing HERMES_HOME config directly — so it plugs into the same memory, skills,
cron, and providers this agent already uses. No separate API server is needed for chat.
ALWAYS check for an existing install before setting anything up
"Set up X" often means X is already set up. The actual work is recognition +
verification, not re-installation. Run this diagnostic FIRST and stop if it's already healthy:
ss -tlnp 2>/dev/null | grep -E ':8787'
systemctl is-active hermes-webui.service ; systemctl is-enabled hermes-webui.service
systemctl cat hermes-webui.service
curl -s http://127.0.0.1:8787/health
curl -s -m 5 http://100.100.232.81:8787/health
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" http://127.0.0.1:8787/
If /health returns status: ok, the unit is active + enabled, and / redirects
to /login, it's already done — report the access URL and stop. Don't reinstall.
⚠️ Pitfall #1: ./ctl.sh status LIES "stopped" when systemd owns the process
The repo ships ctl.sh (start/status/logs/restart/stop). It only tracks processes it
launched itself via its own PID file at ~/.hermes/webui.pid. On codex-klava the
WebUI is launched by systemd (hermes-webui.service), not ctl.sh, so:
$ ./ctl.sh status
● hermes-webui — stopped <-- FALSE. It's running under systemd.
PID: - Health: not checked
This is a red herring. The process is alive (verify: curl /health returns ok, and
ps -o ppid= -p <pid> shows PPID 1 = adopted by init/systemd). On this server, manage
the WebUI with systemctl / journalctl -u hermes-webui, NOT ctl.sh. ctl.sh stop
cannot stop a systemd-launched server either. (Only use ctl.sh on hosts where you
actually launched it via ctl.sh start.)
The codex-klava deployment (reference config)
Unit file: /etc/systemd/system/hermes-webui.service. Key facts:
- Repo checkout:
/srv/codex-klava/hermes-webui (origin nesquena/hermes-webui)
User=codex, WorkingDirectory=/srv/codex-klava/hermes-webui
HERMES_HOME=/srv/codex-klava/data/hermes
- Agent dir/venv:
/srv/codex-klava/apps/hermes-agent (venv/bin/python3)
- Bind:
HERMES_WEBUI_HOST=0.0.0.0, HERMES_WEBUI_PORT=8787
EnvironmentFile=/srv/codex-klava/hermes-webui/.env — holds HERMES_WEBUI_PASSWORD
ExecStart=... bootstrap.py --foreground --no-browser --skip-agent-install 8787
Restart=on-failure, WantedBy=multi-user.target (autostart on boot)
- Logs:
append:/srv/codex-klava/data/hermes/webui.log (so journalctl may show "No entries" — tail the file instead)
- Access from Tailnet:
http://100.100.232.81:8787 (log in with the password from .env)
Full diagnostic transcript + unit dump: references/codex-klava-deployment.md.
Operating commands
systemctl status hermes-webui.service
sudo systemctl restart hermes-webui.service
journalctl -u hermes-webui.service -n 50 --no-pager
tail -50 /srv/codex-klava/data/hermes/webui.log
Security note
The unit binds 0.0.0.0 (reachable on the Tailnet), so a password must be set
(HERMES_WEBUI_PASSWORD in .env). Verify with the / -> /login 302 check above
before declaring it safe. Don't expose the port to the public internet without auth.
Version / upgrade
git -C /srv/codex-klava/hermes-webui describe --tags for the running version.
WebUI and hermes-agent should be upgraded together (matching release train) — the
WebUI imports agent internals directly, so version skew can cause import/behavior drift.
After git pull, sudo systemctl restart hermes-webui.service and re-run the health check.