Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

Hermes 团队多人协作部署方案

一套在单台 Mac 上为 20 人团队部署 Hermes 的实战方案 —— Profile 隔离、Open WebUI 接入、SSH 远程操控 Windows、危险操作审计。

License: MIT


方案速览

维度 设计
硬件 1 台 32GB Mac(服务端)
团队 20 人,各自 Windows PC
接入方式 Open WebUI(PC)+ 飞书机器人(移动端)
远程操控 Hermes SSH 终端后端 → Windows
隔离方案 每人独立 Hermes Profile + Gateway 进程
审计 approvals.mode: manual + 飞书审批 + agent.log 事后追溯
资源占用 20 人同时在线 ≈ 8 Gi 内存

Hermes 团队多人协作部署方案

一、方案概述

目标

一台高配 Mac(32GB 内存)作为服务端,让团队 20 人通过各自 Windows 电脑远程使用 Hermes,每人独立 Profile、独立记忆、独立 Skills 管理。

整体架构

┌──────────────────────────────────────────────────────────┐
│                    Mac Server(32G)                       │
│                                                          │
│  ~/.hermes/                                              │
│  ├── skills/          ← 你集中管理,全局共享              │
│  ├── config.yaml      ← 全局默认配置                      │
│  └── profiles/                                            │
│      ├── alice/                                           │
│      │   ├── config.yaml   ← 独有配置(模型、MCP等)        │
│      │   ├── .env          ← 独有密钥 + SSH配置            │
│      │   ├── sessions/     ← 独有会话记录                  │
│      │   └── ssh_keys/     ← 连接 Alice 电脑的密钥          │
│      ├── bob/                                              │
│      └── carol/                                            │
│                                                          │
│  Gateway 进程池(每人一个):                               │
│  PID 8642 → gateway (profile: alice) → api_server:8642    │
│  PID 8643 → gateway (profile: bob)   → api_server:8643    │
│  PID 8644 → gateway (profile: carol) → api_server:8644    │
│  ...                                                      │
└──────────────────────┬───────────────────────────────────┘
                       │ 局域网
        ┌──────────────┼──────────────┐
        ▼              ▼              ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Alice 的 Win │ │ Bob 的 Win  │ │ Carol 的 Win│
│ OpenSSH 服务 │ │ OpenSSH 服务│ │ OpenSSH 服务│
│ port 22     │ │ port 22    │ │ port 22    │
│ 192.168.1.101│ │192.168.1.102│ │192.168.1.103│
└─────────────┘ └─────────────┘ └─────────────┘
       │               │              │
  Open WebUI       Open WebUI     Open WebUI
  (Alice 的 Win)   (Bob 的 Win)   (Carol 的 Win)

资源预算

项目 占用
macOS 系统 ~4 Gi
Gateway × 20 进程(每进程 ~200MB) ~4 Gi
总计 ~8 Gi
剩余 ~24 Gi(给其他应用和缓冲)

对比 ClawManager K8s 方案(每人一个 Pod 占 2Gi,装不下 20 个),纯 Hermes Gateway 方案20 人同时在线的内存成本不到 8GB


二、前置条件

2.1 Mac 端

  • macOS(32GB 内存,建议 M 系列芯片)
  • Hermes Agent 已安装
  • 局域网 IP 固定(建议 DHCP 静态分配)
  • 防火墙放行 8642-8662 端口区间(每位成员 +1)

2.2 每台 Windows 端

  • Windows 10/11(建议 22H2 以上)
  • Open WebUI 或任意 OpenAI 兼容客户端(LobeChat、ChatBox、NextChat 等)
  • 与 Mac 处于同一局域网
  • SSH 客户端(Win10/11 自带)
  • (可选)Docker Desktop 用于跑 Open WebUI 容器

三、Mac 服务端部署

3.1 创建团队成员的 Hermes Profile

# 为每个成员创建独立 Profile
hermes profile create alice
hermes profile create bob
hermes profile create carol
# ... 以此类推

# 验证
ls ~/.hermes/profiles/

3.2 为每个 Profile 配置模型和 API Key

# 给 Alice 的 Profile 配模型(交互式)
hermes -p alice model

# 或直接编辑 config.yaml
hermes -p alice config edit
# 在打开的 config.yaml 中设置 model 和 provider

3.3 为每个 Profile 生成 SSH 密钥

# 生成密钥,每人一对
ssh-keygen -t ed25519 -f ~/.hermes/profiles/alice/ssh_keys/id_ed25519 -N ""
ssh-keygen -t ed25519 -f ~/.hermes/profiles/bob/ssh_keys/id_ed25519 -N ""
ssh-keygen -t ed25519 -f ~/.hermes/profiles/carol/ssh_keys/id_ed25519 -N ""

3.4 配置每个 Profile 的终端后端为 SSH

编辑每个 Profile 的 .env

