我是AI时代的无业游民,我游荡在现实与意念之间


飞牛NAS部署Hermes AI Agent:接入DeepSeek、微信与公网访问速查手册

An abstract conceptual illustration of a fragile b

什么时候用这份手册

你有一台飞牛NAS(或任意能跑 Docker 的 x86 小主机),想在上面跑一个能接入微信、能调用 DeepSeek 这类大模型、还能从公网访问的 AI Agent,但不想从头读一遍官方文档。这份手册按"排错频率"从高到低组织,30 秒内定位到你要的那条命令或配置。前置知识只需要:会用 SSH、看得懂 YAML、知道什么是环境变量。


① 重构前的症状:为什么直接抄教程会翻车

大多数人第一次部署 Hermes 的写法是这样的——把官方 compose 文件原样复制,改个端口就 up:

# 症状版 docker-compose.yml
services:
  hermes:
    image: hermes-agent:latest
    ports:
      - "8080:8080"
    environment:
      - DEEPSEEK_API_KEY=sk-xxxx
      - WECHAT_TOKEN=xxxx

跑起来后典型报错三连:

现象复现方式表面原因
容器启动即退出docker logs hermes 看到 permission denied数据卷属主不对
微信回调 401公网访问 /wechat/callback 返回 401token 校验路径没对齐
公网能开页面但 Agent 无响应内网正常、外网超时反向代理没转发 WebSocket

这三个症状看起来无关,其实根因是同一个:你把"能跑"当成了"配置正确"。


② 问题诊断:根因不在命令,在配置边界

  • 权限问题:Hermes 容器内以非 root 用户(常见 UID 1000)写 /data,而 NAS 上挂载的目录默认属主是 root。permission denied 不是镜像的错,是卷的错。
  • 微信回调问题:微信公众平台的回调校验要求 URL、Token、EncodingAESKey 三者与代码侧完全一致,且必须走 80/443 端口。你映射到 8080 再套一层路径,校验就过不了。
  • 公网无响应:Agent 的流式输出走 SSE/WebSocket,普通反向代理默认只转发 HTTP 短连接,长连接被掐断,表现就是"页面打开了但一直转圈"。

一句话:NAS 部署的难点从来不是"装软件",而是"把内网服务安全地暴露成一个符合第三方协议要求的端点"。


③ 重构后的写法:完整对照

关键改动 1:卷权限显式声明

services:
  hermes:
    image: hermes-agent:latest
    user: "1000:1000"          # 关键:与宿主机目录属主对齐
    volumes:
      - ./data:/data           # 先在宿主机 chown -R 1000:1000 ./data
    environment:
      - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}   # 用 .env,别硬编码
      - DEEPSEEK_BASE_URL=https://api.deepseek.com
      - DEEPSEEK_MODEL=deepseek-chat

注意:user 字段和 chown 必须同时做,只做一样仍然会失败。

关键改动 2:微信回调走独立反代,别复用主端口

# 微信回调专用 server 块,必须 443
server {
    listen 443 ssl;
    server_name wx.yourdomain.com;
    location /wechat/callback {
        proxy_pass http://127.0.0.1:8080/wechat/callback;
        proxy_set_header Host $host;
    }
}

注意:微信后台填的 URL 必须与 server_name + location 完全一致,多一个斜杠都会校验失败。

关键改动 3:Agent 流式接口补长连接头

location /api/ {
    proxy_pass http://127.0.0.1:8080/api/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";   # WebSocket 必需
    proxy_buffering off;                      # SSE 必需
    proxy_read_timeout 3600s;
}

关键改动 4:公网访问优先用隧道而非端口映射

家庭宽带多数没有固定公网 IP,直接端口映射既不稳定也不安全。更稳的做法是用 Cloudflare Tunnel 或 frp 这类内网穿透,把 443 出口交给隧道服务:

cloudflared tunnel --url http://127.0.0.1:8080

注意:隧道方案下微信回调域名要指向隧道分配的域名,且需在微信后台重新校验一次。


④ 收益与代价

维度症状版重构版
首次跑通时间看似 5 分钟,排错 2 小时配置 20 分钟,一次通过
微信回调成功率经常 401稳定
公网流式响应超时/截断正常
安全暴露面全端口映射仅隧道/443
复杂度代价低中(多一层反代/隧道)

代价很明确:你多维护了一个反向代理或隧道进程,多了一个域名和证书。对于只想内网自用的场景,这部分是纯负担。


⑤ 适用边界与检查清单

不该这么改的时候:纯内网自用、不接微信、不需要公网访问——那就只需要改动 1(卷权限),其余全部省略。别为了"看起来专业"给自己加运维债。

上线前检查清单:

  • 宿主机 data 目录属主 = 容器 user 的 UID
  • API Key 走 .env,.env 已加入 .gitignore
  • 微信后台的 URL / Token / AESKey 与配置逐字符核对
  • 反代对 /api/ 关闭了 proxy_buffering
  • 公网入口只暴露 443,8080 不对公网开放
  • 隧道/证书到期时间已记录

面试/作业常被追问的点:为什么 SSE 需要 proxy_buffering off?(因为缓冲会攒够一批才下发,破坏流式的"逐字返回"语义。)为什么微信回调必须 443?(平台侧校验只认标准端口。)能答上这两条,说明你是真部署过,而不是背命令。

Logo

更多推荐