Hermes Agent 安装与飞书打通复盘
目录 ▾
这篇是一次完整的实操记录:从一台腾讯云 Ubuntu 服务器开始,完成 Hermes Agent 安装、Dashboard 域名映射、HTTPS、基础安全加固,再到飞书机器人接入、Gateway 常驻运行,以及群聊里通过 @ 机器人触发回复。
为方便后续分享或发布,本文做了脱敏处理:
- 真实域名统一写成
hermes.example.com - 真实服务器 IP 统一写成
203.0.113.10 - 本地 SSH Host alias 统一写成
tx_hermes - 真实主机名统一写成
cloud-ubuntu - App Secret、密码、Token 等敏感值只保留占位符
整个过程最后形成的结果是:
- Hermes Dashboard 可通过
https://hermes.example.com访问 - Dashboard 走 HTTPS,并由 Nginx Basic Auth 保护
- Hermes 后端只监听本机
127.0.0.1:9119,不直接暴露公网 - Nginx 负责反向代理和 WebSocket 转发
- fail2ban 已开启,防止 Basic Auth 爆破
- Hermes Gateway 已作为 systemd 服务常驻运行
- 飞书/Lark 长连接已建立
- 私聊机器人可回复
- 群聊中 @ 机器人可回复
1. SSH 登录服务器
本地已经有 SSH key,服务器是腾讯云 Ubuntu,IP 为:
203.0.113.10
本地 ~/.ssh/config 使用了类似配置:
Host tx_hermes
HostName 203.0.113.10
User root
Port 22
IdentityFile ~/.ssh/id_rsa
因此可以直接:
ssh tx_hermes
或者显式指定:
ssh -i ~/.ssh/id_rsa -p 22 root@203.0.113.10
服务器环境确认:
Ubuntu 24.04.4 LTS
user: root
hostname: cloud-ubuntu
2. 安装 Hermes Agent
安装来自官方仓库:
NousResearch/hermes-agent
安装命令:
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- --skip-setup
安装完成后的关键路径:
Code: /usr/local/lib/hermes-agent
Command: /usr/local/bin/hermes
Config: /root/.hermes/config.yaml
Env: /root/.hermes/.env
Data: /root/.hermes/cron, sessions, logs
随后补了一些基础依赖,并跑了一次 doctor:
apt-get update
apt-get install -y ripgrep ffmpeg
hermes doctor --fix
hermes doctor
3. 初始化 Hermes 配置
通过:
hermes setup
完成基本配置。
这次大体选择是:
- Terminal backend:保持当前 local
- Messaging platforms:后续配置飞书
- Browser provider:Local Browser
- Image generation:Skip
- TTS:Microsoft Edge TTS
- Vision backend:Auto
- Search provider:可先用默认或免费方案
配置完成后,Hermes 提示主要文件在:
/root/.hermes/config.yaml
/root/.hermes/.env
启动本地 Dashboard 的基础命令是:
hermes dashboard --host 127.0.0.1 --port 9119 --no-open --skip-build
4. Dashboard systemd 常驻
为了稳定运行,创建了 systemd 服务:
/etc/systemd/system/hermes-dashboard.service
核心内容:
[Unit]
Description=Hermes Agent Dashboard
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/root
Environment=HOME=/root
ExecStart=/usr/local/bin/hermes dashboard --host 127.0.0.1 --port 9119 --no-open --skip-build
Restart=always
RestartSec=5
TimeoutStopSec=15
KillMode=mixed
[Install]
WantedBy=multi-user.target
启动:
systemctl daemon-reload
systemctl enable hermes-dashboard
systemctl start hermes-dashboard
确认:
systemctl status hermes-dashboard
ss -ltnp | grep 9119
期望看到:
127.0.0.1:9119
也就是说,Hermes Dashboard 后端只监听本机端口,不直接暴露公网。
5. 绑定域名与 HTTPS
域名:
hermes.example.com
DNS 指向服务器:
203.0.113.10
安装 Nginx 和 Certbot:
apt-get update
apt-get install -y nginx apache2-utils certbot python3-certbot-nginx
申请证书:
certbot --nginx -d hermes.example.com
证书路径:
/etc/letsencrypt/live/hermes.example.com/fullchain.pem
/etc/letsencrypt/live/hermes.example.com/privkey.pem
Certbot 会自动启用续期 timer。
6. Nginx 反向代理
Nginx 站点配置位于:
/etc/nginx/sites-available/hermes.example.com
核心逻辑是:
server {
server_name hermes.example.com;
client_max_body_size 50m;
auth_basic "Hermes Dashboard";
auth_basic_user_file /etc/nginx/.htpasswd-hermes;
location / {
proxy_pass http://127.0.0.1:9119;
proxy_http_version 1.1;
proxy_set_header Host 127.0.0.1:9119;
proxy_set_header Origin http://127.0.0.1:9119;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/hermes.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hermes.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = hermes.example.com) {
return 301 https://$host$request_uri;
}
listen 80;
server_name hermes.example.com;
return 404;
}
这里有一个关键点:
proxy_set_header Origin http://127.0.0.1:9119;
最初 Dashboard 页面能打开,但 Chat 区域显示:
Chat connection interrupted (code 1006)
events feed disconnected
Nginx 日志里 /api/events 和 /api/pty 返回 403。Hermes 日志显示:
origin_mismatch origin=https://hermes.example.com bound=127.0.0.1
原因是 Hermes Dashboard 以 127.0.0.1 绑定时,会校验 WebSocket 的 Host/Origin。浏览器从公网域名发起 WebSocket,Origin 是 https://hermes.example.com,后端不认。
解决方式是在 Nginx 反代层把 Origin 改成后端绑定地址。这样后端仍只监听本地端口,公网入口仍只有 Nginx。
验证 WebSocket 正常时,应该能看到:
101 Switching Protocols
7. Dashboard Basic Auth
使用 Nginx Basic Auth 保护入口:
htpasswd -c /etc/nginx/.htpasswd-hermes <username>
如果遇到 Nginx 500,并且 error log 里有:
open() "/etc/nginx/.htpasswd-hermes" failed (13: Permission denied)
修复权限:
chgrp www-data /etc/nginx/.htpasswd-hermes
chmod 640 /etc/nginx/.htpasswd-hermes
systemctl reload nginx
注意:密码不要写进文档、代码仓库或聊天记录里。已经明文出现过的密码,应该视为已泄露并尽快更换。
8. 防爆破:fail2ban
为了防止 Basic Auth 被爆破,安装 fail2ban:
apt-get install -y fail2ban
新增:
/etc/fail2ban/jail.d/nginx-hermes-auth.conf
内容:
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 10m
bantime = 1h
backend = auto
启动:
systemctl enable fail2ban
systemctl restart fail2ban
查看状态:
fail2ban-client status
fail2ban-client status nginx-http-auth
当前策略是:
10 分钟内错误 5 次,封禁 1 小时
常用命令:
fail2ban-client status nginx-http-auth
fail2ban-client banned
fail2ban-client set nginx-http-auth unbanip 1.2.3.4
9. 安全性判断
当前架构是:
Internet
-> HTTPS / Nginx / Basic Auth / fail2ban
-> 127.0.0.1:9119 Hermes Dashboard
优点:
- 只有 80/443 暴露公网
- Dashboard 后端不直接暴露公网
- 有 HTTPS
- 有 Basic Auth
- 有 fail2ban 防爆破
- WebSocket 已正常转发
主要风险:
- Hermes 是 Agent 控制台,不是普通后台,权限很大
- 当前服务以 root 运行,安全边界较薄
- Basic Auth 没有 MFA
- 如果密码泄露,攻击者可能获得服务器级操作能力
更安全的长期方案:
- 最安全:不开放公网,只走 SSH Tunnel 或 Tailscale
- 更适合公网:Cloudflare Access / Zero Trust + Nginx
- 当前方案:适合个人低频使用,但建议强密码、限流、定期看日志
10. 配置飞书 / Lark
Hermes 支持 Feishu / Lark 作为消息入口。
飞书配置文件主要是:
/root/.hermes/.env
/root/.hermes/config.yaml
当前关键配置:
FEISHU_APP_ID=cli_xxx
FEISHU_APP_SECRET=***
FEISHU_DOMAIN=feishu
FEISHU_ALLOW_ALL_USERS=true
FEISHU_GROUP_POLICY=open
FEISHU_REQUIRE_MENTION=true
config.yaml 中有:
platforms:
feishu:
enabled: true
飞书后台需要做的事:
- 创建自建应用
- 启用 Bot 能力
- 配置 App ID / App Secret
- 事件订阅启用
im.message.receive_v1 - 连接方式使用长连接 WebSocket
- 发布应用版本
- 把机器人添加到私聊或群聊
推荐权限:
im:message
im:message:send_as_bot
im:resource
im:chat
im:chat:readonly
更完整功能可加:
im:message.reactions:readonly
admin:app.info:readonly
contact:user.id:readonly
11. Gateway 常驻运行
最初执行:
hermes gateway restart
但日志提示:
Cannot restart gateway as a service — linger is not enabled.
The gateway user service requires linger to function on headless servers.
因此改为安装 system-level service:
hermes gateway install --system --run-as-user root --start-now --force
生成服务:
/etc/systemd/system/hermes-gateway.service
确认:
systemctl status hermes-gateway
hermes gateway status --system
正常状态:
hermes-gateway.service active running
enabled
日志里看到:
[Lark] connected to wss://msg-frontier.feishu.cn/ws/v2 ...
这说明 Hermes Gateway 已经通过飞书开放平台长连接在线。
常用命令:
systemctl restart hermes-gateway
systemctl status hermes-gateway
journalctl -u hermes-gateway -f
hermes gateway status --system
12. 私聊与群聊响应策略
Hermes 飞书集成的默认行为:
- 私聊:收到消息就回复
- 群聊:默认只有 @ 机器人时才回复
这次最终设置为:
FEISHU_ALLOW_ALL_USERS=true
FEISHU_GROUP_POLICY=open
FEISHU_REQUIRE_MENTION=true
含义:
- 任何人都可以和机器人交互
- 群聊里必须 @ 机器人
- 不 @ 的群消息不会主动处理
如果想更严格,只允许指定用户:
FEISHU_GROUP_POLICY=allowlist
FEISHU_ALLOWED_USERS=ou_xxx,ou_yyy
FEISHU_REQUIRE_MENTION=true
如果想彻底关闭群聊:
FEISHU_GROUP_POLICY=disabled
当前个人使用场景下,先全开是可以的。后续如果机器人进入多人群,建议改成 allowlist。
13. /set-home 是什么
/set-home 的作用是把当前飞书聊天设为 Hermes 的默认通知群。
它主要用于:
- 定时任务结果发送
- 后台任务完成通知
- cron job 输出
- 没有明确会话时的默认回传位置
它不是私聊或群聊 @ 回复的必要条件。
如果只是:
@机器人 你好
不需要 /set-home。
如果希望某个群作为 Hermes 的默认通知群,可以在那个群里发:
/set-home
设置后类似保存:
FEISHU_HOME_CHANNEL=oc_xxx
14. 最终检查清单
Dashboard:
systemctl status hermes-dashboard
ss -ltnp | grep 9119
curl -I https://hermes.example.com
Nginx:
nginx -t
systemctl status nginx
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
fail2ban:
fail2ban-client status nginx-http-auth
Gateway:
systemctl status hermes-gateway
hermes gateway status --system
journalctl -u hermes-gateway -f
飞书:
私聊机器人:发送“你好”
群聊中:@机器人 你好
如果日志出现:
[Lark] connected to wss://msg-frontier.feishu.cn/ws/v2 ...
说明飞书长连接已经在线。
15. 这次踩过的坑
WebSocket 403
现象:
Chat connection interrupted (code 1006)
events feed disconnected
原因:
origin_mismatch origin=https://hermes.example.com bound=127.0.0.1
解决:
proxy_set_header Origin http://127.0.0.1:9119;
Nginx Basic Auth 权限错误
现象:
open() "/etc/nginx/.htpasswd-hermes" failed (13: Permission denied)
解决:
chgrp www-data /etc/nginx/.htpasswd-hermes
chmod 640 /etc/nginx/.htpasswd-hermes
systemctl reload nginx
Gateway restart 不生效
现象:
Cannot restart gateway as a service — linger is not enabled.
解决:
hermes gateway install --system --run-as-user root --start-now --force
群聊 @ 不回复
可能原因:
- 飞书应用没有发布新版
- 没订阅
im.message.receive_v1 - 机器人没进群
- 群聊策略还是 allowlist
- 没有 @ 机器人
当前推荐配置:
FEISHU_GROUP_POLICY=open
FEISHU_REQUIRE_MENTION=true
FEISHU_ALLOW_ALL_USERS=true
16. 后续建议
短期:
- 换一个新的强密码
- 定期查看 Nginx 和 fail2ban 日志
- 保持
9119只监听127.0.0.1
中期:
- 把 Hermes 从 root 用户迁移到普通用户
- 给 Dashboard 加 Cloudflare Access 或 Tailscale
- 如果多人使用飞书机器人,改成 allowlist
长期:
- 把这套安装流程沉淀成脚本
- 定期备份
/root/.hermes/config.yaml和/root/.hermes/.env - 把飞书 App 权限保持在最小可用范围
这次最终的可用状态是:Dashboard 能稳定访问,飞书 Gateway 已常驻,飞书私聊和群聊 @ 都具备回复条件。