# ~/.hermes/profiles/alice/.env
TERMINAL_ENV=ssh
TERMINAL_SSH_HOST=192.168.1.101        # Alice 的 Windows IP
TERMINAL_SSH_USER=alice
TERMINAL_SSH_PORT=22
TERMINAL_SSH_KEY=~/.hermes/profiles/alice/ssh_keys/id_ed25519
# ~/.hermes/profiles/bob/.env
TERMINAL_ENV=ssh
TERMINAL_SSH_HOST=192.168.1.102
TERMINAL_SSH_USER=bob
TERMINAL_SSH_PORT=22
TERMINAL_SSH_KEY=~/.hermes/profiles/bob/ssh_keys/id_ed25519

3.5 为每个 Profile 启动 Gateway(API Server 模式)

启动脚本示例 start_team_gateways.sh

#!/bin/bash
# 启动所有团队成员的 Gateway 进程

# 端口分配:从 8642 开始,每人 +1
declare -A PORTS=(
  ["alice"]=8642
  ["bob"]=8643
  ["carol"]=8644
  # 继续添加...
)

for profile in "${!PORTS[@]}"; do
  port=${PORTS[$profile]}
  profile_dir="$HOME/.hermes/profiles/$profile"

  # 确保目录存在
  if [ ! -d "$profile_dir" ]; then
    echo "⚠ Profile $profile 不存在,跳过"
    continue
  fi

  # 端口占用检测
  if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
    echo "⚠ 端口 $port 已占用,跳过 $profile"
    continue
  fi

  echo "🚀 启动 $profile → port $port"
  HERMES_HOME="$profile_dir" \
    API_SERVER_ENABLED=true \
    API_SERVER_PORT="$port" \
    API_SERVER_HOST="0.0.0.0" \
    nohup hermes gateway run > "$profile_dir/gateway.log" 2>&1 &

  sleep 1
done

echo "✅ 所有 Gateway 已启动"
echo "   检查状态:ps aux | grep 'hermes gateway'"

注意:如果需要同时对接飞书机器人,在每个 Profile 的 config.yaml 中启用对应 Platform 配置即可。Gateway 会同时启用 API Server 和飞书。

3.6 统一管理 Skills

# Skills 是全局共享的,放在 ~/.hermes/skills/ 下
# 所有 Profile 的 Hermes 启动时会读取这个目录

# 安装全局 Skill
hermes skills install <skill-name>

