How-To Guide
How to Open and Secure the Hermes Agent Dashboard
Open Hermes Web UI on port 9119, keep it running with systemd, secure remote access, understand the Bot Mode boundary, and verify channels and cron jobs end to end.
Quick answer
Run hermes doctor && hermes dashboard, then open http://127.0.0.1:9119. Use hermes dashboard for backend plus Web UI and hermes serve for a headless remote-Desktop backend. Bot Mode is a Desktop interface over isolated Hermes profiles, not a second dashboard: use Web UI to inspect the underlying profile and cron state, then use Desktop for the Bots roster, canonical Bot Chat, Routines pane, and groups. On Linux, keep the chosen process alive with a systemd user service under the same Hermes account, enable lingering for boot startup, and keep the messaging gateway separate. Prefer loopback plus SSH/VPN; a non-loopback bind requires authentication.
This guide covers the complete dashboard path: local launch, optional web/PTY dependencies, machine-level profile switching, the Desktop Bot Mode boundary, private VPS access, fail-closed authentication for public binds, browser Chat, process controls, and an end-to-end delivery test. The Dashboard makes a self-hosted runtime visible; it does not take ownership of host updates, HTTPS, backups, provider accounts, gateway recovery, or channel uptime. Use FlyHermes instead when the real requirement is managed browser/mobile access and channel uptime rather than self-hosted administration.
Managed cloud · API costs included · Skill library · Cancel anytime
Before you start:
- ☑Hermes Agent installed
- ☑hermes setup completed and hermes doctor passing
- ☑A modern web browser
- ☑Hermes v0.16 or newer if you want the latest desktop, dashboard/admin, remote backend, auth, MCP/channel, and browser Chat surface behavior
Steps
- 1
Verify Hermes before opening Web UI
Run
hermes doctorandhermes chat -q "reply ok". Fix provider, config, PATH, or dependency errors before treating the dashboard as the problem. - 2
Start the local dashboard
Run
hermes dashboardand openhttp://127.0.0.1:9119. Usehermes dashboard --port 9120if 9119 is occupied. - 3
Choose dashboard or headless serve
Run
hermes dashboardwhen you need the browser admin UI. Runhermes servewhen Hermes Desktop only needs a headless remote backend. Pick one per port. Telegram, Discord, and other channels use the separate gateway service. - 4
Keep Web UI running with systemd on Linux
Use the copy-paste user unit in the Hermes dashboard and Web UI runbook. Run it as the same account that owns
HERMES_HOMEand can rundocker ps; load%h/.hermes/.envand preserve the working PATH instead of running Hermes as root. - 5
Enable boot startup and verify the service
Run
systemctl --user daemon-reload && systemctl --user enable --now hermes-dashboard.service. If it must start before login, runsudo loginctl enable-linger "$USER". Checksystemctl --user status, the user journal, andhttp://127.0.0.1:9119/api/statusbefore testing a real channel delivery. - 6
Install optional dashboard dependencies if prompted
From a source checkout run
cd ~/.hermes/hermes-agent && uv pip install -e ".[web,pty]". The web extra provides the server; PTY support powers browser Chat. - 7
Choose the correct profile
Use the sidebar profile switcher before editing Config, API Keys, Skills, MCP, Models, or Chat. Gateway services remain profile-specific and must be checked separately.
- 8
Separate Web UI from Desktop Bot Mode
Treat each Bot as an isolated Hermes profile. Use Web UI or
hermes -p <bot> ...to verify its config, sessions, memory, tools, and cron jobs. Use the current Desktop Bots tab for the roster, canonical Bot Chat, Routines pane, groups, and cross-machine Connections. - 9
Confirm which Windows or WSL runtime owns the dashboard
Native Windows and WSL keep separate Hermes homes. If sessions, provider settings, or profiles look wrong, check which environment started port 9119 and run
hermes config pathin both before editing or copying state. - 10
Use Web UI to separate a Desktop failure from a backend failure
If Hermes Desktop will not open after an update, try the CLI smoke test and local dashboard. A working dashboard means the runtime and profile data are available; repair the native client or stale updater process without deleting memory, sessions, or skills.
- 11
Use a private path for VPS access
Keep the dashboard bound to loopback and tunnel it with
ssh -L 9119:localhost:9119 user@your-vps, or use a trusted VPN. - 12
Configure auth before any non-loopback bind
For a trusted LAN or VPN, configure the built-in username/password provider or OAuth/OIDC. For an internet-facing hostname, use Nous OAuth or a conformant OIDC provider instead of the shared-password provider. Non-loopback startup fails closed without authentication; --insecure is a deprecated no-op. Follow the server security acceptance checklist before sharing access.
- 13
Configure a Cloudflare Tunnel or reverse proxy safely
Register Nous OAuth on the host with
hermes dashboard register --redirect-uri https://dashboard.example.com/auth/callback, replacing the example hostname, or configure your OIDC provider. SetHERMES_DASHBOARD_PUBLIC_URLto the same HTTPS origin. Run the dashboard with a non-loopback bind so its auth gate engages, restrict origin access and route the proxy to port 9119. A public tunnel to an auth-free loopback origin is not secure. Verifyauth_required: trueand denial of unauthenticated management reads before signing in. - 14
Trace a stuck OAuth login without leaking credentials
Distinguish three checkpoints: the identity provider accepted the login, the browser returned to the registered /auth/callback, and the dashboard accepted its session. Compare the exact public URL and callback, then correlate a fresh login timestamp with the auth log. A direct manual visit to /auth/callback lacks the normal PKCE state and is not a valid login test. Share redacted error names and timestamps, not full authorization URLs, cookies or tokens. Follow the security troubleshooting guide if the redirect never completes.
- 15
Inspect the control plane in order
Check Status, selected profile, Sessions, Analytics, Logs, Cron Jobs, Skills, MCP, Config, Models, and Gateway state before rotating keys or rebuilding the server.
- 16
Use browser Chat inside the trusted boundary
The Chat tab runs the real Hermes TUI over an authenticated PTY/WebSocket. Resume sessions there, but keep it private like the rest of the admin surface.
- 17
Prove the actual workflow
Send one browser Chat response, Telegram/Discord message, or cron delivery to the exact destination. Record that result as success; a green dashboard is only a checkpoint.
- 18
Verify approvals in browser Chat
Open Chat and run one harmless action that requires clarification or approval. The dashboard embeds the real TUI, so slash commands, tool cards, clarify, sudo, and approval prompts should render in the browser. Keep this surface private.
- 19
Use Kanban for work state, not delivery proof
Open Kanban to inspect tasks, dependencies, assignees, profile lanes, worker runs, and dispatcher state. Then verify the final file, deployment, or channel message separately before calling the job complete.
- 20
Test every remote connection end to end
In Hermes Desktop, open Settings → Gateways, give each local, remote, SSH, or cloud source a unique name, and use Test. A current connection test checks both HTTP and WebSocket legs; the selected profile's sessions, memory, cron, and channels still live on its owning machine.
- 21
Use Dashboard to prove state survived a Desktop failure
When Desktop is blank or stuck after an update, run the CLI smoke test and open Dashboard on the same backend. If profiles and sessions appear, the durable state survived; continue with the Desktop recovery guide and repair the native client rather than deleting
~/.hermes. - 22
Recover a dashboard that will not open on localhost
Run
hermes dashboard --status. If no process exists, runhermes dashboard --no-openand keep that terminal visible. Open the exact printed address. If startup reports missing frontend assets, build~/.hermes/hermes-agent/webonce or setHERMES_WEB_DISTto the existinghermes_cli/web_dist. Only after ordinary pages load should you test PTY-backed Chat and its WebSocket authentication. - 23
Reconcile Agent and Dashboard versions
Run
hermes --versionandhermes dashboard --status. Compare the CLI version with the dashboard footer/status, then identify the executable, source checkout,HERMES_WEB_DIST, andHERMES_HOMEused by that process. Stop the stale dashboard, update or rebuild one intended installation, relaunch it, and confirm the same profile and session inventory before changing any state.
Pro Tips
- 💡Use
hermes dashboard --statusbefore starting another server andhermes dashboard --stopbefore changing bind or auth settings. - 💡Use
--skip-buildonly when the frontend is already built and npm is unavailable in the current environment. - 💡Use
--isolatedonly for a deliberate dedicated per-profile server; the normal dashboard is machine-level. - 💡A non-default port is not a security control.
- 💡Prefer SSH tunneling or VPN access to a public bind.
- 💡
--insecureno longer disables authentication and should not appear in new deployment instructions. - 💡Gateway processes remain profile-specific even when the dashboard profile switcher looks correct.
- 💡Use Logs and Sessions together to understand failed cron or channel runs.
- 💡Use Analytics before blaming model cost; it shows calls, tokens, and model usage.
- 💡Choose FlyHermes when managed browser/mobile access and uptime matter more than owning the server.
- 💡Do not create one dashboard port per profile. One machine-level dashboard on 9119 switches across co-located profiles; only separately exposed OpenAI-compatible API servers need distinct per-profile ports.
- 💡A Cloudflare Tunnel supplies HTTPS transport and routing, not Hermes authentication. Keep OAuth/OIDC enabled and verify the auth gate before sharing the hostname.
- 💡Use one process per backend port: dashboard for browser UI, serve for headless Desktop access, and gateway for messaging delivery.
- 💡If Docker works interactively but not under systemd, compare the service user, supplementary groups,
HERMES_HOME, PATH, Docker socket, andDOCKER_HOST. - 💡If a Bot is missing from Desktop, first update Hermes and Desktop, verify the correct owning backend in Settings → Connections, then compare
hermes profile listandhermes cron liston that backend. Do not recreate the profile until the backend roster is proven wrong. - 💡Sessions defaults to Chats; use Automation or All before declaring a bot, cron, tool, API, or ACP run missing.
- 💡A green
/api/statuscheck is weaker than an authenticated/api/wsChat connection and weaker still than a delivered channel or cron outcome. - 💡Use browser Chat for approvals only behind the same trusted boundary as API keys, logs, sessions, and configuration.
- 💡Dashboard Kanban shows work state; it does not prove the requested side effect or delivery occurred.
- 💡Dashboard plugins and Desktop plugins are different extension systems. Do not install a browser-dashboard bundle as a native Desktop plugin.
- 💡
127.0.0.1always means the machine running the browser. For a remote Hermes host, use an SSH tunnel or VPN and keep the dashboard bound to the remote loopback interface.
Troubleshooting
❌ Dashboard or Web UI returns 'connection refused' when opening in browser
✅ Start the dashboard with hermes dashboard and check the selected port. If you chose port 9120, open http://127.0.0.1:9120. Verify nothing else is using the port with lsof -i :9120.
❌ Web UI frontend not built and npm is not available
✅ Hermes may be running with a reduced PATH. Check which node and which npm in your shell, then build once manually: cd ~/.hermes/hermes-agent/web && npm install && npm run build. Relaunch hermes dashboard after web_dist exists.
❌ Built dashboard assets exist but Hermes still cannot find them
✅ Point Hermes directly at the built frontend: HERMES_WEB_DIST=$HOME/.hermes/hermes-agent/hermes_cli/web_dist hermes dashboard --port 9120 --no-open.
❌ Dashboard is exposed on a public VPS
✅ Restrict exposure immediately. Prefer loopback plus SSH/VPN; for required public HTTPS use Nous OAuth or OIDC and controlled origin access. Built-in username/password auth is for trusted networks or VPNs, not direct internet exposure. Test denied management access separately from the public /api/status response.
❌ Browser Chat tab is missing from WebUI
✅ Confirm that the dashboard web and PTY dependencies are installed, then restart hermes dashboard. The Chat tab is a local PTY-backed TUI surface; on native Windows use WSL2 for the PTY requirement.
❌ Dashboard command works but browser cannot reach it
✅ Confirm the actual port, host binding, firewall, SSH tunnel, and whether you ran with --no-open on a server. For local use, start with the default localhost:9119 before exposing anything.
❌ Dashboard loads but Telegram or Discord is still silent
✅ Use Web UI as a checkpoint only. Then run hermes gateway status, inspect agent/errors logs, verify the active profile and allowed chat/thread IDs, and send one real message in the exact target channel.
❌ Dashboard launches but the team still cannot use Hermes remotely
✅ The self-hosted dashboard is an admin panel for your runtime; it does not magically provide managed uptime, secure public access, or channel delivery. Use FlyHermes when the requirement is hosted browser/mobile access and connected channels.
❌ Dashboard says a gateway is connected but Telegram or Discord does not reply
✅ Use the dashboard/logs to inspect state, then run an end-to-end send/reply test in the exact chat/topic. Process health and channel delivery are separate checks.
❌ Dashboard edits the wrong profile
✅ Check the profile switcher and URL ?profile=<name> before changing Config, API Keys, Skills, MCP, or Models. For scripts and services, use explicit hermes -p <name> ... commands.
❌ Dashboard profile switcher looks right but gateway state still differs
✅ Gateway processes remain profile-specific services. Run hermes -p <name> gateway status for the profile that owns the bot/channel and then send a real test message.
❌ `--insecure` no longer opens the dashboard
✅ --insecure is deprecated and a no-op. Configure Basic Auth, Nous OAuth, or OIDC for a non-loopback bind, or keep the server on 127.0.0.1 and use a tunnel.
❌ Cloudflare Tunnel opens the wrong Hermes port or OAuth keeps redirecting
✅ Route the public hostname to dashboard port 9119, not API port 8642. Set HERMES_DASHBOARD_PUBLIC_URL to the exact HTTPS hostname, confirm the dashboard runs with a non-loopback bind and an OAuth/OIDC provider, then inspect /api/status for auth_required: true and the expected provider.
❌ Dashboard works in a shell but fails under systemd or loses Docker access
✅ Run the user unit as the same Hermes account, verify docker ps first, load %h/.hermes/.env, preserve PATH, and compare the Docker socket or DOCKER_HOST. Enable lingering only after the service works; do not switch to root as a shortcut.
❌ WSL dashboard opens but shows the wrong profile or different sessions
✅ Native Windows and WSL are separate Hermes installations. Identify which process owns port 9119, compare hermes config path in each environment, stop the unintended dashboard, and relaunch from the runtime whose profile you want to manage.
❌ Hermes Desktop stopped opening after an update but Web UI still works
✅ Treat this as a client/update problem, not lost agent state. Back up the profile, stop stale Desktop or gateway child processes, verify CLI and Web UI, then rerun the supported update or rebuild path. Do not delete sessions, memory, or skills.
❌ Remote backend test passes but Desktop Chat disconnects
✅ The status probe can pass while authentication or the WebSocket fails. Confirm the exact port 9119 URL, sign in again, compare the selected profile in Web UI, and verify that Desktop is not pointed at the separate port 8642 API server.
❌ Bots tab is blank, a remote Bot is missing, or a Bot routine cannot be opened
✅ Update Hermes and Desktop first because recent Bot roster, cron-row, panel, and browser-link fixes shipped in the current release wave. Then verify the owning backend under Settings → Connections, run hermes profile list, inspect routines with hermes cron list, and confirm that the Bot profile still exists before recreating it.
❌ A bot, cron, tool, API, or ACP session is missing
✅ Select the owning profile, open Sessions, and change the default Chats filter to Automation or All. Then filter by exact source or search one known phrase before repairing the session store.
❌ Status shows low memory, low disk, or a suspected OOM restart
✅ Treat this as host-pressure evidence. Free resources, inspect gateway and lifecycle logs from the same time window, and rerun one bounded workflow before changing models or reinstalling Hermes.
❌ Remote `/api/status` works but `/api/ws` Chat fails
✅ Verify a non-loopback bind, active Basic Auth/OAuth/OIDC provider, exact Remote URL, and a fresh Desktop sign-in. Close code 4401 means ticket authentication failed; 4403 usually means Host or peer rejection.
❌ The dashboard process is running, but localhost:9119 still opens the wrong machine
✅ Confirm where Hermes is running. If it is on a VPS, WSL, Docker, or another computer, your browser's 127.0.0.1 is not that host. Use the documented port mapping or ssh -L 9119:localhost:9119 user@host, then open local port 9119.
❌ Agent and Dashboard show different versions or capabilities
✅ A long-running backend or cached frontend bundle is probably stale. Compare versions and paths, stop the old dashboard, rebuild or update the intended installation, and relaunch against the same HERMES_HOME. Preserve profiles, sessions, memory, skills, and cron jobs.
FAQ
What command opens the Hermes dashboard?
Run hermes dashboard. It opens on http://127.0.0.1:9119 by default.
How do I use a different dashboard port?
Run hermes dashboard --port 9120 or another free port. Use --no-open on a headless server.
Can one dashboard manage multiple profiles?
Yes. Use the profile switcher for Config, API Keys, Skills, MCP, Models, and Chat. Gateways remain separately managed per profile.
Does `--insecure` bypass authentication?
No. It is deprecated and a no-op. Every non-loopback bind requires a configured password or OAuth provider.
How should I access Web UI on a VPS?
Prefer a loopback bind with an SSH tunnel or VPN. If a public bind is required, add an auth provider, HTTPS, and firewall restrictions.
How do I configure Nous OAuth for the dashboard?
Run hermes dashboard register, then use the saved OAuth client configuration with the dashboard login gate.
What does the browser Chat tab run?
It runs the real Hermes TUI behind an authenticated PTY/WebSocket. The web and PTY extras are required; native Windows users should use WSL2 for Chat.
How do I stop a running dashboard?
Use hermes dashboard --status to list dashboard processes and hermes dashboard --stop to stop them.
Why can Telegram or Discord fail while Web UI looks healthy?
Channel delivery also depends on the correct profile, gateway service, platform permissions, allowlists, routing, and provider credits. Test the exact destination.
When should I use FlyHermes instead?
Use FlyHermes when you want managed browser/mobile access, connected channels, and uptime without maintaining dashboard authentication, VPS processes, providers, and gateways.
Does each Hermes profile need its own dashboard port?
No. The normal machine-level dashboard serves co-located profiles through its profile switcher. Per-profile API servers are separate and need distinct ports only when you expose them to OpenAI-compatible clients.
Can I use Cloudflare Tunnel for Hermes Web UI?
Yes. Route the tunnel to port 9119, use Nous OAuth or OIDC for an internet-facing hostname, set HERMES_DASHBOARD_PUBLIC_URL to the exact HTTPS URL, and verify the dashboard auth gate is active. The tunnel does not replace authentication.
Should I run both hermes serve and hermes dashboard?
Usually no. The dashboard runs the backend plus browser UI; serve runs the headless backend for remote clients. Pick one per port. Run the messaging gateway separately if Telegram, Discord, or other channels must stay connected.
Does Hermes Web UI include Bot Mode?
The underlying Bot is a Hermes profile, so Web UI can inspect its config, sessions, tools, memory, and cron state. The dedicated Bots roster, canonical Bot Chats, Routines pane, groups, and cross-machine connection UI are current Hermes Desktop surfaces.
Where are bot and cron sessions in Hermes Web UI?
Open Sessions and switch the default Chats filter to Automation or All. Select the profile that owns the bot, then narrow by source or search the message text.
Why does remote status work while dashboard Chat fails?
Status is a public readiness probe. Chat separately needs dashboard authentication and an accepted WebSocket; inspect 4401 authentication failures and 4403 Host/peer rejections.
Why can Portal login succeed while dashboard login fails?
Identity-provider sign-in, callback completion and the dashboard session are different checkpoints. Verify the registered HTTPS callback and public URL, then inspect a fresh normal login. Do not test by manually replaying authorization codes or removing authentication.
Related setup and cost guides
Hermes WebUI / dashboard overview
Copy-paste Linux systemd unit, command map, dashboard boundary, and mission-control checklist.
FlyHermes pricing for managed dashboards
Compare managed FlyHermes with the server, provider, gateway, and incident-response work of self-hosting.
VPS deployment trade-offs
Deploy an always-on runtime and verify services after reboot.
secure your Hermes server
Protect dashboard auth, SSH, secrets, network access, and dangerous tools.
Telegram agent setup
Connect a Telegram bot and prove one real reply after the gateway starts.