Hermes Agent Docker 部署实战:VPS 上 24/7 运行的完整方案

从零搭建 Hermes Agent Docker 生产环境:Docker Compose 完整配置、6 种终端后端对比、VPS 选型与成本分析、反向代理与安全加固、Bitwarden 密钥管理,附踩坑清单和 8 问 FAQ。

Hermes Agent Docker 部署架构等距 3D 配置图

Hermes Agent 能当你 24/7 在线的 AI 助手,但前提是它得一直活着。本地跑一下测试没问题,真要挂到 VPS 上持续运行,配置向导只是第一步——容器怎么编排、数据怎么持久化、崩溃了谁来拉起、密钥放哪里安全、Dashboard 怎么安全暴露,每个环节都有坑。

本文给你一套完整的 Docker 部署方案——从 $5/月 VPS 选型到 Docker Compose 配置,从 s6-overlay 进程监管到七层安全加固,从 Bitwarden 密钥管理到踩坑清单。所有配置都可以直接复制到你的服务器上运行,所有命令都经过验证。

适合谁:已经在本地跑通 Hermes Agent 的用户,现在想把它搬到 VPS 上 24/7 运行,需要一份不遗漏细节的生产部署指南。完全没用过 Hermes 的读者,建议先看 Hermes Agent 完全指南


Docker 与 Hermes 的两种关系

Docker Hub 上的 Hermes Agent 官方镜像页面

开始之前需要分清一个容易混淆的概念:Hermes 与 Docker 有两种完全不同的交叉方式,官方文档开篇就做了区分,但很多人第一次看会搞混。

第一种:Agent 本体运行在容器内——这是本文的主线。把 Hermes 整个装进 Docker 容器,利用容器的隔离性和自动重启策略实现 24/7 持续运行。容器内包含完整的 Python 环境、Node.js 运行时、Playwright 浏览器自动化组件和 s6-overlay 进程管理器。你在消息平台(Telegram、Discord 等)发消息,容器里的 Hermes 收到并处理——容器就是 Agent 的家。

第二种:Docker 作为终端后端(Terminal Backend)——Agent 在宿主机运行,但把每条命令发到一个持久化 Docker 沙箱容器内执行。配置项是 terminal.backend: docker。这个沙箱容器跨工具调用、跨 /new 命令、跨子 Agent 持续存活,直到 Hermes 进程结束。这种方式的目的是安全隔离命令执行环境——Agent 要运行 rm -rf 之类的危险命令,破坏的是沙箱而不是宿主机。

两种方式可以叠加使用:Agent 本体运行在 Docker 容器 A 里,同时配置 terminal.backend: docker 让命令在另一个沙箱容器 B 里执行,实现双层隔离。本文聚焦第一种部署方式,第二种在终端后端对比章节简要覆盖。


Docker Compose 完整配置

Docker Compose 多容器编排与健康检查

最简可运行版本

一个 docker-compose.yml 解决全部问题。让你的 AI 助手帮你生成:

提示词:生成最简 Hermes Docker Compose 配置