# 或直接复制
cp -r ~/my-skills/* ~/.hermes/skills/

Skills 是全局共享的。每个 Profile 的 Hermes Gateway 进程读取的是其 HERMES_HOME/skills/ 目录。由于 HERMES_HOME 指向各自的 Profile 目录,默认每个 Profile 的 Skills 也隔离。

要让 Skills 共享,有两种方式:

  1. 在每个 Profile 的 config.yaml 中配置 skills_dir: ~/.hermes/skills/(如果支持)
  2. 用符号链接:ln -s ~/.hermes/skills/ ~/.hermes/profiles/alice/skills

四、Windows 客户端部署

4.1 开启 OpenSSH Server(每台 Windows 执行一次)

# 以管理员身份运行 PowerShell

# 1. 安装 OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# 2. 启动并设为自动
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'

# 3. 防火墙放行 22 端口
New-NetFirewallRule -Name 'OpenSSH-Server' -DisplayName 'OpenSSH Server' `
  -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

# 4. 确认 SSH 服务器运行
Get-Service sshd

# 5. 查看本机 IP
ipconfig
# 记录 IPv4 地址(如 192.168.1.101)

4.2 配置 SSH 密钥认证(先传给管理员,或自行配置)

方法 A:管理员统一配置(推荐) Windows 用户将公钥发给管理员,管理员在 Mac 上装好公钥。但更方便的是:

方法 B:Windows 用户自行配置

# 在 Windows 上执行

# 1. 创建 .ssh 目录(如果不存在)
mkdir $env:USERPROFILE\.ssh -Force

# 2. 管理员给你的公钥内容,粘贴到 authorized_keys
notepad $env:USERPROFILE\.ssh\authorized_keys
# 粘贴公钥内容,保存

# 3. 设置正确的权限
icacls $env:USERPROFILE\.ssh\authorized_keys /inheritance:r /grant "$env:USERNAME:(R)"
icacls $env:USERPROFILE\.ssh /inheritance:r /grant "$env:USERNAME:(RX)"

# 4. 测试连接(在 Mac 上验证)
# ssh -i ~/.hermes/profiles/alice/ssh_keys/id_ed25519 alice@192.168.1.101

4.3 安装 Open WebUI

# 方式一:Docker 安装(推荐)
# 安装 Docker Desktop 后执行
docker run -d -p 3000:8080 ^
  --name open-webui ^
  --restart always ^
  ghcr.io/open-webui/open-webui:main

# 方式二:直接安装(需要 Python 3.11+)
pip install open-webui
open-webui serve

4.4 配置 Open WebUI 连接到 Mac 的 Gateway

打开 Open WebUI,进入设置 → 连接:

设置项
OpenAI API 地址 http://你的MacIP:8642/v1(Alice 用 8642,Bob 用 8643...)
API Key 留空或按需设置
模型名称 hermes-agent(自动显示)

五、日常使用流程

5.1 管理员操作

# 查看所有 Gateway 运行状态
ps aux | grep 'hermes gateway'

# 查看某个成员的 Gateway 日志
tail -f ~/.hermes/profiles/alice/gateway.log

# 重启某个成员的 Gateway
kill <PID>
HERMES_HOME=~/.hermes/profiles/alice \
  API_SERVER_ENABLED=true \
  API_SERVER_PORT=8642 \
  nohup hermes gateway run > ~/.hermes/profiles/alice/gateway.log 2>&1 &

# 安装全局技能
hermes skills install <skill-name>

# 为某个 Profile 单独安装技能
HERMES_HOME=~/.hermes/profiles/alice hermes skills install <skill-name>

# 停服
kill $(pgrep -f 'hermes gateway')

5.2 团队成员操作

所有操作在自己的 Windows 电脑上完成

打开 Open WebUI:

# 方式一:Docker 运行
http://localhost:3000

# 方式二:pip 安装
http://localhost:8080

全流程示例(Alice 的一天):

1. 打开 Open WebUI → http://localhost:3000
2. 确认右上角模型选的是 hermes-agent
3. 输入:"帮我看看桌面有哪些文件"
   → Hermes Mac Gateway 收到请求
   → SSH 连接到 Alice 的 Windows (192.168.1.101:22)
   → 执行 dir %USERPROFILE%\Desktop
   → 结果返回显示在 Open WebUI

4. 继续问:"帮我整理一下,把 .pdf 都放到 PDFs 文件夹"
   → Hermes 通过 SSH 在 Alice 电脑上执行
     mkdir %USERPROFILE%\Desktop\PDFs
     move %USERPROFILE%\Desktop\*.pdf %USERPROFILE%\Desktop\PDFs\
   → 完成后回复 Alice

5. 或者问:"帮我分析这个项目代码结构"
   → Hermes 通过 SSH 读取 Alice 电脑上的文件
   → 进行分析
   → 返回分析结果

六、故障排查

6.1 SSH 连接失败

# 在 Mac 上测试 SSH 连接
ssh -v -i ~/.hermes/profiles/alice/ssh_keys/id_ed25519 alice@192.168.1.101

# 常见原因
# - Windows 防火墙未放行 22 端口
# - OpenSSH Server 未启动
# - 密钥权限不正确
# - IP 地址变更

6.2 Gateway 无法启动

# 检查配置文件
HERMES_HOME=~/.hermes/profiles/alice hermes config check

# 全量测试
HERMES_HOME=~/.hermes/profiles/alice hermes doctor

# 查看日志
cat ~/.hermes/profiles/alice/gateway.log

6.3 Open WebUI 连不上

- 确认 Mac 和 Windows 在同一网段
- 在 Windows 上 ping MacIP 确认网络连通
- 确认 Mac 防火墙未拦截端口 8642-8662
- 检查 Open WebUI 配置的 API 地址是否正确
- Open WebUI 的 "连接" 地址末尾要带 /v1

七、扩展方案

7.1 对接飞书/企业微信机器人

在 Profile 的 config.yaml 中额外配置飞书或企业微信平台:

# ~/.hermes/profiles/alice/config.yaml
gateway:
  platforms:
    feishu:
      enabled: true
      app_id: cli_xxxxx1
      app_secret: xxxx

同一个 Gateway 进程同时服务:

  • Alice 的飞书机器人私聊(手机端)
  • Alice 的 Open WebUI(PC 端)

两者共享同一个 Profile、同一套记忆、同一个 SSH 后端。

7.2 增加 MCP Server 扩展能力

如果 SSH 不够用,可以在每台 Windows 上部署 MCP Server 提供精细控制。

7.3 开机自启 Gateway(launchd 管理)

使用 macOS 原生 launchd 替代 nohup 管理 Gateway 进程,具备崩溃自动重启、开机自启、日志轮转能力。

launchd plist 模板(每 Profile 一份):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.hermes.gateway.alice</string>

  <key>ProgramArguments</key>
  <array>
    <string>/bin/bash</string>
    <string>-c</string>
    <string>
      HERMES_HOME=~/.hermes/profiles/alice \
      API_SERVER_ENABLED=true \
      API_SERVER_PORT=8642 \
      API_SERVER_HOST=0.0.0.0 \
      /Users/chenzhiqing/.local/bin/hermes gateway run
    </string>
  </array>

  <!-- 用户登录后启动 -->
  <key>RunAtLoad</key>
  <true/>

  <!-- 崩溃后自动重启 -->
  <key>KeepAlive</key>
  <true/>

  <!-- 日志输出 -->
  <key>StandardOutPath</key>
  <string>~/.hermes/profiles/alice/logs/gateway.log</string>
  <key>StandardErrorPath</key>
  <string>~/.hermes/profiles/alice/logs/errors.log</string>

  <!-- 每 300s 检查一次进程是否存活 -->
  <key>ThrottleInterval</key>
  <integer>300</integer>
</dict>
</plist>

安装步骤:

# 1. 生成 plist 文件
cat > ~/Library/LaunchAgents/com.hermes.gateway.alice.plist << 'PLIST'
...(上述内容)...
PLIST

# 2. 加载服务
launchctl load ~/Library/LaunchAgents/com.hermes.gateway.alice.plist

# 3. 查看状态
launchctl list | grep hermes

# 4. 手动启停
launchctl start com.hermes.gateway.alice
launchctl stop com.hermes.gateway.alice

注意:

  • plist 中所有路径必须使用绝对路径/Users/xxx/),~ 在 launchd 中不生效
  • hermes 命令路径用 which hermes 确认后填入
  • 批量生成脚本见 §7.7 一键运维

7.4 Workflow Profile 协作(员工助手调用功能性 Profile)

架构概念

两套 Profile 各司其职:

类型 角色 进程状态 例子
员工助手 Profile 每人一个,绑定团队成员 🟢 常驻 Gateway alicebobcarol
Workflow Profile 功能性角色,供员工调用 🔴 纯目录,用时才启动 workflow-analysisworkflow-backend

Workflow Profile 不需要跑任何 Gateway/API Server/MCP Server 进程。它只是 ~/.hermes/profiles/ 下的一个普通目录,有独立的 config.yamlskills/sessions/。员工助手的 agent 在 Mac 上用 Python 子进程直接调用。

架构图

Mac 上的 ~/.hermes/profiles/

员工助手 Profile(常驻 Gateway)        Workflow Profile(纯目录,无进程)
                                           ┌─────────────────────┐
┌──────────────────┐                       │ workflow-analysis   │
│ alice (Gateway)  │── execute_code() ──→  │ config.yaml         │
│ port 8642        │                       │ skills/             │
│ SSH → Alice 的PC │←──── stdout ────────  │ sessions/           │
└──────────────────┘                       │ (独立记忆)         │
                    │                      └─────────────────────┘
┌──────────────────┐                       ┌─────────────────────┐
│ bob (Gateway)    │── execute_code() ──→  │ workflow-backend    │
│ port 8643        │                       │ config.yaml         │
│ SSH → Bob 的PC   │                       │ skills/             │
└──────────────────┘                       │ sessions/           │
                    │                      └─────────────────────┘
┌──────────────────┐                       ┌─────────────────────┐
│ carol (Gateway)  │── execute_code() ──→  │ workflow-writing    │
│ port 8644        │                       │ ...                 │
└──────────────────┘                       └─────────────────────┘

配置方法

第一步:创建 Workflow Profile

和创建员工 Profile 一样,只是不启动 Gateway:

# 创建三个 Workflow Profile
hermes profile create workflow-analysis
hermes profile create workflow-backend
hermes profile create workflow-writing

# 给每个 Profile 配置模型和技能
hermes -p workflow-analysis model       # 选模型
HERMES_HOME=~/.hermes/profiles/workflow-analysis hermes skills install <skill-name>

第二步:员工助手调用 Workflow Profile

员工助手的 agent 通过 execute_code 工具,直接在 Mac 上以子进程方式调用 Workflow CLI:

# Alice 的 agent 收到:"分析这份销售数据" 后内部执行:
import subprocess, os

result = subprocess.run(
    [
        "hermes", "chat", "-q",
        "分析销售数据\n\n"
        "背景:本季度销售额,数据通过 SSH 从用户 Windows 读取。"
        "输出季度环比增长率、Top5 产品排名。"
    ],
    capture_output=True, text=True,
    env={
        "HERMES_HOME": os.path.expanduser("~/.hermes/profiles/workflow-analysis"),
        **os.environ
    },
    timeout=120
)

# 把结果返回给 Alice
return result.stdout

调用流程图:

Alice: "帮我分析一下这份销售数据"
  │
  ▼
Alice 的助手 agent
  │
  ├─ ① SSH → Alice 的 Windows 读取销售数据文件
  │
  ├─ ② execute_code() → subprocess.run()
  │       HERMES_HOME=workflow-analysis
  │       hermes chat -q "分析数据:<读到的数据>"
  │       │
  │       ▼
  │   workflow-analysis(新进程,用完退出)
  │       │ 继承工作流技能,有独立记忆
  │       ▼
  │   返回分析结果 ← stdout
  │
  └─ ③ 汇总结果,回复 Alice

记忆保留

Workflow Profile 的会话历史自动保存在其目录下,两次调用可以用 --continue 续接:

# 第一次调用
subprocess.run(["hermes", "chat", "-q", "分析上月销售数据"], env={...})

# 后续追问(续接同一会话)
subprocess.run(["hermes", "--continue", "-q", "跟去年比怎么样"], env={...})

并行安全性: 每个 subprocess 是独立进程、独立会话。Alice 和 Bob 同时调用同一个 Workflow Profile → 各自启动独立进程、独立会话,互不干扰。

适用场景举例

Workflow Profile 技能配置 员工如何调用
workflow-analysis 数据分析 skill + SQL skill "帮我看一下这个 Excel"
workflow-backend 架构设计 skill + 代码审查 skill "帮我校验这个 API 设计"
workflow-writing 文案写作 skill + 文档 skill "帮我写一份项目周报"
workflow-security 安全审计 skill "帮我检查一下这个配置文件有没有漏洞"

注意事项

  • Workflow Profile 不需要跑任何守护进程(Gateway / API Server / MCP Server 都不需要)
  • 子进程调用有超时(建议设 120-300s),复杂任务设大一点
  • hermes chat -q 是单次对话,非交互模式,适合程序调用
  • 如果需要 Workflow 中有工具调用(如联网搜索、文件读写),确保其 config.yaml 中开了对应工具
  • 调用方(员工助手)需要 execute_code 工具权限(默认开启)

7.5 SSH 安全加固

强制 Windows 静态 IP

DHCP 会导致 Windows IP 不定期变化,SSH 连接因此断连。两种方案选其一:

方案 A:Windows 手动设静态 IP

# 在 Windows 上以管理员身份运行
# 查看当前网络配置
ipconfig /all
# 记下:IPv4 地址、子网掩码、默认网关、DNS 服务器

# 设置为静态(替换为你的实际值)
netsh interface ip set address "以太网" static 192.168.1.101 255.255.255.0 192.168.1.1
netsh interface ip set dns "以太网" static 192.168.1.1

方案 B:路由器 DHCP 绑定(推荐) 在路由器管理界面中,将每台 Windows 的 MAC 地址与 IP 绑定,这样 DHCP 每次分配同一个 IP。

维护 IP 映射表

在 Mac 上维护一个 ~/.hermes/hosts.csv,启动脚本读取此文件:

profile,host,user,port,desc
alice,192.168.1.101,alice,22,设计部-工位A
bob,192.168.1.102,bob,22,开发部-工位B
carol,192.168.1.103,carol,22,产品部-工位C
# 定期校验:检查所有 IP 是否可达
#!/bin/bash
# ping_check.sh
echo "📡 IP 连通性检查"
while IFS=',' read -r profile host user port desc; do
  [ "$profile" = "profile" ] && continue  # 跳过表头
  if ping -c 1 -W 2 "$host" >/dev/null 2>&1; then
    echo "$profile ($host) 可达"
  else
    echo "$profile ($host) 不可达!"
  fi
done < ~/.hermes/hosts.csv

SSH 密钥安全

# 设置密钥目录权限(必须 700,否则 SSH 拒绝使用)
chmod 700 ~/.hermes/profiles/*/ssh_keys/
chmod 600 ~/.hermes/profiles/*/ssh_keys/*

# 每月密钥轮换脚本
#!/bin/bash
# rotate_ssh_keys.sh
month=$(date +%Y%m)
for profile in ~/.hermes/profiles/*/; do
  name=$(basename "$profile")
  key_dir="$profile/ssh_keys"
  [ ! -d "$key_dir" ] && continue
  # 备份旧密钥
  tar czf "${key_dir}/../ssh_keys_bak_${month}.tar.gz" -C "$(dirname "$key_dir")" "ssh_keys"
  # 生成新密钥
  ssh-keygen -t ed25519 -f "${key_dir}/id_ed25519" -N "" -C "${name}-${month}"
  echo "$name 密钥已轮换,请将公钥同步到 Windows"
