1. 为什么你的 Hermes-WebUI 总是“启动成功但用不了”
Hermes-WebUI 是一个面向 Hermes Agent 的自托管可视化控制台,它把聊天、会话、工作区文件、任务调度、模型与 Profile 管理集中到一个三栏式浏览器界面里。适合正在用 Hermes Agent、Claude Code、Codex、OpenCode 这类工具,并且想把 Agent 长期跑在服务器或 homelab 上的开发者。它默认监听 127.0.0.1:8787,用 Python 标准库 HTTP Server 加 vanilla JS 实现,没有前端构建步骤,所以部署路径短、依赖少。
但真正上手时,很多人会卡在同一个地方:docker compose up -d显示容器 running,浏览器也能打开页面,可模型列表是空的、workspace 看不到文件、任务手动能跑定时不触发。这类问题几乎都不是“程序坏了”,而是配置骨架没搭对——settings.json / config.toml 里的 Key 通道、挂载路径、UID/GID、gateway 状态任意一环错位,都会让控制台变成一个空壳。
这篇就按“配置文件骨架 → 统一 Key/API 通道接入 → 连通性验证 → 报错排查”的顺序走一遍,交付可以直接复制的配置片段和逐步验证动作。核心思路是:先把 Key 通道和挂载跑通,再谈任务调度和监控,别一上来就追求三容器完整架构。
2. 前置准备:统一 Key/API 通道与目录骨架
在动 Hermes-WebUI 之前,先把两件事定下来:模型 Key 从哪来、Hermes home 放哪。
模型接入这块,我建议用一个统一的 API 通道来管理,而不是在每个 Profile 里散着填不同厂商的 Key。TaoToken 提供的就是这种统一入口,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api 。它的作用是让你用一套 Key 和兼容接口去对接多个模型,Hermes-WebUI 的 Profile 切换时不用反复改底层凭证。
先把 Key 拿到手:进入控制台创建 API Key,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 。创建完复制保存,后面写进.env和 Hermes 的 config 里。如果你还不确定模型名怎么填,可以先用模型对话页确认可用模型列表:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。
目录骨架建议这样规划,避免后面挂载错位:
# Hermes home:Agent 的配置、记忆、skills、cron 都在这 mkdir -p ~/.hermes # 工作区:Agent 读写文件的地方 mkdir -p ~/hermes-workspace # 项目目录 git clone https://github.com/nesquena/hermes-webui.git hermes-webui cd hermes-webui这里有个关键点:~/.hermes和~/hermes-workspace必须是宿主机上真实存在、且当前用户有读写权限的目录。后面容器挂载的就是这两个路径,挂错了就会出现“config.yaml 读不到”“workspace 是空的”这类现象。
3. 可复制配置:settings.json 与 config.toml 骨架
Hermes-WebUI 本身通过.env控制 WebUI 层的行为,而 Agent 的模型、Profile、记忆等由 Hermes 的 config 管理。两者要分开理解,混在一起改最容易出错。
先看 WebUI 层的.env骨架,从示例复制后逐项改:
cp .env.docker.example .env然后编辑.env,核心字段如下:
# WebUI 访问密码,公网暴露前必须设置 HERMES_WEBUI_PASSWORD=change-me-to-something-strong # 宿主机 UID/GID,避免挂载权限错位 UID=1000 GID=1000 # Hermes home 与 workspace 挂载路径 HERMES_HOME=/home/yourname/.hermes HERMES_WORKSPACE=/home/yourname/hermes-workspace # 监听地址,默认只绑本机 HERMES_WEBUI_HOST=127.0.0.1 HERMES_WEBUI_PORT=8787UID/GID 一定要用id -u和id -g的真实值,macOS 上经常不是 1000:
echo "UID=$(id -u)" >> .env echo "GID=$(id -g)" >> .env再看 Hermes Agent 侧的 config。Hermes 支持config.yaml(部分版本用config.toml),模型 provider 段落是重点。用统一通道接入时,把 base_url 指向 TaoToken 的 API 端点,Key 用刚才创建的那把:
# ~/.hermes/config.yaml providers: taotoken: type: openai-compatible base_url: https://taotoken.net/api api_key: sk-你的TaoToken密钥 models: - gpt-4o - claude-3-5-sonnet - deepseek-chat default_profile: default profiles: default: provider: taotoken model: claude-3-5-sonnet workspace: /home/yourname/hermes-workspace如果你用的是config.toml风格,等价写法是:
[providers.taotoken] type = "openai-compatible" base_url = "https://taotoken.net/api" api_key = "sk-你的TaoToken密钥" models = ["gpt-4o", "claude-3-5-sonnet", "deepseek-chat"] [profiles.default] provider = "taotoken" model = "claude-3-5-sonnet" workspace = "/home/yourname/hermes-workspace"注意:
base_url只写到https://taotoken.net/api,不要自己拼/v1/chat/completions,兼容层会处理路径。Key 不要提交到 git,.env和config.yaml都加进.gitignore。
配置写完后,先别急着起容器,用docker compose config检查变量有没有被正确解析:
docker compose config输出里应该能看到HERMES_HOME、UID、GID都替换成了真实值。如果还是${UID}原样,说明.env没被读到,检查文件是否在 compose 同目录。
4. 启动与连通性验证:从 health 到真实对话
配置骨架搭好后,按“单容器先跑通”的原则启动:
docker compose up -d docker compose logs -f --tail=100日志里看到监听 8787 且没有 traceback,再进行下一步验证。验证顺序很重要,从低风险到高风险逐层排查。
第一层,服务健康:
curl http://127.0.0.1:8787/health预期返回:
{"status":"ok"}第二层,模型通道连通。这一步直接验证 TaoToken 的 Key 和 base_url 是否可用,绕开 WebUI 先确认底层通:
curl https://taotoken.net/api/v1/models \ -H "Authorization: Bearer sk-你的TaoToken密钥"返回模型列表就说明 Key 通道没问题。如果这里就 401,别去翻 WebUI 日志,先解决 Key。
第三层,WebUI 内模型可用性。打开浏览器访问http://127.0.0.1:8787,在模型下拉里应该能看到 config 里配置的模型。发一条测试消息,观察是否流式返回、工具调用卡片是否正常渲染。
第四层,workspace 挂载。点右侧工作区面板,确认能看到~/hermes-workspace里的文件。如果为空,回到第 5 节排查 UID/GID。
第五层,文件读写。在聊天里让 Agent 创建一个测试文件:
# 在 WebUI 聊天框输入 在工作区创建一个 test.md,写入 hello hermes然后到宿主机确认:
cat ~/hermes-workspace/test.md宿主机能看到内容,说明挂载和权限都通了。
第六层,任务调度。如果你用的是双容器,验证 gateway:
docker compose -f docker-compose.two-container.yml exec hermes-agent hermes gateway statusgateway 正常,Tasks 面板里的定时任务才会真正触发。
5. 本篇常见错排查:五类高频故障
5.1 sudo 启动导致挂错 home
现象是 WebUI 起来了,但读不到~/.hermes/config.yaml。原因是sudo让${HOME}变成/root,容器挂载的是/root/.hermes。解决方式是尽量不用 sudo,必须用时显式传环境变量:
HERMES_HOME=/home/yourname/.hermes \ HERMES_WORKSPACE=/home/yourname/hermes-workspace \ sudo -E docker compose up -d5.2 UID/GID 不匹配
现象是PermissionError、workspace 空白、config 存在但读不到。修复:
echo "UID=$(id -u)" >> .env echo "GID=$(id -g)" >> .env docker compose down docker compose up -d5.3 双容器里 git/node 找不到
在聊天里让 Agent 执行git或node,提示command not found。原因是工具运行在 WebUI 容器,而 WebUI 镜像不一定装了这些。三个思路:换单容器、扩展 WebUI 的 Dockerfile 装工具、或用社区 all-in-one 镜像。选哪个取决于你是否需要长期后台任务。
5.4 容器内访问宿主机 localhost 失败
宿主机上http://localhost:11434可用,容器里配 localhost 却连不上。因为容器里的 localhost 指容器自己。Docker Desktop 用http://host.docker.internal:11434,Podman 用http://host.containers.internal:11434。
5.5 任务创建了但离线不执行
Tasks 面板能手动 Run now,定时不触发。原因是缺 gateway daemon 驱动 cron tick。切双容器并检查状态:
docker compose -f docker-compose.two-container.yml up -d docker compose -f docker-compose.two-container.yml exec hermes-agent hermes gateway status6. 长期编码与 Agent 场景的下一步
单容器跑通后,如果你打算让 Hermes Agent 长期承担编码、定时汇总、日志分析这类任务,建议把 Key 通道和 Profile 管理固定下来,再考虑上双容器分离 gateway。统一通道的好处是 Profile 切换时不用动底层凭证,模型换绑只改 config 里的 model 字段。
需要长期跑编码类 Agent 的,可以看下 Coding Plan 的接入方式:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。如果你更想先把模型对话链路验证透,再决定接哪个模型,模型对话页在 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。Key 管理和接入文档分别在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 和 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
最后给一个实测下来最省事的顺序:先curl /health,再curl模型列表,再 WebUI 发消息,再验证 workspace 读写,最后才碰任务调度。这个顺序能把“配置错”和“程序坏”快速分开,少走很多弯路。