Hermes Agent跨平台部署指南:Windows与Linux通用实践
1. 为什么这个指南必须同时覆盖 Windows 和 Linux?——从部署本质讲清“通用性”的真实含义
很多人看到标题里写着“Windows / Linux 通用”,第一反应是:“不就是换条命令的事?Windows 用 PowerShell,Linux 用 Bash,复制粘贴改个路径就行。”
这种理解在 Docker 部署 Hermes Agent 这件事上,不仅片面,而且危险。我去年在给三家客户做私有化部署时,就因为轻信了“通用=命令替换”这个错觉,在 Windows 上反复失败了 17 次,最后发现根本问题不在命令语法,而在于底层运行时契约的断裂。
Hermes Agent 官方镜像(nousresearch/hermes-agent)是一个基于debian:13.4构建的 Linux 容器。它内部依赖的不是抽象的“操作系统”,而是具体的 Linux 内核特性、POSIX 工具链、用户权限模型,以及一套被深度集成的进程管理机制——s6-overlay。当你在 Windows 上运行它时,Docker Desktop 并没有给你一个真正的 Linux 环境,而是通过 WSL2(Windows Subsystem for Linux 2)提供了一个高度兼容但并非完全等同的 Linux 运行时。这个“兼容层”会默默吃掉很多你习以为常的假设:比如/home/username的语义、~符号的展开规则、文件权限位的映射方式、甚至docker run -v挂载卷时的 inode 行为。
举个最典型的例子:官方文档里那条“开箱即用”的初始化命令:
mkdir -p ~/.hermes docker run -it --rm \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent setup在 Linux 上,~/.hermes是一个标准的绝对路径,-v参数能精准地将宿主机的这个目录挂载为容器内的/opt/data。但在 Windows 的 Docker Desktop 中,~默认指向的是WSL2 发行版里的家目录(例如/home/yourname),而不是你 Windows 用户目录下的C:\Users\YourName。如果你直接在 PowerShell 里执行这条命令,Docker Desktop 会尝试把C:\Users\YourName\.hermes映射过去,但此时 WSL2 的文件系统桥接机制可能尚未就绪,或者路径解析规则不同,结果就是容器内/opt/data目录为空,setup向导找不到.env文件,直接报错退出——而错误日志里只显示Permission denied或No such file or directory,根本不会告诉你问题出在路径解析这一步。
这就是“通用”二字背后的真实分量:它不是指命令长得像,而是指整个部署流程能在两个平台的原生约束下,达成完全一致的行为结果。要实现这一点,我们必须放弃“写两套脚本”的懒人思维,转而构建一套平台感知型部署逻辑。这套逻辑的核心,是让部署过程自己去识别当前环境,并自动选择最安全、最符合该平台工程实践的路径。
所以,本指南的“通用”,体现在三个不可妥协的层面:
- 路径策略通用:不依赖
~,统一使用显式、可验证的绝对路径; - 权限模型通用:绕过 UID/GID 映射的灰色地带,用
PUID/PGID环境变量进行显式声明; - 网络行为通用:对
host.docker.internal、--network host、Docker Compose 网络等不同模式,给出明确的适用边界和验证方法。
这不是为了炫技,而是因为 Hermes Agent 的核心价值——多模态工具调用、浏览器自动化、本地模型接入——全部建立在稳定、可预测的底层环境之上。一次因平台差异导致的Playwright启动失败,或Ollama连接超时,都可能让整个智能体工作流卡死。接下来的内容,每一项操作、每一个参数、每一条命令,都将严格服务于这三重“通用性”目标。我们不追求“能跑”,我们追求“跑得稳、看得懂、修得快”。
2. 环境准备:Windows 与 Linux 的“最小可行共识”清单
部署前的环境检查,是所有后续步骤的基石。很多看似玄学的故障,根源都在这里。我见过太多人跳过这一步,直接docker run,然后在日志里大海捞针。下面这份清单,是我从上百次部署中提炼出的、Windows 与 Linux 必须共同满足的“最小可行共识”。它不求大而全,但求每一项都可验证、可证伪、可快速修复。
2.1 Docker 引擎版本与运行时状态
Hermes Agent 官方镜像明确要求 Docker Engine v24.0.0+(基于其对 s6-overlay v3 的依赖)。低于此版本,--restart unless-stopped的行为、--shm-size的默认值、甚至docker exec的信号传递机制都可能存在兼容性问题。
验证方法(Windows & Linux 通用):
docker version --format '{{.Server.Version}}' # 输出应为 24.0.0 或更高关键点:
- Windows 用户注意:Docker Desktop 自带的 Docker Engine 版本,不等于你通过
winget或choco安装的独立 Docker CLI 版本。务必使用docker version命令验证的是Server(服务端)版本,而非 Client(客户端)。 - Linux 用户注意:如果你使用的是 Ubuntu/Debian 的
apt install docker.io,它提供的通常是老旧的20.10.x版本。必须卸载并安装官方 Docker CE:sudo apt-get remove docker docker-engine docker.io containerd runc # 然后按 Docker 官网指引安装 CE
运行时状态检查:
docker info | grep "Server Version\|Kernel Version\|Operating System" # 关键输出示例(Linux): # Server Version: 24.0.7 # Kernel Version: 6.5.0-45-generic # Operating System: Ubuntu 22.04.4 LTS # 关键输出示例(Windows): # Server Version: 24.0.7 # Kernel Version: 5.15.133.1-microsoft-standard-WSL2 # Operating System: Docker Desktop提示:如果
Operating System显示为Docker Desktop,说明你正处于 WSL2 模式,这是 Windows 上的推荐且唯一可靠的运行模式。请勿尝试在纯 Windows 命令提示符(cmd)或 PowerShell(非 WSL2 后端)下运行 Hermes,那会导致音频、GUI 工具等模块彻底失效。
2.2 存储空间与文件系统权限
Hermes Agent 的数据目录(/opt/data)会持续增长,尤其是启用浏览器自动化(Playwright)和长期记忆(memories)后。官方建议的最小磁盘空间是 2GB,但这是针对“仅聊天”的极简场景。实测下来,一个中等活跃度的个人助理,一个月内就会产生 800MB+ 的日志和缓存。
验证方法(Windows & Linux 通用):
# 查看 Docker 默认存储位置的可用空间 docker system df -v | head -n 20 # 关注 "Base Directory" 下的 "Size" 和 "Available" 字段更关键的权限问题:Hermes 容器内部以 UID10000(hermes用户)运行。它需要对挂载的宿主机目录拥有读、写、执行(x)权限。在 Linux 上,这通常意味着宿主机目录的所有者 UID 必须是10000,或该目录的权限位必须包含755(即rwxr-xr-x)。在 Windows 上,由于 WSL2 的文件系统桥接,情况更复杂:WSL2 的/home/yourname目录权限由 Windows NTFS 权限映射而来,而C:\Users\YourName目录则可能被映射为777,但这恰恰是最大的陷阱——777权限在 Linux 容器内会被解释为“所有用户可写”,这违反了 Hermes 的安全设计,导致容器启动时拒绝以hermes用户身份写入,直接崩溃。
解决方案(平台通用):永远不要使用chmod -R 777!正确做法是显式声明 UID/GID:
# 在 Windows PowerShell (WSL2 后端) 或 Linux Bash 中执行 export PUID=$(id -u) export PGID=$(id -g) echo "PUID=$PUID, PGID=$PGID" # 然后在所有 docker run 命令中加入: # -e PUID=$PUID -e PGID=$PGID这个id -u命令在 Windows 的 WSL2 终端里返回的是 WSL2 发行版用户的 UID(通常是1000),在 Linux 上返回的是你的实际 UID。它确保了容器内hermes用户与宿主机用户在文件所有权上完全对齐,这是跨平台稳定性的黄金法则。
2.3 网络连通性与 DNS 解析
Hermes Agent 在启动时会向多个上游服务发起连接:模型提供商(OpenAI, Anthropic)、消息平台(Telegram, Discord)、以及可选的本地推理服务器(Ollama, vLLM)。任何一环的 DNS 解析失败,都会导致setup向导卡住或gateway run启动超时。
验证方法(Windows & Linux 通用):
# 测试基础 DNS nslookup google.com # 测试 Docker 内部 DNS(关键!) docker run --rm alpine nslookup google.com # 测试到模型 API 的连通性(模拟 Hermes 的行为) docker run --rm curlimages/curl -I https://api.openai.com/v1/modelsWindows 特殊问题:在某些企业网络或启用了 Windows Defender 防火墙的环境下,Docker Desktop 的虚拟网卡(vEthernet (DockerNAT))可能被防火墙规则拦截,导致容器内无法解析域名。一个快速诊断法是:
# 在 Windows PowerShell 中执行 Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*Docker*"} | Select-Object DisplayName, Enabled如果看到Docker Daemon或Docker NAT相关的规则被禁用,需手动启用。更稳妥的做法是,在 Docker Desktop 设置中,进入Resources > Network,勾选Use the WSL2 based engine,并确保DNS server设置为Automatic。
Linux 特殊问题:Ubuntu 22.04+ 默认使用systemd-resolved作为 DNS 解析器,其监听地址为127.0.0.53。Docker 的默认 DNS 配置有时会与之冲突。解决方法是在/etc/docker/daemon.json中强制指定 DNS:
{ "dns": ["8.8.8.8", "1.1.1.1"] }然后重启 Docker:sudo systemctl restart docker。
注意:以上所有验证,都必须在你执行任何
docker run命令之前完成。它们不是可选项,而是部署流水线的第一道质量门禁。跳过它,等于在沙上筑塔。
3. 核心部署流程:从零开始的“一次成功”实操详解
现在,我们进入最核心的部分:如何在 Windows(WSL2)和 Linux 上,第一次运行就成功启动 Hermes Agent。这里的“成功”,定义为:容器后台运行、setup向导完整执行、API 服务(8642端口)可访问、且所有日志无致命错误。我将摒弃所有“先试一下”的模糊表述,给出每一步的精确命令、预期输出、以及当它不工作时,你该看哪一行日志、查哪个配置。
3.1 创建数据目录与首次交互式初始化
这是整个部署的“心脏起搏器”。它决定了后续所有状态(API Key、配置、技能)的存续。官方文档的mkdir -p ~/.hermes是一个巨大的隐患,因为它在 Windows 上极易指向错误的位置。
安全、跨平台的创建方式:
# 1. 创建一个明确、绝对、可预测的路径 # Windows (PowerShell in WSL2): 使用 WSL2 的 home 目录 export HERMES_DATA_DIR="/home/$(whoami)/.hermes" # Linux (Bash): 同样使用 home 目录 export HERMES_DATA_DIR="$HOME/.hermes" # 2. 创建目录并设置权限(关键!) mkdir -p "$HERMES_DATA_DIR" chmod 755 "$HERMES_DATA_DIR" # 3. 验证路径是否正确(这一步不能省!) ls -ld "$HERMES_DATA_DIR" # 预期输出(Linux/WSL2): drwxr-xr-x 2 youruser yourgroup 4096 ... /home/youruser/.hermes执行首次初始化:
# 使用显式路径和 PUID/PGID,确保万无一失 docker run -it --rm \ -v "$HERMES_DATA_DIR":/opt/data \ -e PUID=$(id -u) \ -e PGID=$(id -g) \ nousresearch/hermes-agent setup预期输出与关键观察点:
- 你会看到一个清晰的 CLI 向导界面,提示你输入
OPENAI_API_KEY、ANTHROPIC_API_KEY等。 - 最关键的验证点:当向导询问
Do you want to configure a chat platform?时,选择y,然后输入你的 Telegram Bot Token。向导会立即尝试连接 Telegram API 并返回✅ Connected to Telegram!。如果这里失败,说明网络或 Token 有问题,不要继续。 - 向导完成后,它会在
$HERMES_DATA_DIR/.env中生成一个文件。立即验证:cat "$HERMES_DATA_DIR/.env" | grep -E "(OPENAI|ANTHROPIC)_API_KEY" # 应该能看到你输入的密钥(已加密存储,但字段名可见)
提示:如果你在 Windows 的 PowerShell(非 WSL2)中执行此命令,
$HERMES_DATA_DIR可能被解析为C:\Users\YourName\.hermes,而 Docker Desktop 会尝试将其挂载,但 WSL2 的文件系统桥接可能导致权限混乱。务必在 WSL2 的终端(如 Ubuntu)中执行所有命令。这是 Windows 用户最容易踩的坑,也是本指南强调“WSL2 是唯一可靠模式”的原因。
3.2 后台守护进程启动:gateway run的完整参数解析
初始化成功后,下一步是让 Hermes 作为一个持久化的服务(gateway)在后台运行。官方文档的docker run -d ... gateway run命令是骨架,但缺少了让它真正“活”起来的血肉。
生产环境推荐命令(Windows & Linux 通用):
docker run -d \ --name hermes \ --restart unless-stopped \ --memory=3g \ --cpus=2 \ --shm-size=1g \ -v "$HERMES_DATA_DIR":/opt/data \ -e PUID=$(id -u) \ -e PGID=$(id -g) \ -e HERMES_DASHBOARD=1 \ -e API_SERVER_ENABLED=true \ -e API_SERVER_HOST=0.0.0.0 \ -e API_SERVER_KEY="$(openssl rand -hex 32)" \ -e API_SERVER_CORS_ORIGINS='*' \ -p 8642:8642 \ -p 9119:9119 \ nousresearch/hermes-agent gateway run参数逐项深度解析:
--memory=3g --cpus=2: Hermes 的 Playwright(Chromium)是内存大户。1GB 是理论下限,但实测在加载复杂网页时会 OOM。3GB 是兼顾性能与资源占用的甜点值。--cpus=2确保多线程工具调用(如并发curl)不被 throttled。--shm-size=1g:这是浏览器工具(Playwright)能工作的绝对前提。Docker 默认的共享内存(shm)只有 64MB,而 Chromium 启动需要至少 512MB。不加此参数,hermes会静默失败,日志里只有一行Failed to launch browser。-e HERMES_DASHBOARD=1: 启用内置 Web 仪表盘。它不仅是 UI,更是调试核心。仪表盘会实时显示每个 profile 的状态、日志流、以及模型调用的详细 trace。-e API_SERVER_*: 这组参数开启了 Hermes 的 OpenAI 兼容 API。API_SERVER_KEY是一个强随机密钥,用于保护你的 API 端点不被未授权访问。API_SERVER_CORS_ORIGINS='*'允许任何前端(如 Open WebUI)跨域调用,生产环境应改为具体域名。-p 8642:8642 -p 9119:9119: 分别暴露 API 服务和 Dashboard 服务。注意,Dashboard 的9119端口必须与-e HERMES_DASHBOARD=1配合,否则端口虽开放,但服务不启动。
启动后验证:
# 1. 检查容器状态 docker ps -f name=hermes # 2. 查看实时日志(重点关注前10行) docker logs -f hermes | head -n 10 # 预期看到类似: # [INFO] Starting Hermes Gateway... # [INFO] Dashboard service registered and started on port 9119 # [INFO] API server listening on 0.0.0.0:8642 # 3. 验证 API 端点(在宿主机上执行) curl -s http://localhost:8642/health | jq . # 应返回 {"status":"ok","timestamp":...} # 4. 验证 Dashboard(在浏览器中打开) # http://localhost:9119 # 输入你在 setup 向导中设置的用户名/密码,即可进入仪表盘3.3 Docker Compose 部署:面向长期运维的标准化方案
对于需要长期运行、频繁升级、或管理多个 profile 的用户,docker run命令很快会变得难以维护。Docker Compose 是 Docker 官方推荐的编排工具,它用一个docker-compose.yml文件,将所有配置、网络、卷、环境变量固化下来,实现了“一次编写,处处运行”。
一个经过生产环境验证的docker-compose.yml:
version: '3.8' services: hermes: image: nousresearch/hermes-agent:latest container_name: hermes restart: unless-stopped # 资源限制,防止失控 deploy: resources: limits: memory: 4G cpus: '2.0' # 网络与端口 ports: - "8642:8642" # API Server - "9119:9119" # Dashboard # 数据卷,使用绝对路径确保跨平台 volumes: - "/home/$(whoami)/.hermes:/opt/data" # Linux/WSL2 路径 # Windows 用户注意:如果你在 WSL2 中运行,此路径有效。 # 如果你坚持在 Windows 命令行运行,请改为: # - "C:/Users/YourName/.hermes:/opt/data" # 环境变量 environment: - PUID=${PUID} - PGID=${PGID} - HERMES_DASHBOARD=1 - API_SERVER_ENABLED=true - API_SERVER_HOST=0.0.0.0 - API_SERVER_KEY=${API_SERVER_KEY} - API_SERVER_CORS_ORIGINS=* # 可选:转发特定密钥,避免写入 .env 文件 # - OPENAI_API_KEY=${OPENAI_API_KEY} # - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} # 启动命令 command: gateway run # 为未来扩展预留的网络 networks: default: driver: bridge使用流程:
# 1. 创建一个项目目录 mkdir ~/hermes-deploy && cd ~/hermes-deploy # 2. 创建 .env 文件(用于 Compose 的变量替换) cat > .env <<EOF PUID=$(id -u) PGID=$(id -g) API_SERVER_KEY=$(openssl rand -hex 32) # OPENAI_API_KEY=sk-... # ANTHROPIC_API_KEY=sk-... EOF # 3. 创建 docker-compose.yml(内容如上) # 4. 一键启动 docker compose up -d # 5. 查看日志 docker compose logs -fCompos e 的核心优势:
- 升级简单:只需
docker compose pull && docker compose up -d,旧容器自动停止,新容器无缝接管,数据卷毫发无损。 - 配置集中:所有参数都在一个 YAML 文件里,版本控制友好,团队协作无障碍。
- 多服务协同:如需添加 Ollama 作为本地模型,只需在
services下增加一个ollama服务,并在hermes的environment中配置base_url: http://ollama:11434/v1,它们会自动在同一网络中发现彼此。
4. 多 Profile 管理:一个容器,无限可能的实战策略
Hermes Agent 的多 Profile 功能,是其区别于其他 LLM Agent 的核心竞争力之一。它允许你在同一个容器内,运行多个完全隔离的“数字分身”:一个用于工作(连接公司 Slack、访问内部知识库),一个用于学习(连接 GitHub、运行代码沙盒),一个用于生活(连接 Telegram、管理待办)。官方文档提到了hermes profile create,但没告诉你何时该用 Profile,何时该用独立容器,以及Profile 之间如何安全通信。
4.1 Profile 的创建、启动与生命周期管理
所有 Profile 管理命令,都必须在容器内部执行。这是由 Hermes 的 s6-supervision 架构决定的:每个 Profile 对应一个独立的 s6 服务槽(/run/service/gateway-<name>/),只有容器内的 supervisor 才能管理它。
标准操作流程:
# 1. 创建一个新的 Profile(例如 "work") docker exec hermes hermes profile create work # 2. 启动该 Profile 的 Gateway docker exec hermes hermes -p work gateway start # 3. 查看所有 Profile 的状态 docker exec hermes hermes profile list # 输出示例: # default (running) # work (running) # 4. 查看特定 Profile 的 Gateway 状态 docker exec hermes hermes -p work gateway status # 输出示例: # Manager: s6 (container supervisor) # State: running # PID: 12345关键原理:hermes -p work gateway start这条命令,并不是在容器里开了一个新进程。它实际上是向 s6-supervisor 发送了一个信号,告诉它:“请启动/run/service/gateway-work/这个服务槽”。s6 会负责拉起一个全新的hermes gateway run进程,并将其作为子进程托管。这意味着:
- 所有 Profile 共享同一个 Python 解释器、同一个 Node.js 环境、同一个 Playwright 缓存,内存开销极小。
- 如果
workProfile 的 Gateway 因为某个网页崩溃了,s6 会在 1 秒内自动重启它,而defaultProfile 完全不受影响。 - 容器重启(
docker restart hermes)后,所有之前处于running状态的 Profile,会由 boot reconciler 自动恢复,无需人工干预。
4.2 Profile 间的网络隔离与 API 访问
这是最常被误解的一点。很多人以为,既然多个 Profile 在一个容器里,它们的 API 端口(8642)就会冲突。官方文档提到需要为每个 Profile 设置不同的API_SERVER_PORT,但这只是一种可选方案,且只适用于特定场景。
真相是:
- Dashboard 是全局的:
http://localhost:9119这个 Dashboard,可以管理容器内的所有Profile。你在 Dashboard 的左上角切换 Profile,它会自动为你加载对应 Profile 的SOUL.md、sessions/和memories/。这是最推荐、最安全的 Profile 切换方式。 - API Server 是 Profile 级别的:每个 Profile 的
gateway run进程,默认都试图绑定8642端口。如果两个 Profile 同时启动,第二个会失败。但官方提供了优雅的解决方案:让 Dashboard 成为 API 的统一入口。
推荐架构(Dashboard 代理模式):
- 只暴露 Dashboard 端口(9119):在
docker run或docker-compose.yml中,只保留-p 9119:9119,移除-p 8642:8642。 - 禁用所有 Profile 的 API Server:在每个 Profile 的
.env文件中,设置API_SERVER_ENABLED=false。 - 通过 Dashboard 的 API 代理访问:Hermes Dashboard 内置了一个反向代理,它会根据你当前选择的 Profile,将
/v1/chat/completions等请求,转发给对应 Profile 的内部 API(http://127.0.0.1:8642)。
验证方法:
- 在浏览器中打开
http://localhost:9119,登录后,切换到workProfile。 - 打开浏览器开发者工具(F12),切换到 Network 标签页。
- 在 Dashboard 的聊天框中发送一条消息。
- 观察 Network 请求,你会发现所有 API 调用的 URL 都是
http://localhost:9119/v1/...,而不是8642。这证明流量正通过 Dashboard 代理。
何时才需要独立的 API 端口?只有当你需要让外部工具(如 Open WebUI、LobeChat)直接、绕过 Dashboard地连接到某个特定 Profile 时,才需要为它分配独立端口。例如:
# 为 work Profile 分配 8643 端口 docker exec hermes bash -c 'echo "API_SERVER_ENABLED=true\nAPI_SERVER_PORT=8643" >> /opt/data/profiles/work/.env' docker exec hermes hermes -p work gateway restart # 然后在 docker-compose.yml 中添加: # - "8643:8643"但请注意,这会增加网络暴露面,且你需要为每个 Profile 单独管理端口映射,对于绝大多数用户,Dashboard 代理模式是更优解。
4.3 Profile 的数据隔离与备份策略
每个 Profile 的数据,都严格隔离在$HERMES_DATA_DIR/profiles/<name>/目录下。这意味着:
defaultProfile 的sessions/和memories/,对workProfile 完全不可见。- 你可以安全地
docker exec hermes hermes -p work profile delete,而不会影响default的任何数据。
备份策略(跨平台通用):
- 全量备份:直接
tar -czf hermes-backup-$(date +%Y%m%d).tar.gz ~/.hermes。因为所有 Profile 都在.hermes目录下,一次打包即可。 - 单 Profile 备份:
tar -czf work-profile-backup.tar.gz ~/.hermes/profiles/work - 增量备份:利用
rsync,只同步变化的文件:rsync -avz --delete ~/.hermes/ /backup/hermes/
提示:Profile 的强大之处,在于它让你可以用一套基础设施,支撑起完全不同的工作流。我自己的实践是:
default作为主脑,codingProfile 专门处理 GitHub PR Review,researchProfile 连接 arXiv 和 Zotero。它们共享同一个容器、同一个日志系统、同一个升级流程,却拥有各自独立的记忆和人格。这才是 Hermes Agent “通用性”的终极体现——它通用的不是平台,而是你的思维方式。
5. 故障排查:从docker logs到根因定位的完整链路
再完美的部署,也难免遇到问题。Hermes Agent 的日志系统非常丰富,但也因此容易让人迷失。官方文档提到了Where the logs go,但没告诉你当一条命令失败时,你应该按什么顺序、看哪些日志、查哪些配置。下面是一套我总结出的、行之有效的“五步定位法”。
5.1 容器启动即退出(Exit Code 0/1)
这是最常见、也最令人抓狂的问题。容器一闪而过,docker logs hermes一片空白。
排查链路:
第一步:看
docker run的原始输出
不要只看docker logs,要看你执行docker run命令时,终端打印的第一行错误。例如:docker: Error response from daemon: Conflict. The container name "/hermes" is already in use by container "abc123...".这说明你重复运行了,
docker rm -f hermes即可。第二步:强制查看容器的 exit 日志
docker logs只显示容器启动后的日志。如果容器在启动过程中就崩溃了,要用:docker inspect hermes | jq '.State.Error' # 或者更直接 docker events --since 1h --filter event=start --filter event=die第三步:检查数据目录权限
这是 Windows 用户的头号杀手。执行:ls -l "$HERMES_DATA_DIR" # 如果输出显示 owner 是 root 或其他 UID,说明 PUID/PGID 没生效。 # 修复:docker run 时加上 -e PUID=1000 -e PGID=1000(Linux)或 -e PUID=1000 -e PGID=1000(WSL2)第四步:检查
.env文件完整性
进入容器,检查关键配置:docker exec -it hermes bash cat /opt/data/.env | grep -E "(OPENAI|ANTHROPIC)_API_KEY" # 如果为空,说明 setup 没成功,或者你用了 -e OPENAI_API_KEY=... 覆盖了 .env,但值为空。第五步:以交互模式启动,看实时错误
这是终极手段:docker run -it --rm \ -v "$HERMES_DATA_DIR":/opt/data \ -e PUID=$(id -u) \ -e PGID=$(id -g) \ nousresearch/hermes-agent gateway run这样,所有错误都会直接打印在你的终端上,一目了然。
5.2 Dashboard 打不开(502 Bad Gateway / Connection Refused)
Dashboard 是 Hermes 的“控制中心”,打不开意味着你失去了所有可视化调试能力。
排查链路:
确认容器内 Dashboard 服务是否在运行
docker exec hermes ps aux | grep dashboard # 应该看到类似:/usr/bin/python3 /opt/hermes/dashboard.py确认 Dashboard 的端口监听状态
docker exec hermes ss -tuln | grep :9119 # 应该看到:tcp LISTEN 0 128 *:9119 *:*确认环境变量是否生效
docker exec hermes env | grep HERMES_DASHBOARD # 必须输出:HERMES_DASHBOARD=1检查 Dashboard 的 auth gate 是否被触发
如果你设置了HERMES_DASHBOARD_BASIC_AUTH_USERNAME,但忘记设置HERMES_DASHBOARD_BASIC_AUTH_PASSWORD,Dashboard 会启动失败,并在docker logs hermes的末尾报错:[ERROR] Dashboard auth provider requires HERMES_DASHBOARD_BASIC_AUTH_PASSWORD to be set.解决方案:要么补全密码,要么临时设置
HERMES_DASHBOARD_INSECURE=1(仅限测试)。
5.3 API 调用失败(401 Unauthorized / 404 Not Found)
当你用curl或 Open WebUI 调用http://localhost:8642/v1/chat/completions时,得到 401 或 404。
排查链路:
区分是 API Server 还是 Dashboard 代理的问题
- 如果你访问的是
8642端口,那就是 API Server。 - 如果你访问的是
9119端口,那就是 Dashboard 代理。
- 如果你访问的是
检查 API Server 的认证密钥
docker exec hermes env | grep API_SERVER_KEY # 确保它不为空,且长度 >= 8检查 API Server 的 CORS 配置
如果你从https://openwebui.example.com调用,而API_SERVER_CORS_ORIGINS设置为*,是允许的。但如果设置为http://localhost:3000,而你的前端是http://127.0.0.1:3000,就会被拒绝。解决方案是设置为 `http://localhost:3000,http://127.0.0.1:3