done

SSH 客户端配置(防网络抖动)

# ~/.ssh/config
Host 192.168.1.*
  ServerAliveInterval 15       # 每 15s 发心跳保活
  ServerAliveCountMax 3        # 3 次心跳失败才断开
  ConnectionAttempts 3         # 连接失败重试 3 次
  ConnectTimeout 10            # 每次连接超时 10s
  StrictHostKeyChecking no     # 局域网环境跳过 known_hosts 检查
  UserKnownHostsFile /dev/null

在每台 Windows 的 OpenSSH 服务端也配心跳:

# Windows 上以管理员运行
# 编辑 C:\ProgramData\ssh\sshd_config
# 添加:
#   ClientAliveInterval 15
#   ClientAliveCountMax 3

# 重启 SSH 服务
Restart-Service sshd

7.6 配置备份(crontab 定时)

# crontab -e,每日凌晨 2 点备份
0 2 * * * /bin/bash -c '\
  BACKUP_DIR="/Volumes/Backup/hermes_profiles/$(date +%Y%m%d)" && \
  mkdir -p "$BACKUP_DIR" && \
  rsync -avz --delete \
    --exclude="sessions/" \       # 会话文件量大,按需备份
    --exclude="logs/" \           # 日志文件量大,按需备份
    ~/.hermes/profiles/ \
    "$BACKUP_DIR/" && \
  echo "✅ 备份完成: $BACKUP_DIR" >> ~/.hermes/backup.log'

