@@ -175,6 +175,47 @@ The app is immediately live at `https://<host>/<slug>/`.
175175upstream (Caddy on `:8080`) at `:443`; Caddy handles all per-app path routing. Only edit
176176`~/openclaw-apps/router/tailscale-serve.json` when changing ports or funnel state.
177177
178+ ### Adding a Hermes dashboard
179+
180+ A common app is a Hermes agent's own dashboard. Two gotchas specific to Hermes:
181+
182+ 1. **Build the web UI first, or drop `--skip-build`.** The dashboard is served from a
183+ pre-built `web_dist/` directory. On a fresh Hermes install that directory may not
184+ exist yet, and `hermes dashboard --skip-build` will crash-loop with
185+ `✗ --skip-build was passed but no web dist found`. Build it once:
186+
187+ ```
188+ cd ~ /.hermes/hermes-agent/web && npm install && npm run build
189+ ```
190+
191+ This emits `~/.hermes/hermes-agent/hermes_cli/web_dist/`. After that, `--skip-build`
192+ works (and is preferred under PM2 so the process starts instantly without rebuilding).
193+
194+ 2. **Pin the profile and `HERMES_HOME`.** A dashboard reads sessions from one SQLite DB.
195+ For a profile agent, pass `--profile <name>`; for the root agent (cron jobs, no
196+ profile), omit `--profile`. Always set `HERMES_HOME` explicitly in the PM2 `env` so
197+ PM2's rewritten `$HOME` doesn't point the dashboard at an empty DB:
198+
199+ ```js
200+ {
201+ name: "hermes-<agent>",
202+ script: "/Users/<user>/.hermes/hermes-agent/venv/bin/hermes",
203+ args: "--profile <name> dashboard --port 9120 --no-open --skip-build",
204+ interpreter: "none",
205+ cwd: "/Users/<user>/.hermes/hermes-agent",
206+ env: {
207+ PATH: "/Users/<user>/.hermes/hermes-agent/venv/bin:/opt/homebrew/bin:/usr/bin:/bin",
208+ HERMES_HOME: "/Users/<user>/.hermes",
209+ },
210+ max_restarts: 10,
211+ min_uptime: "30s",
212+ }
213+ ```
214+
215+ Add the matching ` forward_auth ` + ` strip_prefix ` Caddy block with
216+ ` header_up X-Forwarded-Prefix /hermes-<agent> ` so the dashboard's SPA asset URLs
217+ resolve under the path prefix.
218+
178219## Removing an App
179220
180221```
@@ -213,6 +254,16 @@ Slugs are validated against `^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$` — lowerca
213254alphanumerics and hyphens, max 32 chars. Anything outside that gets a 400 from
214255` /auth/verify ` and ` /auth/login ` .
215256
257+ ** The session cookie is ` Secure ` , so password-protected apps only work over HTTPS.**
258+ The cookie is set with the ` Secure ` attribute, which means browsers (and ` curl ` ) will
259+ refuse to send it back over plain ` http:// ` . If you front the router with a plain-HTTP
260+ Tailscale Serve listener (e.g. ` tailscale serve --http=<port> ` ), login will appear to
261+ succeed (the POST returns a 303) but every subsequent request gets bounced back to the
262+ login page because the cookie never returns. Always expose the router over an ** HTTPS**
263+ door — ` tailscale serve --https=<port> http://127.0.0.1:8080 ` for tailnet-only, or the
264+ default ` :443 ` HTTPS funnel. Open (no-password) apps work fine over HTTP because they
265+ have no cookie to lose.
266+
216267## Fronting OpenClaw Webhooks (optional)
217268
218269External callers like AgentMail Svix webhooks and iOS Shortcuts don't always support
@@ -285,6 +336,17 @@ the app emits HTML with absolute paths to `/static/...` that 404 once it lives u
285336` /my-app/ ` . Either configure a base path in the app, or rewrite assets at the Caddy
286337layer.
287338
339+ ** Login succeeds (303) but every page bounces back to the login screen.** The session
340+ cookie is ` Secure ` and you're serving over plain HTTP, so the browser never sends the
341+ cookie back. Expose the router over HTTPS instead — `tailscale serve --https=<port >
342+ http://127.0.0.1:8080` (tailnet-only) or the default ` :443 ` funnel. See the note in the
343+ Auth Model section.
344+
345+ ** A Hermes dashboard app crash-loops in PM2.** Check ` pm2 logs hermes-<agent> ` . If you
346+ see ` ✗ --skip-build was passed but no web dist found ` , the dashboard UI was never built
347+ on this machine. Build it once with `cd ~ /.hermes/hermes-agent/web && npm install &&
348+ npm run build` , then ` pm2 restart hermes-<agent >`. See "Adding a Hermes dashboard."
349+
288350** Tailscale config gets wiped on gateway restart.** The OpenClaw gateway's Tailscale
289351integration is enabled. Disable it in ` ~/.openclaw/openclaw.json ` :
290352
0 commit comments