Skip to content

feat(dashboard): add durable service support#37119

Open
LukasParke wants to merge 3 commits into
NousResearch:mainfrom
LukasParke:dashboard-service-support
Open

feat(dashboard): add durable service support#37119
LukasParke wants to merge 3 commits into
NousResearch:mainfrom
LukasParke:dashboard-service-support

Conversation

@LukasParke

@LukasParke LukasParke commented Jun 2, 2026

Copy link
Copy Markdown

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.1 by default, OAuth gate behavior preserved for public binds, and explicit allowlists for proxy hostnames.

Related Issue

Fixes #34390

Related follow-up/risk context:

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:

Related but not fully consolidated by this PR:

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Added hermes_cli/dashboard_service.py:
    • systemd user/system unit generation and lifecycle
    • macOS launchd plist generation and lifecycle
    • Windows Scheduled Task wrapper generation and lifecycle
    • persisted dashboard service install options under $HERMES_HOME/dashboard-service/config.json
    • Tailscale/headscale Serve command generation/apply helper
    • cloudflared tunnel config generation and native service helper
  • Extended hermes dashboard CLI:
    • hermes dashboard service install|start|stop|restart|status|uninstall|unit
    • hermes dashboard access tailscale-serve
    • hermes dashboard access cloudflare-config
    • hermes dashboard access cloudflare-service ...
    • --allowed-hosts for direct dashboard runs
  • Added dashboard Host-header allowlisting:
    • CLI: --allowed-hosts
    • config: dashboard.allowed_hosts
    • env: HERMES_DASHBOARD_ALLOWED_HOSTS
    • applies to HTTP and WebSocket Host/Origin checks
  • Added authenticated dashboard admin endpoints:
    • dashboard service status/install/start/stop/restart/uninstall
    • Tailscale Serve apply
    • cloudflared config generation/service actions
  • Updated the System page with dashboard service and secure access controls.
  • Updated API types/client methods and web dashboard / CLI docs.
  • Added focused tests for service generation, access helpers, Host allowlisting, WebSocket allowlisting, and admin endpoints.

How to Test

  1. Generate a service definition:

    hermes dashboard service unit \
      --host 127.0.0.1 \
      --port 9119 \
      --allowed-hosts device.tailnet.ts.net \
      --public-url https://device.tailnet.ts.net
  2. Print secure-access helper commands/config:

    hermes dashboard access tailscale-serve --port 9119
    hermes dashboard access cloudflare-config \
      --tunnel t123 \
      --credentials-file /tmp/t.json \
      --hostname dash.example.com \
      --port 9119
  3. Run focused verification:

    python -m py_compile hermes_cli/dashboard_service.py hermes_cli/main.py hermes_cli/web_server.py
    uv run --frozen --with pytest --with pytest-timeout pytest tests/hermes_cli/test_dashboard_service.py
    uv run --frozen --with pytest --with pytest-timeout pytest tests/hermes_cli/test_web_server_host_header.py tests/hermes_cli/test_dashboard_admin_endpoints.py
    cd web && bun run build
    git diff --check

Observed results after resolving the latest origin/main merge and cleanup:

  • python -m py_compile hermes_cli/web_server.py tests/hermes_cli/test_web_server_host_header.py: passed
  • uv 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 existing audioop deprecation warning from discord/player.py
  • web production build passed, with the existing large chunk warning
  • git diff --check passed

Not run:

  • Full pytest tests/ -q. The focused dashboard/service/web tests above were run instead.
  • Native macOS launchd and Windows Scheduled Task execution. Those paths are covered by generation/unit tests and mirror the gateway service patterns, but were not executed on those platforms in this checkout.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Linux

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

No screenshots. This is primarily CLI/service/API wiring plus the System page controls.

@alt-glitch alt-glitch added type/feature New feature or request comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have labels Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] dashboard: add --allowed-hosts flag for reverse-proxy and Tailscale access

3 participants