# 也备份一份全局配置
0 2 * * * cp ~/.hermes/config.yaml "/Volumes/Backup/hermes_profiles/config.yaml.$(date +%Y%m%d)"

备份策略建议:

文件 频率 保留期 备注
profiles/*/config.yaml 每日 30 天 核心配置
profiles/*/.env 每日 30 天 API Key、SSH 配置
profiles/*/ssh_keys/ 每月 12 月 轮换前备份旧密钥
profiles/*/sessions/ 按需 量大,不自动备份
skills/ 每次变更 Git 管理更合适

7.7 一键运维脚本(hermes-ops.sh)

将零散的运维命令封装为统一入口,降低管理 20 个 Profile 的操作成本。

#!/bin/bash
# hermes-ops.sh —— Hermes 团队运维脚本
# 用法:
#   ./hermes-ops.sh status             查看所有 Gateway 状态
#   ./hermes-ops.sh start              批量启动所有 Gateway
#   ./hermes-ops.sh restart <name>     重启某个 Profile
#   ./hermes-ops.sh stop all           停止所有 Gateway
#   ./hermes-ops.sh logs <name>        查看某个 Profile 的日志
#   ./hermes-ops.sh check              校验所有 Profile 配置完整性

HERMES_HOME="$HOME/.hermes"
PORTS_FILE="$HERMES_HOME/hosts.csv"