请帮我生成一个最简可运行的 docker-compose.yml,用于部署 Hermes Agent。要求:

  • 镜像:nousresearch/hermes-agent:latest
  • 容器名:hermes
  • 重启策略:unless-stopped
  • 启动命令:gateway run
  • 端口映射:8642(Gateway API)和 9119(Dashboard)
  • 数据卷:宿主机 ~/.hermes 映射到容器 /opt/data
  • 环境变量:启用 Dashboard(HERMES_DASHBOARD=1
  • 资源限制:内存 4G、CPU 2.0 核

这份配置定义了一个单容器服务:镜像拉取后以 gateway run 命令启动网关进程,两个端口分别暴露 Gateway API 和 Dashboard 界面,数据卷确保容器重建后所有配置和会话数据不丢失,资源限制防止 Agent 在突发负载时拖垮整台 VPS。

三条命令启动:

mkdir -p ~/.hermes
docker run -it --rm -v ~/.hermes:/opt/data nousresearch/hermes-agent setup
docker compose up -d

第二条是交互式配置向导——输入 API Key、选择消息平台(Telegram/Discord/Slack/WhatsApp 等)、完成初始化。向导把密钥写入 ~/.hermes/.env,其他配置写入 ~/.hermes/config.yaml。建议在这一步就把消息平台配好,省得启动后再进容器改配置。

💡 通俗讲:setup 命令用完即销毁(--rm),它的唯一目的是往 ~/.hermes/ 写配置文件。写完之后 docker compose up -d 才是真正启动常驻容器。

生产级完整版(含健康检查与自动更新)

提示词:生成生产级 Hermes Docker Compose 配置(含健康检查与自动更新)

请帮我生成一个生产级的 docker-compose.yml,部署 Hermes Agent 并配套自动更新。要求:

  • Hermes 服务
  • 镜像:nousresearch/hermes-agent:latest,命令 gateway run
  • 端口绑定到 127.0.0.1:8642:8642(仅本地回环,不暴露公网)
  • 使用 Docker Named Volume hermes-data 映射到 /opt/data(不用 bind mount)
  • 环境变量:启用 Dashboard、UID=10000、GID=10000
  • 健康检查:用 wget -qO- 探测 http://localhost:8642/health,间隔 30s、超时 10s、重试 3 次、启动等待 20s
  • 资源限制:内存 4G、CPU 2.0 核
  • 可选:Dashboard 以只读模式(:ro)分离部署为独立容器
  • Watchtower 服务
  • 镜像 containrrr/watchtower,每 3600 秒检查一次 hermes 容器的镜像更新
  • 挂载 Docker socket,启用旧镜像自动清理(WATCHTOWER_CLEANUP=true
  • 顶层声明 hermes-data Named Volume

这份配置在最简版基础上加入了四个生产级要素。以下逐条解释关键设计决策:

  • 端口绑定 127.0.0.1:Gateway API 只监听本地回环地址,不暴露公网。外部访问由反向代理(Caddy 或 Nginx)统一处理 HTTPS 和认证。如果你只用 Telegram/Discord 消息平台而不需要 API 接口,端口映射可以直接去掉——消息平台走出站连接,不需要入站端口
  • Named Volumehermes-data 是 Docker 管理的命名卷,比 bind mount(直接映射宿主机目录)更安全。docker compose down 不会删除命名卷,只有显式执行 docker compose down -v 才会清除——这在生产环境是关键的数据保护屏障
  • Watchtower:每小时检查一次上游镜像是否有更新版本,有则自动拉取新镜像、停止旧容器、用新镜像重建容器,旧镜像自动清理。你不需要手动跑 docker compose pull——Watchtower 帮你做了
  • healthcheck:每 30 秒探测一次 Gateway 的 /health 端点。三次失败后标记为不健康,Docker 会重启容器。同时让 depends_on 其他服务时能等待 Gateway 真正就绪再启动

数据持久化:一个目录装所有状态

/opt/data(映射到宿主机 ~/.hermes/)是全部状态的唯一真值源:

路径 存什么
.env API Key 和密钥
config.yaml 全部 Hermes 配置
SOUL.md Agent 人格/身份
sessions/ 对话历史
memories/ 持久化记忆
skills/ 已安装技能
home/ 子进程 HOME(git/ssh/gh/npm)
cron/ 定时任务定义
hooks/ 事件钩子
logs/ 运行日志
checkpoints/ 项目快照(/rollback 用)

关键限制:绝不可让两个 Gateway 容器同时写入同一数据目录——session 文件和 memory 存储不支持并发写入。如果你在一台机器上同时跑了两个 Hermes 容器指向同一个 ~/.hermes/,轻则对话历史丢失,重则配置文件损坏。需要多个 Agent 实例时,应该使用多 Profile 模式(后文详述)而非多容器共享数据。

备份方案

数据目录是全部状态的命脉,务必建立定期备份机制。备份有两种方式:Hermes 内置的 hermes backup 命令(一键导出 zip 包)和标准的 Docker Volume 快照(适合 cron 定期执行)。恢复则用 hermes import 命令导入备份文件。

提示词:生成 Hermes 数据备份脚本

请帮我生成一个 Bash 备份脚本(set -euo pipefail),同时使用两种方式备份 Hermes 数据。要求:

  • 方法 1:执行容器内置命令 docker exec hermes hermes backup
  • 方法 2:启动一个临时 Alpine 容器,以只读模式(:ro)挂载 hermes-data 卷,打包为带时间戳(YYYYmmdd-HHMMSS)命名的 .tar.gz 文件,存放到宿主机的 /backup/hermes/ 目录
  • 恢复命令:docker exec hermes hermes import /opt/data/backups/hermes-backup-YYYYMMDD.zip --force

VPS 选型与 24/7 部署

硬件需求

资源 最低 推荐
CPU 1 核 2 核
内存 1 GB(无浏览器) 2-4 GB
磁盘 500 MB 2+ GB

实际测试:不运行本地模型时 Hermes 使用不到 500 MB 内存,一个最便宜的 VPS 就能胜任。模型推理通过 API 调用(OpenRouter、Nous Portal、OpenAI 等),Agent 本身不做推理计算,轻度使用 API 费约 $2-5/月。浏览器自动化(Playwright/Chromium)是最吃内存的功能——如果你的 Agent 不需要打开网页、截图或填表单,1 GB 内存足够。需要浏览器功能时建议至少 2 GB,4 GB 更稳妥。

💡 通俗讲:Hermes 本身很轻量,像一个只负责调度的管家。真正干重活的是远端的大模型 API,管家只需要把指令传过去、把结果拿回来。所以便宜的 VPS 就够了。

VPS 提供商对比

提供商 起步价 亮点
Hetzner $4.49/月 欧洲数据中心、性价比最高
Hostinger $5/月 有 Hermes Agent 一键模板,最快部署
DigitalOcean $5/月 Droplet 操作简单
Vultr $5/月 全球节点多
Contabo $5/月 详细社区教程
Oracle Always Free $0 4 OCPU / 24 GB ARM,免费

成本计算:$5/月 VPS + $2-5/月 API 费 = 每月 $7-10 拥有一个 24/7 在线的 AI Agent。Oracle Always Free 方案甚至可以把 VPS 成本降到零——4 OCPU / 24 GB ARM 的免费实例跑 Hermes 绰绰有余,只需要支付 API 调用费用。如果连 API 费用都想省,OpenRouter 的 :free 模型可以进一步降为零成本。

Hostinger 提供了专门的 Hermes Agent 应用目录(Application Catalog),选 VPS 计划后系统自动安装 Docker、部署容器,通过 SSH 运行 setup wizard 就能完成配置——全程不到 10 分钟。适合不想自己从头搭环境的用户。

从零到运行:完整步骤

# 1. SSH 连接 VPS(务必用 SSH,不要用提供商的浏览器终端)
ssh root@your-vps-ip

# 2. 安装 Docker
curl -fsSL https://get.docker.com | sh && systemctl enable docker

Docker 就绪后,剩下的步骤可以让 AI 助手一步到位地生成完整的部署命令序列:

提示词:生成 Hermes Agent VPS 部署命令

Docker 已安装就绪,请帮我生成后续的部署命令序列。要求:

  • 创建数据目录 ~/.hermes
  • 运行交互式配置向导:用 docker run -it --rm 挂载数据目录到 /opt/data,执行 nousresearch/hermes-agent setup
  • 后台启动网关容器:容器名 hermes,重启策略 unless-stopped,挂载数据目录,映射端口 8642,命令 gateway run
  • 验证:执行 hermes doctorhermes gateway status 确认运行正常

避免使用 VPS 提供商的浏览器终端(如 Hetzner Cloud Console)。这些终端可能把 : 渲染为 ;,把 @ 错误替换——会静默破坏 Docker 的 -v 参数和 API Key。务必通过 SSH 连接。


6 种终端后端对比

6 种终端后端隔离级别对比

Hermes 支持 6 种终端后端(Terminal Backend),决定了 Agent 执行命令的位置和隔离级别:

后端 执行位置 隔离级别 适用场景 成本
local 宿主机 无隔离 开发/可信环境 $0
docker Docker 容器 容器隔离 生产网关沙箱 $0
ssh 远程服务器 机器隔离 命令执行分离到独立机器 VPS 费用
singularity Singularity 容器 容器隔离 HPC/学术环境 $0
modal Modal 云函数 云端沙箱 突发/GPU 工作负载 按秒计费
daytona Daytona 工作区 云端沙箱 持久化云开发环境 按需计费

Docker 终端后端配置

配置 Docker 终端后端需要在 config.yamlterminal 段指定后端类型、沙箱镜像、资源限额和持久化策略:

提示词:生成 Hermes Docker 终端后端配置

请帮我生成 Hermes config.yamlterminal 配置段,使用 Docker 作为终端后端。要求:

  • backend 设为 docker
  • docker_image 使用 nikolaik/python-nodejs:python3.11-nodejs20(同时有 Python 和 Node.js)
  • docker_forward_env 设为空列表(不向沙箱容器传递宿主机环境变量和密钥)
  • 资源限制:CPU 1 核、内存 5120 MB、磁盘 51200 MB
  • 启用 container_persistent(跨 Session 持久化文件系统)

这段配置的核心思路是让 Agent 在一个隔离的 Docker 沙箱中执行命令,而不是在宿主机上直接运行。docker_forward_env 设为空意味着沙箱容器无法读取宿主机的 API Key 等敏感环境变量。container_persistent 使沙箱容器的文件系统跨工具调用、跨 /new 命令、跨子 Agent 持续存活,直到 Hermes 进程结束。使用 Docker 终端后端时,危险命令检查被跳过——容器本身就是安全边界。

Modal 按秒计费,什么时候比 VPS 划算?

  • 突发场景:每天 10 条命令 x 15 秒 x 2vCPU/4GB = 150 秒计算,每月几分钱。远低于 $5 VPS
  • 稳定场景:每天持续 4 小时以上的计算,超过 VPS 成本
  • 常驻网关:必须始终在线接收消息,Modal 不适用

经验法则:每天有效计算低于 2-3 小时用 Modal 更省;超过则 VPS 更划算。另外 Modal 每次函数调用有几秒冷启动惩罚——如果 Agent 连续发 lscat file.txtgrep foo 三条独立命令,就是三次冷启动。Hermes 的 Modal 后端可以在单次 Session 内保持容器温热来缓解这个问题,但编写批量脚本代替多条短命令仍然是更好的做法。

混合方案也是一种选择:网关在 $5 VPS 上常驻运行(接收消息、管理会话),重计算任务(GPU 推理、大规模数据处理)分发到 Modal。这样兼顾了常驻能力和弹性计算。


网关服务化:让 Hermes 永远在线

Docker 自动重启(最简方案)

如果你只用一个容器、不需要 Compose 的编排能力,--restart unless-stopped 一个参数就解决了崩溃恢复和系统重启后自动拉起的问题。只有手动执行 docker stop 才能停止——VPS 重启、Docker daemon 重启、Agent 进程崩溃,全都自动恢复:

docker run -d \
  --name hermes \
  --restart unless-stopped \
  -v ~/.hermes:/opt/data \
  nousresearch/hermes-agent gateway run

s6-overlay 进程监管(Docker 内部)

官方 Docker 镜像以 s6-overlay v3 作为 PID 1(替换了早期的 tini),提供容器内部的进程监管:

  • Gateway 崩溃后几秒内自动重启,无需重建容器
  • 多 Profile 模式下每个 Profile 的 Gateway 独立监管
  • 日志自动旋转(每 Profile 10 份 x 1 MB)

gateway run 命令在 s6 容器内自动升级为监管语义:内部函数 _gateway_command_inner 检测到 s6 PID 1 后,将请求派发给 s6 service manager,然后执行 sleep infinity 保持 CMD 进程存活。递归保护通过 HERMES_S6_SUPERVISED_CHILD=1 环境变量实现,阻止监管子进程再次进入重定向。如果你需要调试启动过程,可以用 --no-supervise 标志或 HERMES_GATEWAY_NO_SUPERVISE=1 环境变量显式关闭监管模式。

💡 通俗讲:s6-overlay 就像容器里的保姆。Docker 的 --restart 只能在整个容器崩溃时重启——杀掉所有进程再全部重来。s6 更精细,Gateway 进程崩了几秒内就拉起来,其他进程(如 Dashboard)完全不受影响。

systemd(Linux 原生安装)

如果选择不用 Docker 而是直接安装 Hermes,需要创建 systemd 服务文件让系统管理 Hermes 进程的生命周期——开机自启、崩溃自动重启、日志接入 journald:

提示词:生成 Hermes Agent systemd 服务文件

请帮我生成一个 systemd unit 文件 hermes-gateway.service。要求:

  • [Unit] 段:描述为 Hermes Agent Gateway,在 network.target 之后启动
  • [Service] 段:Type=simple、以专用用户 hermes 运行、工作目录 /home/hermes
  • 启动命令:/home/hermes/.local/bin/hermes gateway
  • 崩溃恢复:Restart=alwaysRestartSec=10(崩溃后等 10 秒再重启)
  • 环境变量:PATH 包含 /home/hermes/.local/bin:/usr/bin:/bin(确保能找到 hermes 和系统命令)
  • [Install] 段:WantedBy=multi-user.target
  • 生成后执行 daemon-reloadenablestart 三条命令

launchd(macOS)

hermes gateway install 自动注册 launchd plist。但有一个陷阱:每次 gateway install 会从内置模板重新生成 plist,默认 WorkingDirectory 指向 pipx 包目录。需要手工修补:

plutil -replace WorkingDirectory \
  -string '/your/working/directory' \
  ~/Library/LaunchAgents/ai.hermes.gateway.plist
hermes gateway restart

pipx upgrade hermes-agent 后如果重新安装了 gateway service,同样需要重做修补。

四种方式对比

方式 优势 劣势
Docker --restart 隔离好、升级简单、跨平台 多一层抽象
s6-overlay(Docker 内) 多 Profile 监管、秒级崩溃恢复 需理解 s6 日志机制
systemd 系统级集成、journald 日志 仅 Linux;依赖自己管
launchd macOS 原生 plist 被 gateway install 覆盖

反向代理与 Dashboard 安全

Dashboard 认证机制

官方支持三种 Dashboard 认证模式:

模式 配置 适用场景
用户名/密码 HERMES_DASHBOARD_BASIC_AUTH_USERNAME + PASSWORD 自建/VPN 后面
OAuth(Nous Portal) HERMES_DASHBOARD_OAUTH_CLIENT_ID 公开部署
自建 OIDC HERMES_DASHBOARD_OIDC_ISSUER + CLIENT_ID 企业身份提供者

安全设计:无认证且绑定非回环地址时,Dashboard 启动直接报错拒绝(fail closed)。HERMES_DASHBOARD_INSECURE=1 可绕过但会暴露 API Key。

SSH 隧道(最简安全方案)

ssh -L 9119:localhost:9119 user@vps-ip
# 本地浏览器打开 http://localhost:9119

Caddy 反向代理(自动 HTTPS)

Caddy 的优势是自动申请和续期 Let's Encrypt 证书,零配置实现 HTTPS:

提示词:生成 Hermes Caddy 反向代理配置

请帮我生成 Caddy 的 Caddyfile 配置,反向代理 Hermes Agent。要求:

  • hermes.yourdomain.com:反向代理到 localhost:8642(Gateway API),启用 basicauth(密码用 caddy hash-password 生成的 bcrypt 哈希)
  • dashboard.yourdomain.com:反向代理到 localhost:9119(Dashboard),同样启用 basicauth
  • Caddy 自动处理 HTTPS 证书申请和续期,无需额外配置

Nginx 反向代理(含 WebSocket 支持)

如果你用 Nginx 而非 Caddy,需要额外处理 SSL 证书和 WebSocket 升级头。其中 proxy_read_timeout 是关键参数——Hermes 的 SSE(Server-Sent Events)长连接需要足够长的超时时间,默认 60 秒会导致连接中断:

提示词:生成 Hermes Nginx 反向代理配置

请帮我生成 Nginx 的 server 配置块,反向代理 Hermes Agent Gateway。要求:

  • 监听 443 端口,启用 SSL
  • 域名:hermes.yourdomain.com
  • SSL 证书路径:Let's Encrypt 默认路径 /etc/letsencrypt/live/{域名}/(fullchain.pem + privkey.pem)
  • 反向代理到 http://127.0.0.1:8642
  • 支持 WebSocket 升级:设置 UpgradeConnection "upgrade" 头,HTTP 版本 1.1
  • 转发真实客户端 IP:X-Real-IPHost
  • proxy_read_timeout 设为 3600s(1 小时,SSE 长连接必需)

安全加固:七层纵深防御

七层纵深防御安全模型

AI Agent 有自主执行命令的能力,这意味着安全性比普通 Web 应用更关键。如果模型被提示注入(prompt injection)攻击——比如用户在文件里藏了一条"删除所有数据"的指令——Agent 可能真的去执行。Hermes 对此建立了七层纵深防御模型(Defense in Depth),每一层都是一道独立的安全屏障:

  1. 用户授权——允许列表控制谁能与 Agent 对话,生产环境禁用 GATEWAY_ALLOW_ALL_USERS=true
  2. 危险命令审批——人在回路审批破坏性操作。三种模式:manual(始终提示审批)、smart(辅助模型评估风险)、off(等同 --yolo
  3. 容器隔离——Docker 沙箱 + 加固参数,即使 Agent 执行恶意命令也限制在容器内
  4. MCP 凭据过滤——MCP 子进程的环境变量被隔离,Agent 无法通过 MCP 工具泄露宿主机密钥
  5. 上下文文件扫描——项目文件在加载前检测提示注入模式
  6. 跨 Session 隔离——Session 无法访问彼此数据;Cron 存储路径防路径穿越
  7. 输入消毒——终端工具后端的工作目录参数基于允许列表验证

此外还有一个硬编码黑名单(Always-On Floor)——即使在 --yolo 模式、approvals.mode: off 下也绝对不执行的命令:rm -rf / 及变体、Bash fork bomb、mkfs.* 对已挂载设备、dd if=/dev/zero of=/dev/sd*、将不受信 URL 管道到 sh

Docker 安全参数详解

容器启动时自动附加的安全参数:

--cap-drop ALL                     # 丢弃全部 Linux capabilities
--cap-add DAC_OVERRIDE             # root 可写绑定挂载目录
--cap-add CHOWN                    # 包管理器需要
--cap-add FOWNER                   # 包管理器需要
--security-opt no-new-privileges   # 阻止特权提升
--pids-limit 256                   # 限制进程数(防 fork bomb)
--tmpfs /tmp:rw,nosuid,size=512m   # 有限大小的 /tmp
--tmpfs /var/tmp:rw,noexec,nosuid,size=256m  # 不可执行的 /var/tmp

容器内用户降权

官方镜像通过 s6-setuidgid hermes(UID 10000)降权运行——不再以 root 身份执行 Agent 逻辑。这解决了早期 GitHub Issue #3969 中社区报告的三个安全关注:容器以 root 运行、有过多 capabilities、建议加固为非 root 运行。

官方在 s6-overlay 迁移 PR #30136(+6794/-215,40 个文件)中彻底解决了这些问题——移除了 gosu,改用 s6-setuidgid 降权,同时加入了 hadolint 和 shellcheck 构建输入检查。

Rootless Docker 部署

AI Agent 沙箱的推荐选择。安装:

dockerd-rootless-setuptool.sh install

额外加固措施:

--read-only              # 根文件系统只读
--tmpfs /tmp:size=512m   # 显式可写临时目录

网关/沙箱分离架构

企业级方案(来自 Simon Gajdosik 的实践):

  • 两台 VPS 通过 Tailscale 连接:一台持有 OAuth token 与消息平台通信,一台运行 Shell 命令
  • Agent 永远不 SSH 到普通 Linux Shell——它 SSH 到 rootless 容器内的 /workspace
  • 如果模型被提示注入,最坏情况是在无特权容器中探索——该机器没有生产密钥、没有公网 SSH 端口

网络隔离最佳实践

  • Gateway API 端口仅绑定 127.0.0.1
  • Dashboard 仅通过 SSH 隧道暴露
  • 消息平台走出站连接(Telegram/Discord 长轮询),无需开放入站端口
  • SSRF 防护:所有 URL 工具(Web 搜索、提取、浏览器)在获取前验证 URL,阻止 SSRF 攻击。黑名单包括 RFC 1918 私网(10.0.0.0/8172.16.0.0/12192.168.0.0/16)、回环(127.0.0.0/8)、链路本地(169.254.0.0/16,含云元数据 169.254.169.254)、CGNAT 地址空间(100.64.0.0/10,覆盖 Tailscale/WireGuard VPN)
  • Tirith 预执行扫描:集成 tirith 做命令级安全扫描——检测同形字 URL 欺骗、管道到解释器模式、终端注入攻击。首次使用时自动下载并 SHA-256 校验

凭据文件权限

chmod 600 ~/.hermes/.env  # 仅所有者可读写

生产部署检查清单(官方 10 条)

  1. 设置显式允许列表——生产环境禁用 GATEWAY_ALLOW_ALL_USERS=true
  2. 使用容器后端——terminal.backend: docker
  3. 限制资源——CPU、内存、磁盘
  4. 安全存储密钥——.env 文件权限 600
  5. 启用 DM 配对——用配对码代替硬编码用户 ID
  6. 审查命令允许列表——定期审计 command_allowlist
  7. 设置 terminal.cwd——不让 Agent 在敏感目录操作
  8. 以非 root 运行——不以 root 运行网关
  9. 监控日志——检查未授权访问
  10. 保持更新——定期 docker compose pull

密钥管理:Bitwarden Secrets Manager

Hermes Agent Docker 官方文档页面

生产环境把 API Key 明文写在 .env 里不理想。Hermes 原生集成了 Bitwarden Secrets Manager(BSM):

工作原理

  1. 在 BSM 创建 machine account,授予项目读权限,生成 access token
  2. Hermes 将 token 存入 ~/.hermes/.envBWS_ACCESS_TOKEN
  3. 每次启动时调用 bws secret list,将返回的 Key 设入环境变量
  4. 默认覆盖已有环境变量——Bitwarden 是唯一真值源

在 Bitwarden Web 端轮换一次 Key,所有 Hermes 进程下次启动即生效——不需要逐台机器改 .env 文件。bws 二进制在首次使用时自动下载到 ~/.hermes/bin/,版本固定为 v2.0.0(不自动升级到 latest,确保可复现性),无需 apt/brew/sudo。

这在多机器部署场景下特别有价值。假设你有三台 VPS 各跑一个 Hermes 实例,传统做法是 SSH 到每台机器修改 .env 里的 API Key;用 Bitwarden 后,只在 Web 端改一次,三台机器下次重启时自动拉取新密钥。

配置

hermes secrets bitwarden setup

向导自动完成:下载并校验 bws v2.0.0 -> 提示输入 access token -> 选择区域 -> 列出项目 -> 测试拉取 -> 启用。

除了交互式向导,也可以直接在 config.yaml 中手动配置 Bitwarden 集成。配置段包含启用开关、access token 的环境变量名、项目 ID、区域设定、缓存策略等参数:

提示词:生成 Hermes Bitwarden Secrets Manager 配置

请帮我生成 Hermes config.yamlsecrets.bitwarden 配置段。要求:

  • enabled: true
  • access_token_env:从环境变量 BWS_ACCESS_TOKEN 读取 access token
  • project_id:填你的 Bitwarden 项目 ID
  • server_url:留空表示 US Cloud;欧盟区设为 https://vault.bitwarden.eu
  • cache_ttl_seconds: 300(缓存 5 分钟,避免频繁请求 Bitwarden API)
  • override_existing: true(Bitwarden 值覆盖 .env 中的同名变量,确保唯一真值源)
  • auto_install: true(首次使用时自动下载 bws 二进制)

容错设计

Bitwarden 永不阻塞 Hermes 启动——任何失败仅输出一行警告,Hermes 继续使用 .env 中已有的凭据。

适用场景判断

场景 推荐方案
单机个人部署 .env 足够
多机器集群 / 团队共享 Bitwarden Secrets Manager
气隙环境 .env(无法访问 Bitwarden API)
已有 CI/CD 密钥注入 用现有机制

多 Profile 部署:一容器多 Agent

一容器多 Profile 架构与 s6 监管

s6 迁移后,推荐"一个容器多个 Profile"模式:

# 创建 Profile
docker exec hermes hermes profile create work
docker exec hermes hermes profile create personal

# 查看监管状态
docker exec hermes s6-rc -a list

# 查看特定 Profile 日志
docker exec hermes tail -f /opt/data/logs/gateways/work/current

# 停止/启动特定 Profile
docker exec hermes hermes gateway stop --profile work
docker exec hermes hermes gateway start --profile work

一容器多 Profile vs 一 Profile 一容器

维度 一容器多 Profile 一 Profile 一容器
磁盘开销 一份镜像、一个 venv N 份
内存开销 共享 Python 解释器缓存 每容器重复
Profile 创建 docker exec 秒级完成 docker run + 端口分配
崩溃恢复 s6-supervise 自动重启 Docker --restart(更慢)
备份 一个 ~/.hermes 目录 N 个目录

仍需独立容器的场景:资源隔离需求(--memory/--cpus 每 Profile 不同)、独立镜像版本、网络分段、合规/爆炸半径控制。

每个 Profile 可以连接不同的 Telegram/Discord 频道、使用不同的模型、有独立的 SOUL.md 人格定义。例如创建一个 work Profile 连接公司 Slack,一个 personal Profile 连接个人 Telegram——两个 Agent 共享一个容器但彼此完全隔离。

官方还支持 Profile Distributions(配置文件分发)——将完整 Agent 打包为可分发单元,部署到多台机器或跨机器同步状态。适合团队部署和边缘节点同步。


升级与维护流程

Hermes Agent GitHub 仓库与 Docker Compose 配置

Docker Compose 升级(推荐)

docker compose pull    # 拉取新镜像
docker compose up -d   # 基于新镜像重建容器

数据卷保留,容器启动时自动运行非交互式 config-schema 迁移——如果新版本修改了配置文件格式,迁移脚本会自动转换。Watchtower 可自动化整个流程,你甚至不需要手动执行这两条命令。

升级前的最佳实践:先备份数据目录,再升级。虽然官方保证向后兼容,但多一层保险总没坏处。

单容器升级

如果没有用 Docker Compose 而是用 docker run 单容器运行,升级流程是拉取新镜像、删除旧容器、用相同参数重建容器。数据卷不受影响,新容器启动时自动运行配置迁移:

提示词:生成 Hermes 单容器升级命令

请帮我生成单容器升级 Hermes Agent 的命令序列。要求:

  • 拉取最新镜像 nousresearch/hermes-agent:latest
  • 强制删除旧容器 hermes
  • 用与之前完全一致的参数重建容器:容器名 hermes、重启策略 unless-stopped、数据卷 ~/.hermes:/opt/data、命令 gateway run
  • 确保重建后参数与原容器一致(端口映射、环境变量等根据你的实际配置添加)

日常维护检查

docker exec hermes hermes doctor          # 全面自检
docker exec hermes hermes gateway status   # 网关状态
docker exec hermes hermes status           # 模型/provider 状态
docker logs -f hermes --tail 50            # 最近日志

日志路由

s6 容器有四个日志面:

来源 落地位置 读取方式
每 Profile Gateway ~/.hermes/logs/gateways/<profile>/current tail -F
Dashboard docker logs docker logs -f hermes
Boot reconciler ~/.hermes/logs/container-boot.log tail -F
通用 Hermes 日志 ~/.hermes/logs/agent.log docker exec hermes hermes logs --follow

连接本地推理服务器

如果想用本地模型(vLLM、Ollama 等)配合 Docker 部署的 Hermes:

Docker Compose 方式(推荐)

核心思路是把 Hermes 和推理服务器放在同一个 Docker 网络内,容器名就是主机名,不需要暴露推理端口到宿主机:

提示词:生成 Hermes + vLLM 联合 Docker Compose 配置

请帮我生成一个 docker-compose.yml,同时部署 vLLM 推理服务和 Hermes Agent,放在同一 Docker 网络中。要求:

  • vLLM 服务
  • 镜像 vllm/vllm-openai:latest,容器名 vllm
  • 启动参数:--model Qwen/Qwen2.5-7B-Instruct --served-model-name my-model --host 0.0.0.0 --port 8000
  • GPU 资源预留:deploy.resources.reservations.devices 声明 gpu capability
  • 加入共享网络 hermes-net
  • Hermes 服务
  • 标准 Hermes 容器配置(镜像、gateway run、数据卷、127.0.0.1 端口绑定)
  • 加入同一个 hermes-net 网络
  • 顶层声明 hermes-net 为 bridge 网络
  • config.yaml 配置provider: custommodel: my-modelbase_url: http://vllm:8000/v1(用容器名 vllm 作为主机名)、api_key: "none"

宿主机推理服务器

  • macOS/Windows:使用 host.docker.internal 访问宿主机服务
  • Linux:使用 --network hosthost.docker.internal(Docker 20.10+)

Ollama

如果用 Ollama 作为推理后端,同样放在共享 Docker 网络内。Ollama 需要一个 Named Volume 持久化下载的模型文件,避免容器重建后重复下载:

提示词:生成 Hermes + Ollama 联合 Docker Compose 配置

请帮我在前面的 docker-compose.yml 基础上,把 vLLM 替换为 Ollama。要求:

  • 镜像 ollama/ollama:latest,容器名 ollama
  • Named Volume ollama-data 映射到 /root/.ollama(持久化模型文件)
  • 加入 hermes-net 共享网络
  • config.yaml 的 base_url 改为 http://ollama:11434/v1

更多本地模型部署细节参考 Hermes Agent 本地模型指南


云平台托管方案

除了自建 VPS,还有多种云平台提供一键部署:

平台 方式 特点 适用场景
Hostinger 应用目录一键 最快路径,Docker Manager 可视化 不想碰命令行
Fly.io 官方蓝图 fly deploy 持久卷,无需 Dockerfile 已有 Fly 账号
Render One-click Blueprint 持久磁盘 + Dashboard 一键部署
Coolify 开源 PaaS 模板 自动 HTTPS、Git 集成、$5 VPS 搭配 自建 Heroku 替代
Oracle Free Terraform 4 OCPU/24GB ARM/$0 零成本方案
AWS Marketplace 预构建 AMI 预配 Docker+Tailscale+Caddy 企业合规

Coolify 一键部署

Coolify 开源自托管 PaaS 首页

Coolify 是 57K Stars 的开源自托管 PaaS,已合并 Hermes Agent 模板:

# 安装 Coolify
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
# 在 Web UI 搜索 Hermes Agent → Deploy

模板自动创建双容器栈:WebUI 公开(自动生成域名和密码、自动 HTTPS via Let's Encrypt)、Agent Gateway 内部运行不暴露公网。共享 Named Volume 存储配置、会话和记忆,默认使用嵌入式 SQLite。把 Coolify 装在 $5/月的 Hetzner VPS 上,成本远低于 Vercel Pro,同时获得 280+ 一键模板、Git 集成(推送部署)和多服务器管理能力。

hermes-anywhere:Terraform 多云

开源 Terraform 方案,一条命令部署到 5 个云:

terraform apply  # 选择 Oracle/Hetzner/GCP/AWS/DigitalOcean
make doctor      # 健康检查
make backup      # GPG 加密备份

踩坑清单

基于官方文档、社区实践和实际部署经验总结:

现象 解决
浏览器终端破坏字符 API Key 中的 :;@ 被替换 务必用 SSH 连接,不用 VPS 浏览器终端
UID/GID 不匹配 容器内文件权限报错 设置 HERMES_UID=$(id -u) HERMES_GID=$(id -g)
两个 Gateway 写同一数据目录 session 损坏、记忆丢失 一个数据目录只允许一个 Gateway 进程
Dashboard 绑公网无认证 启动直接报错 加 BasicAuth / OAuth / SSH 隧道
Docker socket 暴露 容器逃逸风险 仅在需要 Docker 终端后端时挂载 socket
Watchtower 自动更新失败 镜像标签问题(manifest unknown) 确认镜像标签为 latest 或指定具体 tag
Named Volume 误删 docker compose down -v 清除数据 生产环境永远不带 -v;定期备份
SELinux 标签问题 挂载文件访问被拒 卷挂载加 :Z 后缀
内存不足 OOM 浏览器自动化触发 OOM deploy.resources.limits.memory: 4G 或关闭浏览器工具
s6 日志不旋转 磁盘被日志撑满 检查 /opt/data/logs/gateways/ 旋转配置

FAQ

Hermes Agent Docker 镜像包含什么?

基于 debian:13.4,包含:Python 3 全依赖、Node.js + npm(WhatsApp 桥接)、Playwright + Chromium(浏览器自动化)、ripgrep、ffmpeg、git、docker-cli(可驱动宿主机 Docker)、openssh-client、s6-overlay v3 作为 PID 1。压缩约 2.6 GB。

消息平台需要开放入站端口吗?

不需要。Telegram、Discord 等消息平台使用出站长轮询连接——Agent 主动连平台,不需要平台连进来。端口映射 8642 只在需要外部调用 Gateway API 时才需要。

如何查看 Hermes 使用了多少资源?

docker stats hermes  # 实时 CPU/内存/网络
docker exec hermes hermes doctor  # 内部自检

能用 Podman 代替 Docker 吗?

可以。官方 NixOS 模块支持 Podman 替代。社区也有 Rootless Podman 部署的讨论。命令基本兼容,把 docker 替换为 podman 即可。

检查点(Checkpoint)在 Docker 里怎么用?

检查点数据存储在 /opt/data/checkpoints/ 目录下,通过数据卷持久化。容器重建后检查点历史保留。管理命令:

docker exec hermes hermes checkpoints status
docker exec hermes hermes checkpoints prune --retention-days 7 --max-size-mb 500

支持哪些 NAS 部署?

QNAP(官方教程覆盖 Container Station)和 Synology(Container Manager)都支持。关键注意 UID/GID 映射:

docker run -d --name hermes \
  -e PUID=1000 -e PGID=10 \
  -v /volume1/docker/hermes:/opt/data \
  nousresearch/hermes-agent gateway run

如何实现零成本部署?

Oracle Cloud Always Free Tier:4 OCPU / 24 GB ARM / $0。配合 hermes-anywhere Terraform 方案一键部署。API 费用使用 OpenRouter :free 模型可进一步降为零。

从 tini 迁移到 s6-overlay 需要改配置吗?

不需要。官方已在镜像层面完成迁移(PR #30136),用户无需改 docker-compose.yml 或命令。升级到最新镜像即自动使用 s6-overlay。


下一步


  • AI 编程实操课:Claude Code + Codex + Agent 工作流,覆盖一人公司、自媒体自动化、AI 副业全场景。237 篇实战教程 + 最佳实践 + 源码包,跟着做就出成果。国内版-FlowUS | 国际版-BMC
  • YouTube 频道翔宇工作流
  • 微信公众号:搜索「翔宇工作流」

订阅成功!请到邮箱查收确认链接。

订阅成功!请到邮箱查收确认链接。

订阅成功!请到邮箱查收确认链接。

订阅成功!请到邮箱查收确认链接。

操作成功。

操作已取消。