feat(dashboard): add durable service support#37119
Open
LukasParke wants to merge 3 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds durable, installable service support for the Hermes web dashboard, matching the gateway's host-service workflow while keeping the dashboard loopback-bound by default.
This gives operators a first-class way to run the dashboard persistently under systemd, launchd, or a Windows Scheduled Task, plus secure remote-access helpers for Tailscale/headscale Serve and cloudflared. It also adds explicit dashboard Host-header allowlisting so loopback-bound dashboards can sit behind trusted local proxies/tunnels without disabling DNS-rebinding protection.
This builds on the new dashboard administration surface from #36704. Because the dashboard can now administer MCP, credentials, gateway lifecycle, memory, webhooks, and ops tasks, this PR keeps the default exposure model conservative:
127.0.0.1by default, OAuth gate behavior preserved for public binds, and explicit allowlists for proxy hostnames.Related Issue
Fixes #34390
Related follow-up/risk context:
--skip-build.Consolidated Related PR Content
#34390 was marked as part of the larger dashboard reverse-proxy Host-header allowlisting cluster. This PR consolidates the operator-facing Host-header / reverse-proxy portions of that cluster into the broader durable dashboard service/access feature, instead of landing another narrow allowlist-only variant.
Fully consolidated by this PR:
--allowed-hostsupport for Tailscale / reverse-proxy Host headers. Covered byhermes dashboard --allowed-hosts, plus service install/unit propagation.HERMES_DASHBOARD_EXTRA_HOSTS. Covered byHERMES_DASHBOARD_ALLOWED_HOSTS, with additional config and CLI surfaces.HERMES_DASHBOARD_ALLOWED_HOSTS, Host normalization, docs, and Tailscale Serve guidance. Covered by the same env var, plus config/CLI/service support.--allowed-hosts,dashboard.allowed_hosts, service persistence, and cloudflared config/service helpers.--trusted-host/HERMES_DASHBOARD_TRUSTED_HOSTSstyle trusted hostname allowlist. Covered by the single--allowed-hosts/HERMES_DASHBOARD_ALLOWED_HOSTSnaming surface.--allowed-hostswith Tailscale Serve and reverse proxies. Covered by direct dashboard runs and persisted service installs.Related but not fully consolidated by this PR:
dashboard.trusted_proxy_hostsmodel from fix(dashboard): validate WebSocket proxy peers and origins #20136.scheduledtype fix is intentionally not included.--tls-cert/--tls-keyis intentionally not included because this PR focuses on loopback plus trusted tunnel/proxy access.--insecurenon-loopback WebSocket fixes were already addressed on main; this PR preserves that path but does not add a separate--insecure-chatflag.Type of Change
Changes Made
hermes_cli/dashboard_service.py:$HERMES_HOME/dashboard-service/config.jsonhermes dashboardCLI:hermes dashboard service install|start|stop|restart|status|uninstall|unithermes dashboard access tailscale-servehermes dashboard access cloudflare-confighermes dashboard access cloudflare-service ...--allowed-hostsfor direct dashboard runs--allowed-hostsdashboard.allowed_hostsHERMES_DASHBOARD_ALLOWED_HOSTSHow to Test
Generate a service definition:
Print secure-access helper commands/config:
Run focused verification:
Observed results after resolving the latest
origin/mainmerge and cleanup:python -m py_compile hermes_cli/web_server.py tests/hermes_cli/test_web_server_host_header.py: passeduv run --frozen --with pytest --with pytest-timeout pytest tests/hermes_cli/test_web_server_host_header.py tests/hermes_cli/test_dashboard_service.py tests/hermes_cli/test_dashboard_admin_endpoints.py: 62 passed, 1 existingaudioopdeprecation warning fromdiscord/player.pywebproduction build passed, with the existing large chunk warninggit diff --checkpassedNot run:
pytest tests/ -q. The focused dashboard/service/web tests above were run instead.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
No screenshots. This is primarily CLI/service/API wiring plus the System page controls.