# 默认端口映射(如无 hosts.csv 则走此表)
declare -A PORTS=(
  ["alice"]=8642
  ["bob"]=8643
  ["carol"]=8644
  ["workflow-analysis"]=8750
  ["workflow-backend"]=8751
)

# 读取端口映射
_load_ports() {
  if [ -f "$PORTS_FILE" ]; then
    while IFS=',' read -r name host user port desc; do
      [ "$name" = "profile" ] && continue
      PORTS["$name"]=$port
    done < "$PORTS_FILE"
  fi
}

status() {
  echo "═══════════════════════════════════════"
  echo "📊 Hermes Gateway 状态报告"
  echo "日期: $(date)"
  echo "═══════════════════════════════════════"
  for profile in "${!PORTS[@]}"; do
    port=${PORTS[$profile]}
    pid=$(lsof -Pi :$port -sTCP:LISTEN -t 2>/dev/null)
    if [ -n "$pid" ]; then
      uptime=$(ps -o etime= -p "$pid" | xargs)
      echo "$profile → port $port (PID $pid, 已运行 $uptime)"
    else
      echo "$profile → port $port (未运行)"
    fi
  done
}

start() {
  _load_ports
  for profile in "${!PORTS[@]}"; do
    port=${PORTS[$profile]}
    profile_dir="$HERMES_HOME/profiles/$profile"

    [ ! -d "$profile_dir" ] && echo "$profile 目录不存在,跳过" && continue
    lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1 && echo "$port 已占用,跳过 $profile" && continue

    echo "🚀 启动 $profile → port $port"
    HERMES_HOME="$profile_dir" \
      API_SERVER_ENABLED=true \
      API_SERVER_PORT="$port" \
      API_SERVER_HOST="0.0.0.0" \
      nohup hermes gateway run > "$profile_dir/logs/gateway.log" 2>&1 &
    sleep 1
  done
  echo "✅ 启动完成"
}

stop() {
  local target=${1:-all}
  if [ "$target" = "all" ]; then
    echo "🛑 停止所有 Gateway..."
    pkill -f "hermes gateway run" 2>/dev/null
    echo "✅ 已停止"
  elif [ -n "${PORTS[$target]}" ]; then
    local pid=$(lsof -Pi :${PORTS[$target]} -sTCP:LISTEN -t 2>/dev/null)
    if [ -n "$pid" ]; then
      kill "$pid"
      echo "$target 已停止"
    else
      echo "$target 未运行"
    fi
  fi
}

logs() {
  local profile=$1
  [ -z "$profile" ] && echo "用法: $0 logs <profile>" && exit 1
  tail -f "$HERMES_HOME/profiles/$profile/logs/gateway.log"
}

check() {
  echo "🔍 校验所有 Profile 配置..."
  for profile in "${!PORTS[@]}"; do
    dir="$HERMES_HOME/profiles/$profile"
    local ok=true
    [ ! -f "$dir/config.yaml" ] && echo "$profile: 缺少 config.yaml" && ok=false
    [ ! -f "$dir/.env" ] && echo "$profile: 缺少 .env" && ok=false
    [ -d "$dir/ssh_keys" ] && [ "$(stat -f %A "$dir/ssh_keys")" != "700" ] && echo "$profile: ssh_keys 权限不是 700" && ok=false
    $ok && echo "$profile: 正常"
  done
}

case "${1:-status}" in
  status)  status ;;
  start)   start ;;
  stop)    stop "$2" ;;
  restart) stop "$2"; sleep 1; start ;;
  logs)    logs "$2" ;;
  check)   check ;;
  *)
    echo "用法: $0 {status|start|stop|restart|logs|check}"
    echo "示例:"
    echo "  $0 status             查看所有状态"
    echo "  $0 start              批量启动"
    echo "  $0 stop alice         停止 Alice"
    echo "  $0 stop all           停止所有"
    echo "  $0 restart bob        重启 Bob"
    echo "  $0 logs alice         查看 Alice 日志"
    echo "  $0 check              校验配置"
    ;;
esac

---

# 八、危险操作审计

## 8.1 审计策略总览

审计策略选型:方案 B — Open WebUI + 飞书审批通道

