记录飞牛 ARM (OES Plus)通过 Docker 部署 Hermes Agent v.2026.06.19,并接入飞书机器人和第三方 OpenAI-compatible API 的完整过程。
# 飞牛小主机部署 Hermes Agent,并接入飞书机器人完整教程
最近尝试在飞牛小主机上部署 [Hermes Agent](https://github.com/nousresearch/hermes-agent),并通过飞书机器人实现私聊对话。整个过程并不算特别复杂,但由于 Hermes 官方镜像里缺少 Feishu/Lark 相关依赖,实际部署时会遇到一些坑。
本文记录一套已经跑通的方案:
```text
飞书客户端
↓
飞书机器人 / Feishu App
↓ WebSocket 长连接
飞牛小主机 Docker 中的 Hermes Agent
↓
第三方 OpenAI-compatible CLI Proxy
↓
真实模型服务这套方案的特点是:
1. 飞牛小主机只运行 Hermes Agent,不在本地跑大模型。
2. 模型推理交给第三方兼容 OpenAI API 的 CLI Proxy。
3. 飞书使用 WebSocket 长连接,不需要公网 Webhook。
4. 通过 Docker 自定义镜像补齐 Feishu/Lark 依赖。一、环境说明
我的部署环境如下:
设备:飞牛 ARM 小主机
系统:飞牛 OS
部署方式:Docker Compose
Hermes 版本:v2026.6.19
安装目录:/vol2/1000/Docker/hermes
模型后端:第三方 OpenAI-compatible CLI Proxy
对话入口:飞书机器人最终目录结构大致如下:
/vol2/1000/Docker/hermes
├── Dockerfile
├── docker-compose.yml
└── data
├── .env
└── config.yaml二、准备工作
部署前需要准备以下信息:
1. 飞书 App ID
2. 飞书 App Secret
3. 第三方 CLI Proxy 的 API 地址
4. 第三方 CLI Proxy 的 API Key
5. 第三方 CLI Proxy 支持的模型名本文所有涉及隐私的内容都用占位符表示,例如:
填写你的飞书App_ID
填写你的飞书App_Secret
填写你的CLIProxy端口
填写你的CLIProxy_API_Key
填写你的模型名实际部署时替换成自己的内容即可。
三、飞书开放平台配置
先进入飞书开放平台,创建一个企业自建应用。
1. 创建企业自建应用
进入:
飞书开放平台
→ 开发者后台
→ 创建企业自建应用创建完成后,在应用后台找到:
凭证与基础信息复制:
App ID
App Secret注意不要把 Verification Token 或 Encrypt Key 当成 App Secret。
2. 启用机器人能力
进入:
应用能力
→ 机器人启用机器人能力。
启用后,飞书里才能把这个应用当作机器人私聊或拉入群聊。
3. 配置飞书权限
进入:
权限管理添加以下权限:
im:message
im:message:send_as_bot
im:resource
im:chat
im:chat:readonly如果后续日志中出现类似错误:
Access denied. One of the following scopes is required:
[im:chat:readonly, im:chat, im:chat:read]则继续补充:
im:chat:read建议顺手添加这些推荐权限:
im:message.reactions:readonly
admin:app.info:readonly
contact:user.id:readonly
application:bot.basic_info:read4. 配置事件订阅
进入:
事件与回调连接方式选择:
长连接 / WebSocket订阅事件:
im.message.receive_v1如果后续需要使用飞书交互卡片,再订阅:
card.action.trigger这里推荐使用 WebSocket 长连接,而不是 Webhook。因为 WebSocket 模式是 Hermes 主动连接飞书,不需要你暴露公网地址,也不需要配置 Cloudflare Tunnel。
5. 发布应用版本
飞书权限配置完成后,一定要发布版本:
版本管理与发布
→ 创建版本
→ 发布如果企业需要管理员审批,要等审批通过后权限才会真正生效。
这是一个很容易遗漏的步骤。仅仅添加权限但不发布,Hermes 仍然可能因为权限不足而报错。
四、创建 Hermes 目录
SSH 进入飞牛小主机,执行:
mkdir -p /vol2/1000/Docker/hermes/data
cd /vol2/1000/Docker/hermes五、创建 .env 文件
执行:
cat > /vol2/1000/Docker/hermes/data/.env <<'EOF'
# ===== Feishu / Lark 配置 =====
# 中国飞书用 feishu,国际版 Lark 用 lark
FEISHU_APP_ID=填写你的飞书App_ID
FEISHU_APP_SECRET=填写你的飞书App_Secret
FEISHU_DOMAIN=feishu
FEISHU_CONNECTION_MODE=websocket
# 测试阶段先开放,确认能用后建议改为白名单
GATEWAY_ALLOW_ALL_USERS=true
# 群聊策略:测试阶段用 open;正式使用建议改 allowlist
FEISHU_GROUP_POLICY=open
# 群聊中是否必须 @ 机器人
FEISHU_REQUIRE_MENTION=true
# ===== Dashboard 配置 =====
HERMES_DASHBOARD=1
HERMES_DASHBOARD_BASIC_AUTH_USERNAME=admin
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=填写一个强密码
HERMES_DASHBOARD_BASIC_AUTH_SECRET=填写一串很长的随机字符串
EOF可以用下面命令生成随机字符串:
head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n'生成后填入:
HERMES_DASHBOARD_BASIC_AUTH_SECRET六、创建 config.yaml
这里配置 Hermes 使用第三方 OpenAI-compatible API。
执行:
cat > /vol2/1000/Docker/hermes/data/config.yaml <<'EOF'
model:
provider: custom
model: "填写你的模型名"
base_url: "http://host.docker.internal:填写你的CLIProxy端口/v1"
api_key: "填写你的CLIProxy_API_Key"
group_sessions_per_user: true
EOF示例:
model:
provider: custom
model: "gpt-5.5"
base_url: "http://host.docker.internal:3000/v1"
api_key: "sk-xxxxxxxxxxxxxxxx"
group_sessions_per_user: true注意:
1. base_url 建议明确写到 /v1。
2. 不要写成 /v1/chat/completions。
3. 如果 CLI Proxy 跑在飞牛宿主机上,容器内不要写 localhost。
4. 配合 docker-compose.yml 里的 extra_hosts 使用 host.docker.internal。容器内的 localhost 指的是容器自己,不是飞牛宿主机。
七、创建自定义 Dockerfile
实际部署时会遇到一个关键问题:
Hermes 官方 Docker 镜像里可能缺少 Feishu/Lark 适配器需要的依赖:
lark-oapi
websockets
aiohttp如果缺少这些依赖,日志里会出现类似:
Feishu: lark-oapi not installed or FEISHU_APP_ID/SECRET not set
No adapter available for feishu
No adapter could be created for any of the configured platform(s)另外,Hermes 镜像使用的是自己的虚拟环境:
/opt/hermes/.venv所以不能简单地在容器里 pip install,需要把依赖装进 Hermes 自己的 venv 里。
创建 Dockerfile:
cat > /vol2/1000/Docker/hermes/Dockerfile <<'EOF'
FROM nousresearch/hermes-agent:v2026.6.19
USER root
RUN sed -i \
-e 's|http://deb.debian.org/debian-security|https://mirrors.tuna.tsinghua.edu.cn/debian-security|g' \
-e 's|http://security.debian.org/debian-security|https://mirrors.tuna.tsinghua.edu.cn/debian-security|g' \
-e 's|http://deb.debian.org/debian|https://mirrors.tuna.tsinghua.edu.cn/debian|g' \
/etc/apt/sources.list /etc/apt/sources.list.d/*.sources 2>/dev/null || true && \
apt-get update && \
apt-get install -y --no-install-recommends python3-pip ca-certificates && \
VENV_SITE=$(/opt/hermes/.venv/bin/python3 -c "import sysconfig; print(sysconfig.get_paths()['purelib'])") && \
/usr/bin/python3 -m pip install --break-system-packages --no-cache-dir \
--target "$VENV_SITE" \
-i https://pypi.tuna.tsinghua.edu.cn/simple \
pip setuptools wheel && \
/opt/hermes/.venv/bin/python3 -m pip install --no-cache-dir \
-i https://pypi.tuna.tsinghua.edu.cn/simple \
--timeout 120 \
lark-oapi \
websockets \
aiohttp && \
/opt/hermes/.venv/bin/python3 -c "import lark_oapi, websockets, aiohttp; print('Feishu deps OK')" && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
EOF这里同时做了两件事:
1. 把 Debian 官方源替换为清华源,加快构建速度。
2. 把 lark-oapi、websockets、aiohttp 安装进 Hermes 的虚拟环境。如果清华源较慢,可以把:
https://mirrors.tuna.tsinghua.edu.cn替换成:
https://mirrors.ustc.edu.cn八、创建 docker-compose.yml
执行:
cat > /vol2/1000/Docker/hermes/docker-compose.yml <<'EOF'
services:
hermes:
build:
context: .
dockerfile: Dockerfile
image: hermes-agent-feishu:v2026.6.19
container_name: hermes
restart: unless-stopped
command: gateway run
volumes:
- /vol2/1000/Docker/hermes/data:/opt/data
env_file:
- /vol2/1000/Docker/hermes/data/.env
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "9119:9119"
shm_size: "1g"
environment:
- TZ=Asia/Shanghai
EOF说明:
1. 使用 build 构建自定义镜像。
2. data 目录挂载到 /opt/data。
3. .env 中保存飞书和 Dashboard 环境变量。
4. host.docker.internal 用于容器访问宿主机上的 CLI Proxy。
5. 9119 是 Dashboard 端口。九、检查 Compose 配置
执行:
cd /vol2/1000/Docker/hermes
docker compose config如果没有报错,再继续。
如果出现:
yaml: line 4: found character that cannot start any token通常是 docker-compose.yml 中出现了 Tab 缩进。YAML 只能用空格,不能用 Tab。
本文使用 cat > docker-compose.yml <<'EOF' 的方式生成文件,可以避免大多数格式问题。
十、构建并启动
执行:
cd /vol2/1000/Docker/hermes
docker compose down
docker compose build --no-cache --progress=plain
docker compose up -d查看容器状态:
docker compose ps查看实时日志:
docker logs -f hermes构建成功时,应该能看到:
Feishu deps OK十一、验证 Feishu 依赖
执行:
docker exec -it hermes sh -lc '/opt/hermes/.venv/bin/python3 - <<PY
import importlib.util
for m in ["lark_oapi", "websockets", "aiohttp"]:
print(m, "OK" if importlib.util.find_spec(m) else "MISSING")
PY'正常输出应该是:
lark_oapi OK
websockets OK
aiohttp OK如果还是 MISSING,说明自定义镜像没有生效。检查:
docker compose config | sed -n '1,80p'应能看到类似:
build:
context: /vol2/1000/Docker/hermes
dockerfile: Dockerfile
image: hermes-agent-feishu:v2026.6.19十二、验证飞书长连接
查看最近 2 分钟日志:
docker logs --since 2m hermes | grep -Ei "feishu|lark|chat|error|warning|access"如果看到类似:
[Lark] connected to wss://msg-frontier.feishu.cn/...说明飞书长连接成功。
如果看到:
No adapter available for feishu
lark-oapi not installed
websockets not installed
FEISHU_APP_ID/SECRET not set说明 Feishu 依赖或 .env 配置还有问题。
如果看到:
Access denied
im:chat:readonly
im:chat
im:chat:read说明飞书应用权限没有补全,需要回飞书开放平台补权限,并重新发布应用版本。
十三、飞书客户端测试
打开飞书,找到机器人私聊窗口,发送:
/status如果机器人有回复,说明 Hermes 命令系统已经正常。
然后发送普通对话:
你好,简单介绍一下你自己如果能正常回答,说明完整链路已经打通:
飞书客户端
↓
飞书机器人
↓
Hermes Feishu Gateway
↓
Hermes Agent
↓
第三方 CLI Proxy
↓
模型服务
↓
飞书客户端十四、设置 Home Channel
飞书私聊机器人发送:
/sethome成功后,这个飞书私聊窗口会成为 Hermes 的默认通知频道。
Home Channel 主要用于:
1. 定时任务结果推送
2. 跨平台消息推送
3. Hermes 主动通知如果 /sethome 无效,可以尝试:
/set-home不同版本命令可能略有差异,以机器人提示为准。
十五、测试完成后开启白名单
测试阶段我们配置了:
GATEWAY_ALLOW_ALL_USERS=true这表示允许所有能接触到机器人的用户使用 Hermes。长期使用不建议这样配置。
1. 获取自己的飞书 open_id
推荐从飞书开放平台事件日志中获取:
开发者后台
→ 你的应用
→ 事件与回调
→ 事件日志
→ 找 im.message.receive_v1
→ 找 sender.sender_id.open_id形如:
ou_xxxxxxxxxxxxxxxxx这个 ou_xxx 就是飞书用户 open_id。
2. 修改 .env
执行:
nano /vol2/1000/Docker/hermes/data/.env把测试配置:
GATEWAY_ALLOW_ALL_USERS=true
FEISHU_GROUP_POLICY=open改成:
GATEWAY_ALLOW_ALL_USERS=false
FEISHU_ALLOWED_USERS=填写你的飞书open_id
FEISHU_GROUP_POLICY=allowlist
FEISHU_REQUIRE_MENTION=true如果允许多个用户,用英文逗号分隔:
FEISHU_ALLOWED_USERS=ou_xxx,ou_yyy,ou_zzz重启 Hermes:
cd /vol2/1000/Docker/hermes
docker compose restart再到飞书发送:
/status如果还能回复,说明白名单配置成功。
十六、访问 Dashboard
浏览器打开:
http://飞牛IP:9119登录账号密码来自 .env:
HERMES_DASHBOARD_BASIC_AUTH_USERNAME
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD建议只在局域网、Tailscale 或 ZeroTier 内访问 Dashboard,不要直接暴露到公网。
十七、备份当前可用配置
部署成功后建议立即备份:
cd /vol2/1000/Docker/hermes
tar -czf hermes-feishu-working-$(date +%F-%H%M%S).tar.gz \
docker-compose.yml \
Dockerfile \
data也可以单独备份数据目录:
cp -a /vol2/1000/Docker/hermes/data \
/vol2/1000/Docker/hermes/data_backup_$(date +%F-%H%M%S)十八、后续升级方式
不要直接使用 latest,建议固定版本,例如:
FROM nousresearch/hermes-agent:v2026.6.19升级前先备份:
cd /vol2/1000/Docker/hermes
tar -czf hermes-before-upgrade-$(date +%F-%H%M%S).tar.gz \
docker-compose.yml \
Dockerfile \
data然后修改 Dockerfile 里的 Hermes 版本号:
nano Dockerfile重新构建:
docker compose down
docker compose build --no-cache --progress=plain
docker compose up -d
docker logs -f hermes如果升级失败,把 Dockerfile 里的版本号改回旧版本,再重新构建。
十九、常见问题整理
1. 飞书机器人完全没反应
查看日志:
docker logs --since 2m hermes | grep -Ei "feishu|lark|adapter|error|warning|access"重点看有没有:
No adapter available for feishu
FEISHU_APP_ID/SECRET not set
lark-oapi not installed
websockets not installed常见原因:
1. .env 没有被 docker-compose.yml 加载。
2. FEISHU_APP_ID 或 FEISHU_APP_SECRET 写错。
3. 飞书 App 没有启用机器人能力。
4. 事件订阅没有选择 WebSocket 长连接。
5. 没有订阅 im.message.receive_v1。
6. 应用权限没有发布或审批。
7. Hermes 镜像缺少 Feishu 依赖。2. 日志提示 lark-oapi MISSING
验证命令:
docker exec -it hermes sh -lc '/opt/hermes/.venv/bin/python3 - <<PY
import importlib.util
for m in ["lark_oapi", "websockets", "aiohttp"]:
print(m, "OK" if importlib.util.find_spec(m) else "MISSING")
PY'如果显示:
lark_oapi MISSING
websockets MISSING
aiohttp MISSING说明 Feishu/Lark 依赖没有装进去。
解决方式是使用本文的自定义 Dockerfile,重新构建镜像。
3. 构建时提示 No module named pip
如果看到:
/opt/hermes/.venv/bin/python3: No module named pip说明 Hermes 自带的虚拟环境里没有 pip。
不能简单执行:
python3 -m pip install ...应该使用本文 Dockerfile 的方式:
1. 先用系统 Python 的 pip。
2. 找到 /opt/hermes/.venv 的 site-packages。
3. 把 pip 和依赖安装到 Hermes 的 venv 里。4. 日志提示 Access denied im:chat
如果看到:
Access denied
One of the following scopes is required:
[im:chat:readonly, im:chat, im:chat:read]说明飞书应用缺少聊天信息读取权限。
解决方法:
飞书开放平台
→ 你的应用
→ 权限管理
→ 添加 im:chat、im:chat:readonly、im:chat:read
→ 创建版本
→ 发布
→ 等待审批通过
→ 重启 Hermes重启:
cd /vol2/1000/Docker/hermes
docker compose restart5. /status 能回复,但普通聊天不回复
这通常说明飞书链路正常,但模型后端有问题。
检查配置:
cat /vol2/1000/Docker/hermes/data/config.yaml应类似:
model:
provider: custom
model: "填写你的模型名"
base_url: "http://host.docker.internal:填写端口/v1"
api_key: "填写API_Key"容器内测试 CLI Proxy:
docker exec -it hermes sh -lc 'curl -s http://host.docker.internal:填写端口/v1/chat/completions \
-H "Authorization: Bearer 填写API_Key" \
-H "Content-Type: application/json" \
-d "{\"model\":\"填写模型名\",\"messages\":[{\"role\":\"user\",\"content\":\"回复 TEST_OK\"}],\"stream\":false}"'如果这里不通,说明 Hermes 容器无法访问模型后端。
6. Dockerfile 构建很慢
本文默认使用清华源:
https://mirrors.tuna.tsinghua.edu.cn如果仍然很慢,可以替换成中科大源:
https://mirrors.ustc.edu.cn7. 日志里有 raft CLI not found
如果看到:
WARNING hermes_plugins.raft_platform.adapter: [raft] raft CLI not found可以暂时忽略。这个 warning 和飞书对话无关,不影响 Hermes 正常使用。
8. 日志里有 config.yaml has empty section(s)
如果看到:
config.yaml has empty section(s)一般不是致命错误,说明配置文件里有空字段。只要飞书和模型能正常对话,可以暂时忽略。
二十、安全提醒
不要把下面这些信息公开到博客、论坛或截图中:
FEISHU_APP_SECRET
CLI Proxy API Key
Dashboard 密码
飞书日志里的 access_key
飞书日志里的完整连接 URL如果这些信息已经被公开,建议立即:
1. 重置飞书 App Secret。
2. 重置 CLI Proxy API Key。
3. 修改 Dashboard 密码。
4. 重新生成 HERMES_DASHBOARD_BASIC_AUTH_SECRET。总结
这次部署的关键点主要有三个:
1. 飞书选择 WebSocket 长连接模式,不需要公网 Webhook。
2. Hermes 官方镜像可能缺少 Feishu/Lark 依赖,需要自定义 Dockerfile。
3. 测试成功后必须关闭 GATEWAY_ALLOW_ALL_USERS,改用 FEISHU_ALLOWED_USERS 白名单。最终跑通后,飞书机器人就可以作为一个比较方便的个人 AI 助手入口:
飞书私聊机器人
→ Hermes Agent
→ 第三方 OpenAI-compatible API
→ 模型服务对于飞牛 ARM 小主机来说,这种部署方式比较合适:小主机只负责常驻 Hermes 和飞书网关,不负责本地大模型推理,因此资源压力相对较小,也更容易长期稳定运行。