diff --git a/website/docs/reference/cli-commands.md b/website/docs/reference/cli-commands.md
index 439e64a42724..53d1ea3d83fa 100644
--- a/website/docs/reference/cli-commands.md
+++ b/website/docs/reference/cli-commands.md
@@ -1348,6 +1348,7 @@ Launch the web dashboard — a browser-based UI for managing configuration, API
| `--no-open` | — | Don't auto-open the browser |
| `--tui` | off | Enable the in-browser Chat tab by running `hermes --tui` behind a PTY/WebSocket bridge. Requires `pip install 'hermes-agent[web,pty]'` and a POSIX PTY environment such as Linux, macOS, or WSL2. |
| `--insecure` | off | Allow binding to non-localhost hosts. Exposes dashboard credentials on the network; use only behind trusted network controls. |
+| `--allowed-hosts` | — | Extra accepted Host headers for loopback proxy/tunnel access |
| `--stop` | — | Stop running `hermes dashboard` processes and exit. |
| `--status` | — | List running `hermes dashboard` processes and exit. |
@@ -1362,6 +1363,25 @@ hermes dashboard --port 8080 --no-open
hermes dashboard --tui
```
+### Dashboard service
+
+```bash
+hermes dashboard service install [--host 127.0.0.1] [--port 9119] [--tui] [--start-now]
+hermes dashboard service start|stop|restart|status|uninstall
+hermes dashboard service unit
+```
+
+Linux uses systemd user services by default (`--system` installs a boot-time
+system service), macOS uses launchd, and Windows uses a Scheduled Task.
+
+### Dashboard access helpers
+
+```bash
+hermes dashboard access tailscale-serve --port 9119 [--apply]
+hermes dashboard access cloudflare-config --tunnel --credentials-file --hostname
+hermes dashboard access cloudflare-service install|start|stop|restart|status|uninstall
+```
+
## `hermes profile`
```bash
diff --git a/website/docs/user-guide/features/web-dashboard.md b/website/docs/user-guide/features/web-dashboard.md
index 67cbe0e2a74c..d12997f55c8a 100644
--- a/website/docs/user-guide/features/web-dashboard.md
+++ b/website/docs/user-guide/features/web-dashboard.md
@@ -28,7 +28,9 @@ This starts a local web server and opens `http://127.0.0.1:9119` in your browser
| `--host` | `127.0.0.1` | Bind address |
| `--no-open` | — | Don't auto-open the browser |
| `--insecure` | off | Allow binding to non-localhost hosts (**DANGEROUS** — exposes API keys on the network; pair with a firewall and strong auth) |
+| `--allowed-hosts` | — | Extra Host headers accepted for loopback proxy/tunnel access |
| `--tui` | off | Expose the in-browser Chat tab (embedded `hermes --tui` via PTY/WebSocket). Alternatively set `HERMES_DASHBOARD_TUI=1`. |
+| `--skip-build` | off | Serve the existing bundled web dist without running the frontend build |
```bash
# Custom port
@@ -44,6 +46,69 @@ hermes dashboard --no-open
hermes dashboard --tui
```
+## Durable service
+
+Use `hermes dashboard service` to run the dashboard under the host service
+manager, matching the gateway service workflow:
+
+```bash
+# Linux systemd user service, macOS launchd, or Windows Scheduled Task
+hermes dashboard service install --tui --start-now
+hermes dashboard service status
+hermes dashboard service restart
+hermes dashboard service stop
+hermes dashboard service uninstall
+
+# Linux boot-time system service
+sudo hermes dashboard service install --system --run-as-user "$USER" --start-now
+```
+
+The generated service runs `hermes dashboard --no-open --skip-build` with the
+selected host, port, embedded-chat mode, profile, `HERMES_HOME`, PATH, and venv
+captured at install time. Pre-build the dashboard before installing if your
+deployment does not ship `hermes_cli/web_dist`.
+
+### Secure remote access
+
+The safest default is still a loopback-bound dashboard:
+
+```bash
+hermes dashboard service install --host 127.0.0.1 --port 9119
+```
+
+Expose that loopback service through an identity-aware tunnel or reverse proxy:
+
+```bash
+# Tailscale or headscale tailnet-only access
+hermes dashboard access tailscale-serve --port 9119 --apply
+
+# Generate a locally managed cloudflared tunnel config
+hermes dashboard access cloudflare-config \
+ --tunnel \
+ --credentials-file ~/.cloudflared/.json \
+ --hostname dashboard.example.com
+
+# Install/manage cloudflared's native service
+hermes dashboard access cloudflare-service install
+hermes dashboard access cloudflare-service restart
+```
+
+When a proxy forwards requests with a hostname other than `localhost`, allow it
+explicitly while keeping DNS-rebinding protection on:
+
+```bash
+hermes dashboard service install \
+ --allowed-hosts device.tailnet.ts.net,dashboard.example.com \
+ --public-url https://dashboard.example.com \
+ --start-now
+```
+
+`dashboard.allowed_hosts` in `config.yaml` and
+`HERMES_DASHBOARD_ALLOWED_HOSTS` provide the same allowlist for direct
+`hermes dashboard` runs. Public internet hostnames should be protected by
+Cloudflare Access, an OAuth `DashboardAuthProvider`, or an equivalent upstream
+identity policy.
+
## Prerequisites
The default `hermes-agent` install does not ship the HTTP stack or PTY helper — those are optional extras. The **web dashboard** needs FastAPI and Uvicorn (`web` extra). The **Chat** tab also needs `ptyprocess` to spawn the embedded TUI behind a pseudo-terminal (`pty` extra on POSIX). Install both with:
@@ -425,6 +490,11 @@ same auth gate as the rest of `/api/`.
| `PUT /api/memory/provider` | Select a provider (empty = built-in only) |
| `POST /api/memory/reset` | Reset built-in memory. Body: `{target: all\|memory\|user}` |
| `POST /api/gateway/start` · `/stop` · `/restart` | Gateway lifecycle (backgrounded) |
+| `GET /api/dashboard/service/status` | Dashboard service manager status |
+| `POST /api/dashboard/service/install` · `/start` · `/stop` · `/restart` · `/uninstall` | Dashboard service lifecycle (backgrounded) |
+| `POST /api/dashboard/access/tailscale-serve` | Apply Tailscale/headscale Serve for loopback dashboard access |
+| `POST /api/dashboard/access/cloudflare-config` | Generate a cloudflared tunnel config |
+| `POST /api/dashboard/access/cloudflare-service/{verb}` | Manage cloudflared's native service |
| `POST /api/ops/doctor` · `/security-audit` · `/backup` · `/import` | Diagnostics & maintenance (backgrounded; tail via `/api/actions/{name}/status`) |
| `GET /api/ops/hooks` | Configured shell hooks + allowlist status |
| `GET /api/ops/checkpoints` · `POST .../prune` | Inspect / prune the `/rollback` store |