┌─────────────────────────────────────────────────────────┐ │ Alice 日常使用 │ │ │ │ "帮我删掉 D 盘 temp 文件夹" │ │ │ │ │ ▼ │ │ Open WebUI (Alice 的 Windows) │ │ │ │ │ ▼ │ │ Hermes Gateway (profile: alice) │ │ │ │ │ ├─ 检测到危险命令 ───→ 飞书审批群 ←─ 你在手机上审批 │ │ │ │ │ │ │ ┌──────────────┴──────────────┐ │ │ │ │ 批准 ──→ 执行命令 │ │ │ │ │ 拒绝 ──→ 拦截 + agent.log 记录│ │ │ │ └─────────────────────────────┘ │ │ │ │ │ ▼ │ │ SSH → Alice 的 Windows 执行 │ │ │ │ │ ▼ │ │ 结果返回 Alice 的 Open WebUI │ └─────────────────────────────────────────────────────────┘

事后审计:你定期跑 daily_audit.sh 扫 agent.log


## 8.2 Hermes 自带的危险命令检测

Hermes 内置了 `tools/approval.py` 危险命令检测系统,可以自动识别并拦截高风险操作。

**可以检测到的危险命令模式包括:**

| 类别 | 示例 |
|------|------|
| 破坏性文件操作 | `rm -rf /`、`mkfs.ext4`、`dd if=/dev/zero of=/dev/sda` |
| 系统关机/重启 | `shutdown`、`reboot`、`halt`、`poweroff` |
| 权限提升 | `sudo` 高风险命令、`pkexec`、`chmod -R 777` |
| 远程下载执行 | `curl ... \| bash`、`wget ... \| sh` |
| SSH 密钥操作 | 修改 `~/.ssh/` 下的文件 |
| 容器破坏 | `docker rm -f` 所有容器 |
| 配置文件篡改 | 修改 `~/.hermes/.env`、`config.yaml`、shell rc 文件 |

## 8.3 审批模式配置(方案 B 选定配置)

