章節:Core Features · 網址:https://hermesbible.com/docs/user-guide/features/web-dashboard
Web Dashboard 是一個基於瀏覽器的 UI,用於管理你的 Hermes Agent 安裝。你可以透過簡潔的 Web 介面配置設定、管理 API 金鑰和監控 Session,而不需要編輯 YAML 檔案或執行 CLI 指令。
TIP
Hosted 模式認證使用 Nous Portal OAuth;如果你也希望 Dashboard 連接到真正的後端,
hermes setup --portal可以同時設定模型和工具閘道。請參閱 Nous Portal。
快速開始
hermes dashboard
這會啟動一個本地 Web 伺服器,並在瀏覽器中開啟 http://127.0.0.1:9119。Dashboard 完全在你的機器上運行 — 不會有任何資料離開 localhost。
選項
| Flag | 預設值 | 說明 |
|---|---|---|
--port | 9119 | Web 伺服器運行的連接埠 |
--host | 127.0.0.1 | 綁定位址 |
--no-open | — | 不自動開啟瀏覽器 |
--insecure | off | 允許綁定到非 localhost 的主機(危險 — 會在網路中暴露 API 金鑰;請搭配防火牆和強認證使用) |
--isolated | off | 從具名 Profile 啟動時(worker dashboard),運行專屬的 Profile 伺服器,而不是路由到機器級 Dashboard |
# 自訂連接埠
hermes dashboard --port 8080
# 綁定到所有介面(在共享網路上請謹慎使用)
hermes dashboard --host 0.0.0.0
# 啟動但不開啟瀏覽器
hermes dashboard --no-open
管理多個 Profile
Dashboard 是一個機器級的管理介面:一個伺服器管理該機器上的所有 Profile。側邊欄中的 Profile 切換器(當存在多個 Profile 時可見)決定管理頁面讀寫哪個 Profile — Config、API Keys、Skills、MCP、Models 和 Chat 分頁都遵循此切換。當選取非 Dashboard 所屬的 Profile 時,琥珀色橫幅會顯示正在管理的 Profile 名稱,確保寫入目標永遠不會含糊。
選擇狀態記錄在 URL 中(?profile=<name>),所以像 http://127.0.0.1:9119/skills?profile=worker 這樣的深層連結會帶著預選的切換狀態,並在重新整理後保留。
從 Profile 別名啟動 Dashboard 會路由到機器級 Dashboard,而不是啟動第二個伺服器:
worker dashboard
# → 已經在執行:在 ?profile=worker 開啟瀏覽器
# → 尚未執行: 啟動機器級 Dashboard 並預選 "worker"
加上 --isolated 可以選擇退出,運行一個限定於該 Profile 的專屬伺服器(統一前的預設行為 — 適用於你想以不同認證方式暴露不同 Profile Dashboard 的情況)。
Chat 分頁也遵循切換器:有範圍限定的聊天會以選取 Profile 的 HERMES_HOME 啟動其 PTY 子程序,因此對話會使用該 Profile 的模型、技能、記憶和 Session 歷史。切換 Profile 會啟動全新的終端 Session。
以下功能維持 Profile 級別,不被切換器吸收:閘道程式(透過 hermes -p <name> gateway … 管理)、每個 Profile 的 Session 資料庫,以及 Cron 排程器(Cron 頁面已透過自己的篩選器跨 Profile 聚合)。
前置需求
預設的 hermes-agent 安裝不包含 HTTP 堆疊或 PTY 輔助工具 — 這些是可選的額外套件。Web Dashboard 需要 FastAPI 和 Uvicorn(web 額外套件)。Chat 分頁還需要 ptyprocess 來在偽終端後方啟動內建 TUI(POSIX 上的 pty 額外套件)。一次安裝兩者:
pip install 'hermes-agent[web,pty]'
web 額外套件會安裝 FastAPI/Uvicorn;pty 會安裝 ptyprocess(POSIX)或 pywinpty(原生 Windows — 注意內建 TUI 本身仍需要 WSL)。pip install hermes-agent[all] 包含兩者,如果你也需要訊息/語音等功能,這是最簡單的方式。
當你執行 hermes dashboard 但缺少依賴時,它會告訴你需要安裝什麼。如果前端尚未建置且 npm 可用,首次啟動時會自動建置。
Chat 分頁是每次 hermes dashboard 啟動的一部分 — 內建的瀏覽器聊天面板(透過 PTY/WebSocket 運行 TUI)始終可用,無需額外 flag。
頁面
Status
首頁顯示安裝的即時概覽:
- Agent 版本和發布日期
- 閘道狀態 — 運行中/已停止、PID、已連線的平台及其狀態
- 活躍 Session — 過去 5 分鐘內活躍的 Session 數量
- 近期 Session — 最近 20 個 Session 的列表,包含模型、訊息數、Token 使用量和對話預覽
Status 頁面每 5 秒自動重新整理。
Chat
Chat 分頁將完整的 Hermes TUI(與 hermes --tui 相同的介面)直接嵌入瀏覽器。你在終端 TUI 中能做的一切 — 斜線指令、模型選擇器、工具呼叫卡片、Markdown 串流顯示、clarify/sudo/approval 提示、主題佈景 — 在這裡完全相同地運作,因為 Dashboard 執行的是真正的 TUI 二進位檔,並透過 xterm.js 的 WebGL 渲染器將 ANSI 輸出呈現為像素完美的格點佈局。
運作方式:
/api/pty開啟一個使用 Dashboard Session Token 認證的 WebSocket- 伺服器在 POSIX 偽終端後方啟動
hermes --tui - 按鍵輸入傳送到 PTY;ANSI 輸出串流回瀏覽器
- xterm.js 的 WebGL 渲染器將每個儲存格繪製到整數像素網格上;滑鼠追蹤(SGR 1006)、全形字元(Unicode 11)和方框繪圖字形全部原生渲染
- 調整瀏覽器視窗大小會透過
@xterm/addon-fit附加元件調整 TUI 大小
恢復既有 Session: 從 Sessions 分頁,點擊任何 Session 旁的播放圖示(▶)。這會跳轉到 /chat?resume=<id> 並以 --resume 啟動 TUI,載入完整歷史記錄。
前置需求:
- Node.js(與
hermes --tui相同的需求;TUI 繫束在首次啟動時建置) ptyprocess— 由pty額外套件安裝(pip install 'hermes-agent[web,pty]',或[all]包含兩者)- POSIX 核心(Linux、macOS 或 WSL2)。
/chat終端面板特別需要 POSIX PTY — 原生 Windows Python 沒有等效功能,所以在原生 Windows 安裝中,Dashboard 的其他功能(Sessions、jobs、metrics、config 編輯器)都能運作,但/chat分頁會顯示橫幅告知你需要使用 WSL2。
關閉瀏覽器分頁後,PTY 會在伺服器上被正常回收。重新開啟時會啟動全新的 Session。
要將 Hermes Desktop 指向在另一台機器上運行的 Dashboard 而非其內建後端,請參閱下方的遠端後端段落。
將 Hermes Desktop 連接到遠端後端
Hermes Desktop 通常會啟動自己的本地後端,但它也可以透過 Settings → Gateway → Remote gateway 連接到在遠端機器(VM、家庭伺服器等)上運行的 Dashboard。這是最常見的「Desktop 說後端已就緒但聊天永遠無法運作」報告的來源,因為 Desktop 的就緒檢查驗證的內容比實際即時聊天連接所需的還少。
INFO — 前置需求:遠端主機上必須有一個正在運行的
hermes dashboardDesktop 連接的「遠端後端」就是在遠端機器上運行的
hermes dashboard程序 — 與本頁面文件記載的是同一個伺服器。它必須先啟動並可達,下方的步驟才有效;Desktop 是連接到它,而不是為你啟動它。讓它在systemd/tmux/等等下運行,以便在登出和重啟後存活。閘道(Telegram/Discord/Slack/等等)是一個獨立的長期運行程序 — 如果你依賴訊息通道,請獨立啟動它;它不是桌面應用連接的對象。
Desktop 的「遠端後端已就緒」探測只會呼叫 GET /api/status,這是一個公開端點 — 只要任何 Dashboard 在主機上運行,它就會回應。即時聊天連接是到 /api/ws(和 /api/pty)的獨立 WebSocket,而該 Socket 受狀態探測從未觸及的兩個額外檢查控制:
- 你必須已認證。 當 Dashboard 綁定到非迴環位址時,會啟用其認證閘道。用使用者名稱和密碼保護它(使用內建的 username/password provider);Desktop 登入一次後,透過一次性票券重用該 Session 進行 WebSocket 連接。如果沒有設定 Provider,非迴環的 Dashboard 會啟動時失敗關閉。
- 綁定主機必須允許客戶端且與 Host 標頭匹配。 迴環綁定(
127.0.0.1)只接受迴環客戶端,所以遠端機器會在 Socket 層被拒絕,無論憑證如何。請綁定到非迴環位址(--host 0.0.0.0),讓對端 IP 防護允許遠端客戶端通過。你在 Desktop 輸入的遠端 URL 必須透過與綁定相同的主機到達 Dashboard — DNS 重新綁定防護要求 Host 標頭匹配。
遠端 Dashboard 設定
設定使用者名稱和密碼,然後在可達的位址上啟動 Dashboard。使用 systemd 服務:
[Service]
EnvironmentFile=%h/.hermes/.env
ExecStart=/path/to/venv/bin/python -m hermes_cli.main dashboard \
--host 0.0.0.0 --port 9119 --no-open
~/.hermes/.env 內容為:
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=choose-a-strong-password
HERMES_DASHBOARD_BASIC_AUTH_SECRET=<32+ random bytes; openssl rand -base64 32>
然後在 Desktop 中輸入 Remote URL(例如 http://VM_IP:9119)並使用該使用者名稱和密碼登入。完整的設定選項請參閱 username/password provider 段落。
TIP — 重試 Desktop 前先驗證閘道已啟用
從任何機器檢查 Dashboard 是否宣傳 username/password provider:
curl -s http://VM_IP:9119/api/status | jq '.auth_required, .auth_providers' # true # ["basic"]
auth_required: true且 providers 列表中有"basic"→ Desktop 的登入流程將正常運作。auth_required: false→ 綁定是迴環的,或閘道未啟用。請綁定到非迴環位址。auth_required: true但沒有"basic"provider → username/password 環境變數未載入。請先修正這些設定。
如果 /api/status 顯示閘道已啟用且有 "basic" provider,但 Desktop 仍然在登入後無法連接,問題已超出基本設定範圍 — 請取得最新的 desktop.log(Settings → Gateway → Open logs)以及同一重試時間段內的 Dashboard 日誌,查找 /api/ws 的關閉代碼(4403 = 聊天 WS 被請求防護拒絕,例如 Host/對端不匹配;4401 = WS 票券未通過認證)。
Config
一個表單式的 config.yaml 編輯器。所有 150+ 個配置欄位都從 DEFAULT_CONFIG 自動發現,並組織成分頁類別:

- model — 預設模型、供應商、基礎 URL、推理設定
- terminal — 後端(local/docker/ssh/modal)、逾時、shell 偏好
- display — 佈景、工具進度、resume 顯示、spinner 設定
- agent — 最大迭代次數、閘道逾時、服務層級
- delegation — 子代理限制、推理努力程度
- memory — Provider 選擇、上下文注入設定
- approvals — 危險指令審批模式(ask/yolo/deny)
- 以及更多 — config.yaml 的每個段落都有對應的表單欄位
具有已知有效值的欄位(terminal backend、skin、approval mode 等)渲染為下拉選單。布林值渲染為切換開關。其他所有欄位都是文字輸入。
操作:
- Save — 立即將變更寫入
config.yaml - Reset to defaults — 將所有欄位還原為預設值(在你點擊 Save 之前不會儲存)
- Export — 以 JSON 下載目前的設定
- Import — 上傳 JSON 設定檔以替換目前的值
TIP
設定變更會在下一個 Agent Session 或閘道重啟時生效。Web Dashboard 編輯的與
hermes config set和閘道讀取的是同一個config.yaml檔案。
API Keys
管理儲存 API 金鑰和憑證的 .env 檔案。金鑰按類別分組:
- LLM Providers — OpenRouter、Anthropic、OpenAI、DeepSeek 等
- Tool API Keys — Browserbase、Firecrawl、Tavily、ElevenLabs 等
- Messaging Platforms — Telegram、Discord、Slack bot tokens 等
- Agent Settings — 非機密的環境變數,如
API_SERVER_ENABLED
每個金鑰顯示:
- 是否目前已設定(附帶遮蔽的值預覽)
- 該金鑰的用途說明
- 供應商註冊/金鑰頁面的連結
- 用於設定或更新值的輸入欄位
- 用於移除金鑰的刪除按鈕
進階/少用的金鑰預設隱藏在切換開關後方。
Sessions
瀏覽和檢查所有 Agent Session。每一列顯示 Session 標題、來源平台圖示(CLI、Telegram、Discord、Slack、cron)、模型名稱、訊息數、工具呼叫數,以及距上次活躍的時間。活躍 Session 以脈動徽章標示。
- Search — 使用 FTS5 跨所有訊息內容進行全文搜尋。結果顯示帶有突顯的摘要片段,展開時自動捲動到第一個匹配的訊息。
- Stats — 摘要列顯示總 Session 數、資料庫中活躍的數量、已封存數量、總訊息數,以及按來源的分布。
- Expand — 點擊 Session 以載入其完整訊息歷史。訊息按角色著色(user、assistant、system、tool),並以帶有語法突顯的 Markdown 呈現。
- Tool calls — 帶有工具呼叫的 assistant 訊息顯示可收合的區塊,包含函數名稱和 JSON 參數。
- Rename — 行內設定或清除 Session 標題(鉛筆圖示)。
- Export — 以 JSON 下載 Session(中繼資料 + 完整訊息歷史)(下載圖示)。
- Prune — 頁首的「Prune old sessions」按鈕刪除超過 N 天的已結束 Session。
- Delete — 使用垃圾桶圖示移除 Session 及其訊息歷史。

Logs
查看 Agent、閘道和錯誤日誌檔案,支援篩選和即時追蹤。
- File — 在
agent、errors和gateway日誌檔案間切換 - Level — 按日誌級別篩選:ALL、DEBUG、INFO、WARNING 或 ERROR
- Component — 按來源元件篩選:all、gateway、agent、tools、cli 或 cron
- Lines — 選擇顯示的行數(50、100、200 或 500)
- Auto-refresh — 切換每 5 秒輪詢新日誌行的即時追蹤
- Color-coded — 日誌行按嚴重程度著色(紅色為錯誤、黃色為警告、暗色為除錯)
Analytics
從 Session 歷史計算的使用量和成本分析。選擇時間範圍(7、30 或 90 天)查看:
- 摘要卡片 — 總 Token 數(輸入/輸出)、快取命中百分比、估計或實際總成本,以及總 Session 數和每日平均
- 每日 Token 圖表 — 堆疊長條圖顯示每日輸入和輸出 Token 使用量,懸停時顯示明細和成本
- 每日明細表 — 每日的日期、Session 數、輸入 Token、輸出 Token、快取命中率和成本
- 各模型明細 — 顯示每個使用過的模型、其 Session 數、Token 使用量和估計成本的表格
Cron
建立和管理排程的 Cron 作業,按重複排程執行 Agent 提示。
- Create — 填入名稱(可選)、提示、cron 表達式(例如
0 9 * * *),以及遞送目標(local、Telegram、Discord、Slack 或 email) - Job list — 每個作業顯示其名稱、提示預覽、排程表達式、狀態徽章(enabled/paused/error)、遞送目標、上次執行時間和下次執行時間
- Pause / Resume — 在活躍和暫停狀態間切換作業
- Edit — 開啟預填的對話框以變更作業的提示、排程、名稱或遞送目標
- Trigger now — 在正常排程之外立即執行作業
- Delete — 永久移除 Cron 作業
Profiles
建立和管理 Profiles — 擁有獨立設定、技能和 Session 的隔離 Hermes 實例。
- Profile cards — 每個卡片顯示其模型/供應商、技能數、閘道狀態、描述和徽章(active、default、alias)
- Create — 名稱 + 可選的 clone-from-default / clone-everything / no-bundled-skills、描述和模型;專屬的 Profile Builder 頁面(
/profiles/new)提供完整流程(模型、MCP、技能) - Manage skills & tools — 跳轉到限定於該 Profile 的 Skills 頁面(設定側邊欄的 Profile 切換器)
- Set as active — 翻轉固定的預設值,讓未來的 CLI/閘道執行使用(與
hermes profile use相同)。這不改變 Dashboard 管理的對象 — 那是 Profile 切換器的工作 - Edit model / description / SOUL — 行內編輯器寫入該 Profile
- Rename / Delete — 僅限具名 Profile
Skills
瀏覽、搜尋和切換已安裝的技能與工具組,並從 Hub 安裝新的技能。技能從 ~/.hermes/skills/ 載入並按類別分組。
- Search — 按名稱、描述或類別篩選已安裝的技能和工具組
- Category filter — 點擊類別藥丸縮小清單範圍(例如 MLOps、MCP、Red Teaming、AI)
- Toggle — 用開關啟用或停用個別技能。變更在下一個 Session 生效。
- Toolsets — 獨立視圖顯示內建工具組(檔案操作、網頁瀏覽等),包含其啟用/未啟用狀態、設定需求和包含的工具清單
- Browse hub — 第三個視圖搜尋跨所有來源的技能 Hub(與
hermes skills search相同),透過標識符安裝任何結果並附有即時安裝日誌,並提供「Update all」按鈕來重新整理已安裝的技能。

MCP
無需 CLI 即可管理 MCP 伺服器。與 hermes mcp 讀取的 config.yaml 中相同的 mcp_servers 區塊。
你的 MCP 伺服器:
- Add — 註冊 HTTP/SSE 伺服器(URL)或 stdio 伺服器(指令 + 參數),stdio 伺服器可選擇附加
KEY=VALUE環境變數 - Enable / disable — 在不刪除的情況下切換伺服器的開啟或關閉。已停用的伺服器保留在設定中,以便稍後重新啟用。在下一次閘道重啟時生效。
- Test — 連接到伺服器、列出其工具並斷開連接 — 在 Agent 依賴它之前驗證連接
- Remove — 從設定中刪除伺服器
- 機密形態的環境變數值在清單視圖中被遮蔽
Catalog: 瀏覽 Nous 核准的 MCP 伺服器(內建的 optional-mcps/ 目錄),並一鍵安裝任何一個。需要 API 金鑰的項目會行內提示輸入;值會寫入 .env。這與 hermes mcp catalog / hermes mcp install 使用的是同一個目錄。

Webhooks
管理動態的 Webhook 訂閱。Webhook 平台必須先在訊息設定中啟用;頁面在未啟用時會顯示提示。
- Create — 名稱、描述、事件篩選器、遞送目標、可選的直接遞送模式,以及 Agent 提示。建立時頁面顯示路由 URL 和一次性 HMAC 密鑰以供複製。
- Enable / disable — 切換訂閱的開啟或關閉。已停用的路由保留在訂閱檔案中,但閘道會拒絕其傳入事件(403)。閘道會熱重新載入檔案,因此變更在下一個事件時生效 — 無需重啟。
- List — 每個訂閱顯示其 URL、事件和遞送目標
- Delete — 移除訂閱

Pairing
無需 CLI 即可核准和撤銷訊息使用者 — 這是遠端管理員將 Telegram/Discord/等等使用者加入配對閘道的方式。與 hermes pairing 完全對等。
- Pending requests — 每個顯示平台、碼、使用者和時間,附帶 Approve 按鈕
- Approved users — 每個顯示平台和使用者,附帶 Revoke 按鈕
- Clear pending — 丢棄所有未完成的配對碼

Channels
從瀏覽器將 Hermes 連接到任何訊息平台 — 與 hermes setup gateway 完全對等。頁面列出每個支援的通道(Telegram、Discord、Slack、Matrix、Mattermost、WhatsApp、Signal、BlueBubbles/iMessage、Email、SMS/Twilio、DingTalk、Feishu/Lark、WeCom、WeChat、QQ Bot、Yuanbao,加上 API server 和 webhook 端點)及其即時連接狀態。
- Configure — 開啟每個平台的表單,包含該通道所需的確切欄位(bot token、app token、server URL、allowlist 等)。機密欄位以密碼輸入呈現並以遮蔽方式儲存;留空欄位保持現有值。必要欄位有標記並會驗證。「Setup guide」連結指向該平台的憑證文件。
- Enable / disable — 切換通道的開啟或關閉。憑證保留在磁碟上;只有活躍狀態會改變。
- Test — 檢查通道是否已設定、已啟用,並回報來自閘道的即時連接。
- Restart gateway — 憑證寫入
~/.hermes/.env,啟用標誌寫入config.yaml;閘道在下一次重啟時連接每個已啟用的通道,你可以直接從頁面觸發重啟。

System
一個整合的管理面板,用於安裝範圍的操作:
- Host — 即時系統統計:OS / 核心、架構、主機名稱、Python 和 Hermes 版本、CPU 核心數 + 利用率、記憶體、Hermes 主目錄的磁碟使用量、運行時間和負載平均。(CPU/記憶體/磁碟在安裝
psutil時提供;身分欄位始終顯示。)Hermes 版本顯示更新狀態徽章(最新 / 落後 N 個 commit)和Check for updates按鈕。當 git 或 pip 安裝有可用更新時,Update now按鈕會開啟確認對話框 — 顯示你將拉取多少 commit — 然後在背景執行hermes update。在 Docker/Nix/Homebrew 安裝中,Dashboard 無法就地套用更新,因此會顯示正確的帶外指令。 - Nous Portal — 登入狀態、活躍的推理供應商,以及 Tool Gateway 路由表(哪些工具透過 Portal 運行 vs. 本地運行),附帶管理訂閱的連結。
hermes portal的唯讀鏡像。 - Skill curator — 背景技能維護狀態(active / paused、間隔、上次執行),附帶 pause/resume 和 run-now 按鈕。鏡像
hermes curator。 - Gateway — 啟動、停止和重啟訊息閘道,附帶即時狀態(running/stopped、PID、state)
- Memory — 選擇外部記憶 Provider(或僅內建),以及重設內建的
MEMORY.md/USER.md儲存 - Credential pool — 新增和移除 Agent 輪替使用的旋轉 API 金鑰(按 Provider)。金鑰在清單中被遮蔽;原始值只會傳遞給 Agent。
- Operations — 執行
doctor、安全審計、建立備份、從備份封存還原、更新技能、顯示 system-prompt 大小分析、產生支援資訊包,或為已棄用的設定遷移配置。每個操作會啟動一個背景動作,其即時日誌串流到頁面。 - Checkpoints — 查看
/rollbackshadow store 大小並修剪它 - Shell hooks — 列出已設定的 hook 及其同意 + 可執行狀態、建立 hook(事件、指令、匹配器、逾時,附帶選擇性的同意授權),以及移除 hook。Hook 會執行任意指令,因此建立表單附帶安全警告,且 hook 只在同意授權後才會觸發。



建立 Shell hook(注意同意勾選框和執行任意指令的警告):

WARNING — 安全
Web Dashboard 讀寫你的
.env檔案,其中包含 API 金鑰和機密。它預設綁定到127.0.0.1— 只能從本機存取。如果你綁定到0.0.0.0,網路上的任何人都可以查看和修改你的憑證。Dashboard 本身沒有認證機制。
/reload 斜線指令
Dashboard PR 也為互動式 CLI 新增了 /reload 斜線指令。透過 Web Dashboard 變更 API 金鑰(或直接編輯 .env)後,在活躍的 CLI Session 中使用 /reload 即可套用變更而無需重啟:
You → /reload
Reloaded .env (3 var(s) updated)
這會將 ~/.hermes/.env 重新讀取到執行中程序的環境中。當你透過 Dashboard 新增了新的供應商金鑰並想立即使用時非常有用。
REST API
Web Dashboard 暴露一個前端使用的 REST API。你也可以直接呼叫這些端點進行自動化:
TIP — Profile 範圍限定的端點
管理端點系列 —
/api/config、/api/env、/api/skills、/api/tools/toolsets、/api/mcp和/api/model/{info,options,auxiliary,set}— 接受一個可選的?profile=<name>查詢參數(或寫入時 JSON body 中的"profile"),將讀寫限定到該 Profile 的HERMES_HOME。省略 = Dashboard 自己的 Profile。未知的 Profile 名稱回傳404。/api/ptyWebSocket 接受相同的參數以在選定的 Profile 下啟動聊天。
GET /api/status
回傳 Agent 版本、閘道狀態、平台狀態和活躍 Session 數量。
GET /api/sessions
回傳最近 20 個 Session 的中繼資料(模型、Token 計數、時間戳、預覽)。
GET /api/config
以 JSON 回傳目前的 config.yaml 內容。
GET /api/config/defaults
回傳預設配置值。
GET /api/config/schema
回傳描述每個配置欄位的 schema — 類型、描述、類別,以及適用時的 select 選項。前端使用此資訊為每個欄位渲染正確的輸入元件。
PUT /api/config
儲存新配置。Body:{"config": {...}}。
GET /api/env
回傳所有已知的環境變數及其 set/unset 狀態、遮蔽的值、描述和類別。
PUT /api/env
設定環境變數。Body:{"key": "VAR_NAME", "value": "secret"}。
DELETE /api/env
移除環境變數。Body:{"key": "VAR_NAME"}。
GET /api/sessions/{session_id}
回傳單個 Session 的中繼資料。
GET /api/sessions/{session_id}/messages
回傳 Session 的完整訊息歷史,包含工具呼叫和時間戳。
GET /api/sessions/search
跨訊息內容的全文搜尋。查詢參數:q。回傳匹配的 Session ID 及帶有突顯的摘要片段。
DELETE /api/sessions/{session_id}
刪除 Session 及其訊息歷史。
GET /api/logs
回傳日誌行。查詢參數:file(agent/errors/gateway)、lines(數量)、level、component。
GET /api/analytics/usage
回傳 Token 使用量、成本和 Session 分析。查詢參數:days(預設 30)。回應包含每日明細和各模型聚合。
GET /api/cron/jobs
回傳所有已設定的 Cron 作業及其狀態、排程和執行歷史。
POST /api/cron/jobs
建立新的 Cron 作業。Body:{"prompt": "...", "schedule": "0 9 * * *", "name": "...", "deliver": "local"}。
POST /api/cron/jobs/{job_id}/pause
暫停 Cron 作業。
POST /api/cron/jobs/{job_id}/resume
恢復已暫停的 Cron 作業。
POST /api/cron/jobs/{job_id}/trigger
在排程之外立即觸發 Cron 作業。
DELETE /api/cron/jobs/{job_id}
刪除 Cron 作業。
GET /api/skills
回傳所有技能及其名稱、描述、類別和啟用狀態。
PUT /api/skills/toggle
啟用或停用技能。Body:{"name": "skill-name", "enabled": true}。
GET /api/tools/toolsets
回傳所有工具組及其標籤、描述、工具清單和活躍/已設定狀態。
Admin 端點
這些端點驅動 MCP、Channels、Webhooks、Pairing 和 System 頁面。全部位於與 /api/ 其餘部分相同的認證閘道後方。
| 方法與路徑 | 用途 |
|---|---|
GET /api/mcp/servers | 列出已設定的 MCP 伺服器(環境變數值被遮蔽) |
POST /api/mcp/servers | 新增伺服器。Body:{name, url?, command?, args?, env?, auth?} |
POST /api/mcp/servers/{name}/test | 連接、列出工具、斷開連接 |
PUT /api/mcp/servers/{name}/enabled | 啟用/停用伺服器 |
DELETE /api/mcp/servers/{name} | 移除伺服器 |
GET /api/mcp/catalog | 瀏覽 Nous 核准的 MCP 目錄 |
POST /api/mcp/catalog/install | 安裝目錄項目(附帶必要環境變數) |
GET /api/messaging/platforms | 列出每個訊息通道及其狀態 + 平台專屬設定欄位 |
PUT /api/messaging/platforms/{id} | 設定通道。Body:{enabled?, env?, clear_env?}(env 寫入 .env,enabled 寫入 config.yaml) |
POST /api/messaging/platforms/{id}/test | 回報通道是否已設定、已啟用且已連接 |
GET /api/pairing | 列出待處理和已核准的訊息使用者 |
POST /api/pairing/approve | 核准碼。Body:{platform, code} |
POST /api/pairing/revoke | 撤銷使用者。Body:{platform, user_id} |
POST /api/pairing/clear-pending | 丢棄所有待處理的碼 |
GET /api/webhooks | 列出訂閱 + 平台啟用狀態 |
POST /api/webhooks | 建立訂閱(回傳一次性密鑰) |
DELETE /api/webhooks/{name} | 移除訂閱 |
GET /api/credentials/pool | 列出集中的輪替金鑰(已遮蔽) |
POST /api/credentials/pool | 新增金鑰。Body:{provider, api_key, label?} |
DELETE /api/credentials/pool/{provider}/{index} | 移除金鑰(1 起始索引) |
GET /api/memory | 活躍 Provider + 可用 Providers + 內建檔案大小 |
PUT /api/memory/provider | 選擇 Provider(空值 = 僅內建) |
POST /api/memory/reset | 重設內建記憶。Body:{target: all|memory|user} |
POST /api/gateway/start · /stop · /restart | 閘道生命週期(背景執行) |
POST /api/ops/doctor · /security-audit · /backup · /import | 診斷與維護(背景執行;透過 /api/actions/{name}/status 追蹤) |
GET /api/ops/hooks | 已設定的 Shell hooks + allowlist 狀態 |
GET /api/ops/checkpoints · POST .../prune | 檢查/修剪 /rollback 儲存 |
POST /api/ops/hooks · DELETE /api/ops/hooks | 建立/移除 Shell hook(需同意授權) |
GET /api/system/stats | 主機統計 — OS、CPU、記憶體、磁碟、運行時間 |
GET /api/hermes/update/check | 回報更新可用性(落後 commit 數、安裝方式)而不套用。對於落後的 git/pip 安裝,也回傳 commits 列表(sha、summary、author、at)顯示已變更的內容。?force=1 清除 6 小時快取 |
GET /api/curator · PUT .../paused · POST .../run | Skill curator 狀態 + pause/resume + run |
GET /api/portal | Nous Portal 認證 + Tool Gateway 路由(唯讀) |
POST /api/ops/prompt-size · /dump · /config-migrate | 診斷(背景執行) |
PUT /api/webhooks/{name}/enabled | 啟用/停用 Webhook 路由 |
POST /api/skills/hub/install · /uninstall · /update | Skills hub 操作(背景執行) |
GET /api/skills/hub/search | 跨所有來源搜尋技能 Hub |
GET /api/sessions/stats | Session store 統計 |
PATCH /api/sessions/{id} | 重新命名/封存 Session |
GET /api/sessions/{id}/export | 以 JSON 匯出 Session(中繼資料 + 訊息) |
POST /api/sessions/prune | 刪除超過 N 天的已結束 Session |
PUT /api/cron/jobs/{id} | 編輯 Cron 作業的提示/排程/名稱/遞送方式 |
認證(閘道模式)
當 Dashboard 綁定到公開或非迴環位址 — 任何不是 127.0.0.1 / localhost 的位址 — 時,Hermes Agent 會啟用認證閘道。每個請求都必須攜帶已驗證的 Session Cookie,否則會被導向登入頁面。有三個內建 Provider:
- Username/password — 在自架 / 本地部署 / 家用實驗室 Dashboard 上設定認證的最簡單方式。無需外部身分提供者。僅在可信網路或 VPN 後方使用 — 不要用於公開網際網路暴露。
- OAuth (Nous Portal) — 用於託管部署和任何可透過公開網際網路存取的 Dashboard,也是 遠端 Hermes Desktop 連接的推薦路徑。每次登入都透過你的 Nous 帳戶驗證,因此這是適合面向網際網路使用的 Provider。
- Self-hosted OIDC — 透過標準 OpenID Connect 帶入你自己的身分提供者(Keycloak、Auth0、Okta、Google、GitHub 透過 OIDC 橋接器等)。不涉及 Nous Portal;在符合標準的 OIDC 伺服器前面時,適合用於公開網際網路暴露。
綁定到迴環位址的 Operator 管理的 Dashboard 不受影響 — 無認證、無登入頁面。
閘道何時啟用
| Flags | 認證閘道 | 使用情境 |
|---|---|---|
hermes dashboard(預設 — 綁定到 127.0.0.1) | OFF | 本地開發 |
hermes dashboard --host 0.0.0.0 | ON | 遠端/生產 — 以 username/password provider 或 OAuth 保護 |
閘道在且僅在以下情況啟用:
- 綁定主機不是
127.0.0.1、::1、localhost或0.0.0.0,且 - 未設定
--insecureflag。
DANGER —
--insecure完全禁用認證
--insecure跳過閘道,提供一個未認證的 Dashboard,可讀寫你的.env(API 金鑰、機密)並可執行 Agent 指令。不要用於遠端連接。 要將 Dashboard 暴露給另一台機器,請設定 username/password provider(或 OAuth)並保持--insecure關閉。此 flag 僅作為完全可信、有防火牆的單主機網路上的最後手段逃生艙。
失敗關閉語義
如果閘道應該啟用但未註冊任何 DashboardAuthProvider(無 Nous 外掛、無自訂外掛),hermes dashboard 會拒絕綁定並顯示明確的錯誤訊息。不存在「預設拒絕但接受一切」的退路 — 配置錯誤的閘道 Dashboard 永遠不會啟動。
預設 Provider:Nous Research
內建的 plugins/dashboard_auth/nous 外掛始終已安裝並自動載入。當設定客戶端 ID 時,它會自動註冊一個名為 nous 的 DashboardAuthProvider。
由於每次登入都透過 Nous Portal 驗證並受你的 Nous 帳戶保護,Nous Provider 是適合將 Dashboard 暴露給公開網際網路的選擇。
註冊 Dashboard
要使用 Nous Provider,你需要一個 OAuth 客戶端 ID(格式為 agent:{id})。有兩種取得方式:
-
CLI —
hermes dashboard register。 在 Dashboard 所在的主機上執行。它會解析你現有的 Nous 登入(如果尚未登入,先執行hermes setup),向 Portal 註冊一個自架 OAuth 客戶端,並將HERMES_DASHBOARD_OAUTH_CLIENT_ID寫入~/.hermes/.env。可選 flag:--name(人類可讀標籤,否則自動生成)和--redirect-uri(面向網際網路主機的公開 HTTPS 回呼 URL)。hermes dashboard register # ✓ Registered dashboard "swift_falcon" # …writes HERMES_DASHBOARD_OAUTH_CLIENT_ID to ~/.hermes/.env -
GUI — Local Dashboards 頁面。 在 Nous Portal 開啟
/local-dashboards,從瀏覽器註冊、命名、管理和撤銷自架 Dashboard。將產生的agent:{id}客戶端 ID 複製到HERMES_DASHBOARD_OAUTH_CLIENT_ID(env)或dashboard.oauth.client_id(config.yaml)。這裡也是你撤銷透過 CLI 註冊的 Dashboard 的地方。
設定
外掛從兩個介面讀取,當環境變數設定為非空值時環境變數優先:
config.yaml — 規範介面:
dashboard:
oauth:
client_id: agent:01HXYZ… # 閘道啟用所需
環境變數 — Operator 覆蓋:
| 環境變數 | 覆蓋 | 格式 | 提供方式 |
|---|---|---|---|
HERMES_DASHBOARD_OAUTH_CLIENT_ID | dashboard.oauth.client_id | agent:{instance_id} | hermes dashboard register |
根據 Hermes Agent 約定(~/.hermes/.env 僅用於 API 金鑰/機密),config.yaml 是為本地開發、本地部署和你直接控制的任何部署設定這些值的推薦位置。 環境變數路徑存在是為了讓託管平台的密鑰注入能推送每次部署的 client_id,而無需有人在映像內部編輯 config.yaml — 這是其主要目的。
空的環境變數值視為未設定,因此已 provisioned 但未填充的平台密鑰不會意外遮蔽有效的 config.yaml 條目。
如果兩個來源都未提供 client_id,外掛會報告具體原因,Dashboard 的失敗關閉綁定錯誤會確切告訴你該修正什麼:
Refusing to bind dashboard to 0.0.0.0 — the OAuth auth gate engages on
non-loopback binds, but no auth providers are registered.
Bundled providers reported these issues:
• nous: HERMES_DASHBOARD_OAUTH_CLIENT_ID is not set (and
dashboard.oauth.client_id in config.yaml is empty). The Nous Portal
provisions this env var (shape 'agent:{instance_id}') when it
deploys a Hermes Agent instance — set it to your provisioned
client id (either as an env var or under dashboard.oauth.client_id
in config.yaml), or pass --insecure to skip the OAuth gate entirely.
Or pass --insecure to skip the auth gate (NOT recommended on untrusted
networks).
實作範例:Nous Research
從已登入的 Hermes 安裝到 Nous 認證的 Dashboard,三個步驟。
1. 登入並註冊 Dashboard。 hermes dashboard register 使用你現有的 provisioning Nous 登入來設置 OAuth 客戶端,並將 HERMES_DASHBOARD_OAUTH_CLIENT_ID 寫入 ~/.hermes/.env:
hermes setup # 如果你尚未登入 Nous Portal
hermes dashboard register
# ✓ Registered dashboard "swift_falcon"
# …writes HERMES_DASHBOARD_OAUTH_CLIENT_ID to ~/.hermes/.env
2. 在可達的位址上執行 Dashboard。 未加 --insecure 的非迴環綁定會啟用 OAuth 閘道,剛寫入的 client_id 會啟用 nous provider:
hermes dashboard --host 0.0.0.0 --port 9119 --no-open
3. 登入。 開啟 http://<host>:9119/,你會被導向到 /login。點擊 Sign in with Nous Research → 在 Portal 認證 → 回到已認證的 Dashboard。從任何機器驗證閘道:
curl -s http://<host>:9119/api/status | jq '.auth_required, .auth_providers'
# true
# ["nous"]
GET /api/auth/me 然後回傳已驗證的 Session(provider: nous)。對於面向網際網路的主機,使用 --redirect-uri https://hermes.example.com/auth/callback 註冊,並設定 HERMES_DASHBOARD_PUBLIC_URL 使 OAuth 回呼解析到你的公開 URL(參閱 Public URL override)。
Username/password Provider(無 OAuth IDP)
如果你不想設定 OAuth 身分提供者 — 一個自架的「只要給我的 Dashboard 加個密碼」部署 — 內建的 plugins/dashboard_auth/basic 外掛會註冊一個名為 basic 的 DashboardAuthProvider,使用使用者名稱和密碼進行認證,而非 OAuth 重定向。
它插入與 OAuth Provider 相同的閘道:在沒有 --insecure 的非迴環綁定時啟用閘道,登入頁面為此 Provider 呈現憑證表單(而非「使用 X 登入」按鈕),登入後的所有下游功能 — Session Cookie、透明重新整理、WS 票券、登出、稽核日誌 — 與 OAuth 路徑完全相同。Session 是 Provider 自行鑄造的無狀態 HMAC 簽章 Token,因此無資料庫、無外部 IDP。密碼雜湊使用 stdlib scrypt(無第三方依賴)。
WARNING — 僅在可信網路上使用 — 不要用於公開網際網路
Username/password Provider 適用於可信網路上的自架 / 本地部署 / 家用實驗室 Dashboard,或僅透過 VPN 可達。它以單一共用憑證保護,無外部身分提供者、MFA 或背後的個別使用者帳戶,因此不適合直接暴露 Dashboard 到公開網際網路。對於面向網際網路的 Dashboard,請使用 Nous Research provider(或你自己的 self-hosted OIDC / custom OAuth provider)。
設定
與 Nous Provider 相同,它從 config.yaml(規範介面)讀取,當環境變數設定為非空值時環境變數優先。它僅在設定 username 加上 password_hash(推薦)或 password 時啟用 — 否則為無操作,因此 OAuth 使用者和迴環/--insecure Operator 不受影響。
config.yaml:
dashboard:
basic_auth:
username: admin
# 推薦 — 儲存時無明文。使用以下指令計算:
# python -c "from plugins.dashboard_auth.basic import hash_password; print(hash_password('PW'))"
password_hash: "scrypt$16384$8$1$…$…"
# ...或明文密碼(載入時在記憶體中雜湊;儲存時安全性較低):
# password: "s3cret"
secret: "<32+ random bytes, base64 or hex>" # Token 簽章密鑰
session_ttl_seconds: 43200 # 可選;存取 Token 生命週期(預設 12 小時)
環境變數覆蓋:
| 環境變數 | 覆蓋 | 備註 |
|---|---|---|
HERMES_DASHBOARD_BASIC_AUTH_USERNAME | dashboard.basic_auth.username | 啟用所需 |
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH | dashboard.basic_auth.password_hash | 推薦(儲存時無明文) |
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD | dashboard.basic_auth.password | 明文;優先於設定中的 password_hash,因此你可以透過環境變數輪替 |
HERMES_DASHBOARD_BASIC_AUTH_SECRET | dashboard.basic_auth.secret | Token 簽章密鑰 |
HERMES_DASHBOARD_BASIC_AUTH_TTL_SECONDS | dashboard.basic_auth.session_ttl_seconds | 存取 Token 生命週期 |
CAUTION — 為穩定 Session 設定明確的
secret當
secret為空時,會為每個程序生成隨機的簽章密鑰。對單個程序來說這沒問題,但這意味著每次重啟都會使所有 Session 失效,且 Session 無法跨多個 Worker。為重啟存活 / 多 Worker 部署設定明確的secret。
/auth/password-login 端點按客戶端 IP 限流(預設每分鐘 10 次嘗試 → HTTP 429),對未知使用者和錯誤密碼都回傳單一通用的 401 Invalid credentials,因此無法用作使用者名稱列舉預言機。
實作範例:username/password
從零開始在可信網路上建立密碼認證的 Dashboard,三個步驟。
1. 在 ~/.hermes/.env 中設定憑證。 雜湊密碼使儲存時無明文,並設定穩定的簽章密鑰使 Session 在重啟後存活:
# 計算你選擇的密碼的 scrypt 雜湊:
HASH=$(python -c "from plugins.dashboard_auth.basic import hash_password; print(hash_password('choose-a-strong-password'))")
cat >> ~/.hermes/.env <<EOF
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH=$HASH
HERMES_DASHBOARD_BASIC_AUTH_SECRET=$(openssl rand -base64 32)
EOF
chmod 600 ~/.hermes/.env
2. 在可達的位址上執行 Dashboard。 未加 --insecure 的非迴環綁定會啟用閘道,使用者名稱 + 雜湊會啟用 basic provider:
hermes dashboard --host 0.0.0.0 --port 9119 --no-open
3. 登入。 開啟 http://<host>:9119/,你會被導向到 /login — 一個憑證表單(不是「使用 X 登入」按鈕)。輸入 admin / 你的密碼 → 到達已認證的 Dashboard。從任何機器驗證閘道:
curl -s http://<host>:9119/api/status | jq '.auth_required, .auth_providers'
# true
# ["basic"]
GET /api/auth/me 然後回傳已驗證的 Session(provider: basic)。請將此放在 VPN 後方 — 參閱上方的警告;對於公開主機,請改用 Nous Research 或 self-hosted OIDC provider。
編寫你自己的密碼 Provider
basic 只是延伸點的一個實作。任何外掛都可以註冊密碼 Provider:在你的 DashboardAuthProvider 子類別上設定 supports_password = True,並實作 complete_password_login(*, username, password) -> Session(拒絕時拋出 InvalidCredentialsError,當你的儲存後端當機時拋出 ProviderError)。OAuth 的 start_login / complete_login 方法可以留為 NotImplementedError 骨架。這是 LDAP 綁定、憑證資料庫或任何其他非重定向認證方案的路徑 — 框架為你處理表單、路由、Cookie 和重新整理。
Self-hosted OIDC Provider
如果你運行自己的身分提供者,內建的 plugins/dashboard_auth/self_hosted 外掛使用標準 OpenID Connect 對 Dashboard 進行認證 — 無需針對特定 IDP 的程式碼,不涉及 Nous Portal。它已驗證並可與任何符合標準的 OIDC 伺服器一起使用:
Authentik · Keycloak · Zitadel · Authelia · Auth0 · Okta · Google · …
與 Nous Provider 相同,它會自動載入,且僅在設定完成後才註冊自己,因此對迴環/--insecure 的 Dashboard 來說是無操作的。
設定
設定一個 issuer 和一個 client_id(公開 PKCE 客戶端 — 無客戶端密鑰)。外掛從 {issuer}/.well-known/openid-configuration 取得 IDP 的 authorization_endpoint、token_endpoint 和 jwks_uri,因此你永遠不需要硬編碼端點 URL。
config.yaml — 規範介面:
dashboard:
oauth:
provider: self-hosted
self_hosted:
issuer: https://auth.example.com/application/o/hermes/ # 必要
client_id: hermes-dashboard # 必要
scopes: "openid profile email" # 可選(這是預設值)
環境變數 — Operator 覆蓋(當設定為非空值時環境變數優先於 config.yaml;空值視為未設定):
| 環境變數 | 覆蓋 | 備註 |
|---|---|---|
HERMES_DASHBOARD_OIDC_ISSUBER | dashboard.oauth.self_hosted.issuer | OIDC issuer URL — 必要 |
HERMES_DASHBOARD_OIDC_CLIENT_ID | dashboard.oauth.self_hosted.client_id | 公開客戶端 ID — 必要 |
HERMES_DASHBOARD_OIDC_SCOPES | dashboard.oauth.self_hosted.scopes | 預設為 openid profile email |
在你的 IDP 中,註冊一個公開應用/客戶端,使用 authorization-code + PKCE(S256)grant,並將 Dashboard 的回呼加入允許的重定向 URI。回呼是 <dashboard public URL>/auth/callback(參閱 Public URL override 了解 Dashboard 在代理後方如何取得其公開 URL)。
它驗證什麼
Provider 根據已發現的 jwks_uri 驗證 OpenID Connect ID Token(RS256/ES256),iss 和 aud claims 固定到你設定的 issuer 和 client_id。標準 OIDC claims 映射到 Dashboard Session:
| Session 欄位 | Claim(s) |
|---|---|
user_id | sub(必要) |
email | email |
display_name | name → preferred_username → nickname → email |
org_id | org_id / organization,否則為連接的 groups |
ID Token 是建立身分的依據 — Access Token 被視為不透明的(OIDC 規範不要求它是 JWT)。端點 URL 必須是 HTTPS(迴環 http:// 允許用於本地開發 IDP),且發現文件宣傳的 issuer 必須與你設定的一致(允許尾部斜線差異)。Refresh Token(當 IDP 發行時)用於透過標準 refresh_token grant 進行靜默重新認證;登出會在 IDP 宣傳時呼叫其 RFC 7009 revocation_endpoint。
Confidential clients(帶有
client_secret的)尚未支援 — 請設定公開 + PKCE 客戶端,這是瀏覽器前端 Dashboard 的典型選擇。
實作範例:Keycloak
Keycloak 是最容易架設用於本地測試的自架 OIDC 伺服器之一 — 它以單一容器在開發模式下運行(記憶體資料庫),並暴露教科書級的 OIDC 發現功能。本教學讓你在幾分鐘內從零開始到運作的 Dashboard 登入。
1. 使用預設設定的 realm 執行 Keycloak。 將此 realm 匯出儲存為 realm-hermes.json — 它定義了一個 hermes realm、一個公開 PKCE 客戶端(hermes-dashboard)和一個測試使用者,全部在啟動時匯入,因此在管理 UI 中無需點擊任何東西:
{
"realm": "hermes",
"enabled": true,
"clients": [
{
"clientId": "hermes-dashboard",
"name": "Hermes Agent Dashboard",
"enabled": true,
"publicClient": true,
"standardFlowEnabled": true,
"protocol": "openid-connect",
"redirectUris": ["http://localhost:9119/auth/callback"],
"webOrigins": ["http://localhost:9119"],
"attributes": { "pkce.code.challenge.method": "S256" }
}
],
"users": [
{
"username": "testuser",
"enabled": true,
"emailVerified": true,
"email": "testuser@example.com",
"firstName": "Test",
"lastName": "User",
"credentials": [
{ "type": "password", "value": "testpassword", "temporary": false }
]
}
]
}
啟動它(Keycloak 26+),將該檔案掛載到匯入目錄:
docker run --rm -p 8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
-v "$PWD/realm-hermes.json:/opt/keycloak/data/import/realm-hermes.json:ro" \
quay.io/keycloak/keycloak:26.0 \
start-dev --import-realm
啟動後,realm 在 http://localhost:8080/realms/hermes/.well-known/openid-configuration 宣傳標準 OIDC 發現(issuer http://localhost:8080/realms/hermes)。管理控制台位於 http://localhost:8080/(admin / admin)。
2. 將 Dashboard 指向它。 Self-hosted 外掛允許迴環 http:// issuer(任何非迴環 issuer 需要 HTTPS),因此本地 Keycloak 可以原樣使用:
export HERMES_DASHBOARD_OIDC_ISSUER="http://localhost:8080/realms/hermes"
export HERMES_DASHBOARD_OIDC_CLIENT_ID="hermes-dashboard"
export HERMES_DASHBOARD_PUBLIC_URL="http://localhost:9119"
hermes dashboard --host 0.0.0.0 --port 9119 --no-open
HERMES_DASHBOARD_PUBLIC_URL 告訴 Dashboard 其 OAuth 回呼是 http://localhost:9119/auth/callback — 即 realm 上方註冊的重定向 URI。綁定到 0.0.0.0(非迴環綁定)且不加 --insecure 就是啟用 OAuth 閘道的方式。
3. 登入。 開啟 http://localhost:9119/,你會被導向到 /login。點擊 Sign in with Self-Hosted OIDC → 在 Keycloak 以 testuser / testpassword 認證 → 回到已認證的 Dashboard。側邊欄顯示 Logged in as Test User via self-hosted,GET /api/auth/me 回傳已驗證的 Session(provider: self-hosted,email: testuser@example.com)。
如果你在不同的主機/連接埠綁定或瀏覽,請在 Keycloak 管理控制台(Clients → hermes-dashboard → Settings)的Valid redirect URIs中加入該來源的
…/auth/callback。相同的模式適用於 Authentik、Zitadel、Authelia 和其他 OIDC 伺服器 — 只有 issuer URL 和客戶端註冊 UI 不同。
Public URL Override
預設情況下,Dashboard 從請求中重建 OAuth 回呼 URL — X-Forwarded-Host + X-Forwarded-Proto + X-Forwarded-Prefix(當 uvicorn 配置了 proxy_headers=True 時,start_server 在閘道下會啟用此選項)。這在正確設定所有三個標頭的反向代理後方可以開箱即用。
對於無法可靠轉發這些標頭的反向代理後方的部署(手動 nginx 設定、本地 ingress、帶有部分代理鏈的自訂網域部署),請設定 dashboard.public_url(或 HERMES_DASHBOARD_PUBLIC_URL)為你到達 Dashboard 的完整公開 URL:
dashboard:
public_url: "https://dashboard.example.com/hermes"
設定後,OAuth 回呼 URL 就是 <public_url>/auth/callback 的原文 — 該程式碼路徑上 X-Forwarded-Prefix 被忽略,因為 Operator 已明確宣告了公開 URL。這是故意的:在前綴已嵌入 public_url 的常見情況下,疊加前綴會導致雙重前綴。
與其他 Dashboard 設定相同的優先順序 — 環境變數優先於 config.yaml:
| 介面 | 覆蓋路徑 | 使用時機 |
|---|---|---|
config.yaml 中的 dashboard.public_url | HERMES_DASHBOARD_PUBLIC_URL | 本地開發/本地部署(規範介面) |
HERMES_DASHBOARD_PUBLIC_URL 環境變數 | — | 託管平台密鑰 / CI |
| (未設定) | — | 預設 — 從 X-Forwarded-* 標頭重建 |
驗證會拒絕不含 http:// / https:// scheme、不含主機或包含引號/尖括號/空白字元/控制字元的值。格式不正確的值會靜默降級到標頭重建,使登入流程保持運作而不是將使用者導向惡意 URL。
注意:
public_url只覆蓋 OAuth 回呼 URL。SecureCookie 標誌仍由request.url.scheme控制(在 proxy_headers 下為 X-Forwarded-Proto),因此在 TLS 終止的公開部署上使用http://public_url會產生非 Secure 的 Cookie。這是 Operator 的常見陷阱 — 請在上游搭配正確的 TLS 終止。
OAuth 流程
Provider 實作了 Nous Portal OAuth contract v1 — 帶有 PKCE(S256)的 authorization-code grant:
- 使用者在沒有 Session Cookie 的情況下存取
/→ 閘道重定向到/login。 - 登入頁面顯示「Continue with Nous Research」按鈕 →
/auth/login?provider=nous。 - 伺服器將 PKCE state 存入短期 Cookie,將使用者重定向到
https://portal.nousresearch.com/oauth/authorize?…。 - 使用者在 Portal 認證,到達
/auth/callback?code=…&state=…。 - 伺服器在
POST /api/oauth/token用授權碼換取 Access Token,根據 Portal 的 JWKS(/.well-known/jwks.json)驗證 JWT 簽章,並設定hermes_session_atCookie。 - 使用者被重定向到
/(或透過next=查詢參數到達原始深層連結路徑)。
Access Token 有 15 分鐘的 TTL。contract v1 中沒有 Refresh Token — 當 Token 過期時,SPA 的 fetch wrapper 檢測到 401 信封並進行整頁導航回到 /login 以重新執行流程。
設定的 Cookies
| 名稱 | 生命週期 | 備註 |
|---|---|---|
hermes_session_at | Token TTL(15 分鐘) | HttpOnly、SameSite=Lax、HTTPS 時 Secure |
hermes_session_pkce | 10 分鐘 | HttpOnly;在來回行程中保存 PKCE verifier + provider 提示 |
hermes_session_rt | v1 中未使用 | 為前向相容保留;當 refresh_token 為空時不寫入 |
三者的 Path=/ 和 SameSite=Lax。Secure 標誌在透過 HTTPS 到達 Dashboard 時設定(透過請求 URL scheme 偵測 — 在 proxy_headers=True 下遵守上游 TLS 終止的 X-Forwarded-Proto)。
登出
側邊欄小部件顯示 Logged in as <user_id…> via nous 及登出圖示。點擊它會 POST /auth/logout,清除所有 Dashboard 認證 Cookie 並重定向回 /login。
稽核日誌
每次登入開始、成功、失敗和 Session 驗證失敗都以 JSON 行寫入 $HERMES_HOME/logs/dashboard-auth.log。敏感欄位(access_token、refresh_token、code、code_verifier、state、Authorization 標頭)在記錄前被遮蔽。
自訂 Providers
要插入非 Nous 的 OAuth Provider(例如 Google、GitHub、自訂 OIDC),建立一個註冊 DashboardAuthProvider 的外掛:
# ~/.hermes/plugins/dashboard-auth-myidp/__init__.py
from hermes_cli.dashboard_auth import DashboardAuthProvider, Session, LoginStart
class MyIdPProvider(DashboardAuthProvider):
name = "myidp"
display_name = "My Identity Provider"
def start_login(self, *, redirect_uri): ...
def complete_login(self, *, code, state, code_verifier, redirect_uri): ...
def verify_session(self, *, access_token): ...
def refresh_session(self, *, refresh_token): ...
def revoke_session(self, *, refresh_token): ...
def register(ctx):
ctx.register_dashboard_auth_provider(MyIdPProvider())
登入頁面列出所有已註冊的 Provider;多個 Provider 可以疊加,使用者在 /login 選擇其中一個。
驗證閘道已啟用
# 快速環境變數路徑。
HERMES_DASHBOARD_OAUTH_CLIENT_ID=agent:test \
hermes dashboard --host 0.0.0.0
# 或透過 config.yaml 的等效方式(推薦用於本地開發/本地部署):
#
# dashboard:
# oauth:
# client_id: agent:test
#
# 然後只需:
hermes dashboard --host 0.0.0.0
# 呼叫 /api/status 查看閘道狀態:
curl -s http://127.0.0.1:9119/api/status | jq '.auth_required, .auth_providers'
# true
# ["nous"]
Dashboard 的 React StatusPage 在「Web server」下方顯示相同的欄位。側邊欄的 AuthWidget 在你登入後呈現目前的身分。
將 Hermes Desktop 連接到遠端後端
Hermes Desktop 可以驅動在另一台機器上運行的 Hermes 後端(VPS、家庭伺服器、Tailscale 後方的 Mini)。在應用中位於 Settings → Gateway → Remote gateway,需要輸入 Remote URL 和登入方式。(桌面應用本身 — 安裝、設定、聊天 — 請參閱 Hermes Desktop 頁面。)
你使用其中一個內建的認證 Provider 保護遠端 Dashboard,桌面應用會根據後端宣傳的 Provider 進行登入。對於超出你自己機器的後端 — VPS、公開主機、任何面向網際網路的 — 推薦的 Provider 是 OAuth (Nous Portal)(使用 hermes dashboard register 註冊,並使用 Sign in with Nous Research 登入)。內建的 username/password provider 是後端在可信 LAN 或僅透過 VPN 可達時最快的選項,但不適合直接公開網際網路暴露。將 Dashboard 綁定到非迴環位址會啟用其認證閘道;一旦登入,Desktop 會自動重用 Session 進行聊天 WebSocket — 無需複製或貼上 Token。
以下配方使用 username/password 路徑,因為它是在可信網路上最快架設的方式;OAuth 路徑請參閱 Default provider: Nous Research。
在後端(遠端機器上)
# 1. 在 ~/.hermes/.env 中設定 Dashboard 登入憑證(機密檔案,0600)。
cat >> ~/.hermes/.env <<'EOF'
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=choose-a-strong-password
# 推薦:穩定的簽章密鑰使 Session 在重啟後存活。
HERMES_DASHBOARD_BASIC_AUTH_SECRET=$(openssl rand -base64 32)
EOF
chmod 600 ~/.hermes/.env
# 2. 在可達的位址上執行 Dashboard。非迴環綁定會啟用認證閘道;
# username/password provider 處理登入。
hermes dashboard --no-open --host 0.0.0.0 --port 9119
偏好儲存時無明文?使用 HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH 搭配 scrypt 雜湊 — 完整選項請參閱 Username/password provider。
如果你以 systemd 服務執行 Dashboard,當 unit 設有 EnvironmentFile=%h/.hermes/.env 時,~/.hermes/.env 會在啟動時自動載入,因此憑證在開機時就在環境中。
WARNING
Dashboard 讀寫你的
.env(API 金鑰、機密)並可執行 Agent 指令。此處展示的 username/password 設定用於可信網路 — 永遠不要將密碼保護的 Dashboard 直接暴露到公開網際網路。將它放在 VPN 後方。Tailscale 是乾淨的選項:綁定到機器的 tailscale IP(--host <tailscale-ip>),並使用http://<tailscale-ip>:9119作為 Remote URL。只有你 tailnet 上的裝置才能到達它。要透過公開網際網路到達後端,請改用 OAuth (Nous Portal) provider。
在 Hermes Desktop 中
Settings → Gateway → Remote gateway:
- Remote URL —
http://<backend-host>:9119(如果你在反向代理前面,路徑前綴如/hermes受支援) - Sign in — 應用偵測到 username/password 閘道並顯示 Sign in 按鈕;點擊它並輸入步驟 1 的憑證
- Save and reconnect — 將桌面 Shell 切換到遠端後端
Session 會自動重新整理,當後端設定了 HERMES_DASHBOARD_BASIC_AUTH_SECRET 時會在重啟後存活。
環境變數覆蓋
除了應用內設定,你也可以在啟動前用環境變數將桌面指向後端。當 HERMES_DESKTOP_REMOTE_URL 設定時,它會覆蓋已儲存的應用內 URL(Gateway 設定面板顯示「env override」徽章並停用編輯);你仍然從面板用使用者名稱和密碼登入。
| 環境變數 | 值 |
|---|---|
HERMES_DESKTOP_REMOTE_URL | http://<backend-host>:9119 |
疑難排解
- 「Remote gateway incomplete」 — 你尚未輸入遠端 URL。
- 登入失敗 401 / 「Invalid credentials」 — 使用者名稱或密碼與後端的
HERMES_DASHBOARD_BASIC_AUTH_USERNAME/HERMES_DASHBOARD_BASIC_AUTH_PASSWORD不匹配。後端對未知使用者和錯誤密碼回傳相同的通用錯誤,因此兩者都要檢查。使用curl -s http://<host>:9119/api/status | jq '.auth_required, .auth_providers'確認閘道 — 應回報true且包含"basic"。 - 沒有「Sign in」按鈕 — 改為要求 Session Token — username/password provider 未啟用(
/api/status不會列出"basic")。確保使用者名稱和密碼(或密碼雜湊)已設定且 Dashboard 程序已載入它們。 - 每次重啟都登出 — 將
HERMES_DASHBOARD_BASIC_AUTH_SECRET設為穩定值;否則簽章密鑰會在每次啟動時重新生成。 - 連接被拒絕 / 逾時 — 後端綁定到
127.0.0.1(預設值)而非可達的位址,或防火牆/VPN 正在封鎖連接埠。綁定到0.0.0.0或 tailscale IP,並對你的可信網路開放連接埠。
CORS
Web 伺服器將 CORS 限制為僅允許 localhost 來源:
http://localhost:9119/http://127.0.0.1:9119(生產環境)http://localhost:3000/http://127.0.0.1:3000http://localhost:5173/http://127.0.0.1:5173(Vite 開發伺服器)
如果你在自訂連接埠上執行伺服器,該來源會自動新增。
開發
如果你要貢獻 Web Dashboard 前端:
# 終端 1:啟動後端 API
hermes dashboard --no-open
# 終端 2:啟動帶有 HMR 的 Vite 開發伺服器
cd web/
npm install
npm run dev
http://localhost:5173 上的 Vite 開發伺服器將 /api 請求代理到 http://127.0.0.1:9119 上的 FastAPI 後端。
前端使用 React 19、TypeScript、Tailwind CSS v4 和 shadcn/ui 風格的元件構建。生產建置輸出到 hermes_cli/web_dist/,FastAPI 伺服器將其作為靜態 SPA 伺服。
更新時自動建置
當你執行 hermes update 時,如果 npm 可用,Web 前端會自動重新建置。這使 Dashboard 與程式碼更新保持同步。如果未安裝 npm,更新會跳過前端建置,hermes dashboard 會在首次啟動時建置它。
主題與外掛
Dashboard 內建六個主題,並可透過使用者自訂主題、外掛分頁和後端 API 路由進行擴展 — 全部即插即用,無需複製 repo。
即時切換主題 — 從頁首列點擊語言切換器旁的調色盤圖示。選擇會持久化到 config.yaml 的 dashboard.theme,並在頁面載入時還原。
獨立更改字型 — 從相同的選擇器中 — 主題清單下方的 Font 區段覆蓋任何活躍主題的 UI 字型。選擇會跨主題切換持久化(config.yaml → dashboard.font);選擇 Theme default 可清除它並回到活躍主題自己的字型。
內建主題:
| 主題 | 特色 |
|---|---|
Hermes Teal (default) | 深藍綠 + 奶油色、系統字型、舒適間距 |
Hermes Teal (Large) (default-large) | 與 default 相同,18px 文字和更寬鬆的間距 |
Midnight (midnight) | 深藍紫、Inter + JetBrains Mono |
Ember (ember) | 暖紅 + 青銅色、Spectral serif + IBM Plex Mono |
Mono (mono) | 灰階、IBM Plex、緊湊 |
Cyberpunk (cyberpunk) | 黑底霓虹綠、Share Tech Mono |
Rosé (rose) | 粉紅 + 象牙色、Fraunces serif、寬敞 |
要建立你自己的主題、新增外掛分頁、注入 Shell Slots 或暴露外掛專屬 REST 端點,請參閱 Extending the Dashboard — 完整指南涵蓋:
- 主題 YAML schema — 調色盤、字型排版、佈局、資源、componentStyles、colorOverrides、customCSS
- 佈局變體 —
standard、cockpit、tiled - 外掛 manifest、SDK、Shell slots、頁面範圍限定的 slots(將小部件注入內建頁面而不覆蓋它們)、後端 FastAPI 路由
- 完整的主題加外掛教學(Strike Freedom cockpit 示範)
- 發現、重新整理和疑難排解