```yaml
# ~/.hermes/profiles/alice/config.yaml

# 审批模式:manual
# 所有危险操作 → 通过飞书发给管理员审批
# API Server 本身无法交互审批,必须依赖外部 IM 通道
approvals:
  mode: manual
  timeout: 60            # 超时后自动拒绝,防止永久阻塞
  cron_mode: deny
  subagent_auto_approve: false

# 审批通道:飞书(主)+ 企业微信(备)
# 两条通道同时在线,一条挂了另一条兜底
gateway:
  platforms:
    feishu:
      enabled: true
      app_id: cli_xxxxx        # 管理员审核用飞书机器人
      app_secret: xxxxx
    wecom:                     # 企业微信兜底
      enabled: true
      corp_id: xxxx
      agent_id: xxxx
      secret: xxxx

security:
  redact_secrets: true
# 配置命令
hermes -p alice config set approvals.mode manual

⚠ 注意:Open WebUI 本身不具备审批交互能力。 危险操作被拦截时,Alice 在 Open WebUI 会看到类似 "操作等待审批" 的提示。 审批请求将通过飞书发送到你的审核群,你在手机上点批准或拒绝。

8.4 审计日志查看

每个 Profile 有 3 个日志文件,这是你作为管理员做审计的核心依据:

# 日志文件位置(每个 Profile 独立)
~/.hermes/profiles/alice/logs/
├── agent.log          # 所有操作的全量日志(核心审计文件)
├── errors.log         # 错误和警告(快速排查用)
└── gateway.log        # Gateway 层面事件

常用审计命令:

# 1. 查看 Alice 今天执行了哪些终端命令
grep "terminal_tool\|SSH\|executing command" ~/.hermes/profiles/alice/logs/agent.log | tail -50

# 2. 查看 Alice 触发过哪些危险命令审批
grep -i "dangerous\|approval\|BLOCKED\|DENY\|WARNING" ~/.hermes/profiles/alice/logs/agent.log | tail -30

# 3. 查看 Alice 的所有错误
tail -50 ~/.hermes/profiles/alice/logs/errors.log

# 4. 实时监控某个 Profile 的操作
tail -f ~/.hermes/profiles/alice/logs/agent.log | grep "terminal_tool\|executing\|SSH"

# 5. 全局审计:所有 Profile 的终端操作一键查询
for p in ~/.hermes/profiles/*/; do
  name=$(basename "$p")
  count=$(grep -c "terminal_tool\|executing command" "$p/logs/agent.log" 2>/dev/null || echo 0)
  danger=$(grep -c "dangerous\|BLOCKED\|DENY" "$p/logs/agent.log" 2>/dev/null || echo 0)
  echo "$name: $count 次终端操作, $danger 次危险操作拦截"
done

8.5 会话回溯(查看完整对话记录)

# 列出 Alice 的所有历史会话
HERMES_HOME=~/.hermes/profiles/alice hermes sessions list

# 回溯某个具体会话的全部内容(包括工具调用)
HERMES_HOME=~/.hermes/profiles/alice hermes sessions browse
# 交互式选择会话 → 查看完整对话

# 导出会话为 JSONL 用于存档或分析
HERMES_HOME=~/.hermes/profiles/alice hermes sessions export ~/alice_sessions.jsonl

# 查看会话统计
HERMES_HOME=~/.hermes/profiles/alice hermes sessions stats

8.6 安全增强配置

# ~/.hermes/profiles/alice/config.yaml 中额外配置

security:
  # 开启秘密信息脱敏(API Key 等不会写入日志和会话)
  redact_secrets: true

  # 网站黑名单(禁止 Hermes 访问的域名)
  website_blocklist:
    - "malware.example.com"

approvals:
  # 子 Agent 遇到危险命令 → 自动拒绝并记审计日志(安全默认)
  subagent_auto_approve: false

  # Cron 任务遇到危险命令 → 自动拒绝(安全默认)
  cron_mode: deny

8.7 飞书审批操作流程

当 Alice 触发了危险命令,你在飞书上的审批体验:

飞书审批群收到消息:
┌────────────────────────────────────┐
│ ⚠️ 危险操作需要审批                 │
│                                    │
│ 用户:Alice                        │
│ 命令:rm -rf D:\temp\*             │
│ 原因:批量删除临时文件              │
│                                    │
│ [✅ 批准]  [❌ 拒绝]               │
└────────────────────────────────────┘

你点 批准 → 命令在 Alice 的 Windows 上执行
你点 拒绝 → 命令被拦截,Alice 看到"操作被拒绝"

8.8 审计流程建议

作为管理员(你),建立以下日常检查流程:

#!/bin/bash
# daily_audit.sh —— 每日审计检查

echo "═══════════════════════════════════════"
echo "📋 Hermes 团队每日审计报告"
echo "日期: $(date)"
echo "═══════════════════════════════════════"

for profile_dir in ~/.hermes/profiles/*/; do
  name=$(basename "$profile_dir")
  log="$profile_dir/logs/agent.log"
  echo ""
  echo "── $name ──"

  if [ ! -f "$log" ]; then
    echo "   ⚠ 无日志"
    continue
  fi

  # 1. 今日危险操作
  danger_count=$(grep "$(date +%Y-%m-%d)" "$log" | grep -ci "BLOCKED\|DENY" || echo 0)
  echo "   危险操作拦截: $danger_count"
  if [ "$danger_count" -gt 0 ]; then
    echo "   被拦截的命令:"
    grep "$(date +%Y-%m-%d)" "$log" | grep -i "BLOCKED\|DENY" | \
      sed 's/.*BLOCKED: //;s/.*DENY: //' | \
      sort | uniq -c | sort -rn | head -5 | \
      while read count cmd; do
        echo "      - $cmd$count 次)"
      done
  fi

  # 2. 今日终端命令执行次数
  cmds=$(grep "$(date +%Y-%m-%d)" "$log" | grep -c "executing command" || echo 0)
  echo "   终端命令执行: $cmds"

  # 3. 今日 SSH 连接次数
  ssh=$(grep "$(date +%Y-%m-%d)" "$log" | grep -c "SSH\|ssh" || echo 0)
  echo "   SSH 连接次数: $ssh"

  # 4. 今日错误数
  errs=$(grep "$(date +%Y-%m-%d)" "$log" | grep -ci "error\|exception\|traceback" || echo 0)
  echo "   错误数: $errs"
done

8.9 审计架构总结

Alice 操作                         你在飞书上                          日志留存
    │                                │                                  │
    ▼                                ▼                                  ▼
"删掉 D 盘 temp"
    │
    ▼
Hermes 检测到危险命令
    │
    ▼
审批请求 ──────────────────→ 飞书审批群
                                │
                           ┌────┴────┐
                           │ 你点批准 │──→ SSH 执行命令         ← agent.log 记录
                           │ 你点拒绝 │──→ 命令被拦截            ← agent.log 记录 BLOCKED
                           └─────────┘
                                            Alice 的会话完整记录 → sessions/*.jsonl
                                            agent.log 永久可查     → 事后追溯

---

# 九、架构决策记录

| 决策 | 选择 | 原因 |
|------|------|------|
| 远程终端方案 | SSH | Hermes 原生支持,零开发,成熟稳定 |
| 用户隔离方式 | Hermes Profile | 原生 Profile 机制,`~/.hermes/profiles/` 完全隔离 |
| 用户接入方式 | Open WebUI + api_server | OpenAI 兼容标准,客户端选择多,体验好 |
| Gateway 进程模型 | 每 Profile 一个 | `HERMES_HOME` 隔离保证,PID 防冲突机制原生支持 |
| Skills 管理 | 全局共享 + 符号链接 | 统一管理、灵活隔离 |
| 多 IM 渠道 | 可选,Profile config.yaml 中配置 | 与 API Server 共存于同一 Gateway 进程 |
| **审计策略** | **方案 B:Open WebUI + 飞书审批通道** | **`approvals.mode: manual` + 飞书机器人 → 管理员在手机上审批;`agent.log` 事后审计** |
| **Workflow 调用方式** | **`execute_code()` + `subprocess.run()` 调 CLI** | **Workflow Profile 不跑任何守护进程;员工助手用 `HERMES_HOME` 环境变量以子进程方式直接调用;`hermes chat -q` 单次交互 + `--continue` 续接会话;天然并行,互不干扰** |

About

Hermes 团队多人协作部署方案 — 单台 Mac 为 20 人团队部署 Hermes 的完整实战方案

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages