侧边栏壁纸
博主头像
龍騰博客 博主等级

行动起来,活在当下

  • 累计撰写 186 篇文章
  • 累计创建 31 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

让 Hermes 只能启停指定的三个模型容器 保姆级教程

管理员
2026-08-23 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

背景:trim.hermes 系统账号默认不在 docker 组、摸不到 /var/run/docker.sock, 这是好事(防止它碰你其他所有 docker 服务)。但坏处是它连自己该管的三个本地模型 容器(qwen36 / qwen3-2507 / glm47)都启停不了,尤其是已停止的容器,靠 ps aux 完全看不到。

本教程通过"白名单脚本 + 精确 sudoers 授权",只开一条窄门: Hermes 能且只能启停这三个指定容器,碰不了其他任何 docker 资源。


涉及到的容器名(以本机实际为准)

llama-qwen3-2507
llama-glm47
llama-qwen36

如果以后新增/更换模型容器,只需要改脚本里 ALLOWED_CONTAINERS 这一个数组,其他步骤不用动。


第一步:创建白名单脚本

SSH 登录 fnOS 后,执行:

cat > /usr/local/bin/manage-model-containers.sh << 'EOF'
#!/bin/bash
set -euo pipefail

ALLOWED_CONTAINERS=("llama-qwen3-2507" "llama-glm47" "llama-qwen36")
ACTION="$1"
CONTAINER="${2:-}"

in_whitelist() {
    local target="$1"
    for c in "${ALLOWED_CONTAINERS[@]}"; do
        [[ "$target" == "$c" ]] && return 0
    done
    return 1
}

case "$ACTION" in
    start)
        in_whitelist "$CONTAINER" || { echo "拒绝:容器 '$CONTAINER' 不在白名单内" >&2; exit 1; }
        docker start "$CONTAINER"
        ;;
    stop)
        in_whitelist "$CONTAINER" || { echo "拒绝:容器 '$CONTAINER' 不在白名单内" >&2; exit 1; }
        docker stop "$CONTAINER"
        ;;
    switch)
        in_whitelist "$CONTAINER" || { echo "拒绝:容器 '$CONTAINER' 不在白名单内" >&2; exit 1; }
        echo "切换到 $CONTAINER,先停掉其他模型容器..."
        for c in "${ALLOWED_CONTAINERS[@]}"; do
            if [[ "$c" != "$CONTAINER" ]]; then
                docker stop "$c" 2>/dev/null || true
            fi
        done
        docker start "$CONTAINER"
        echo "已切换到 $CONTAINER"
        ;;
    status)
        for c in "${ALLOWED_CONTAINERS[@]}"; do
            state=$(docker inspect -f '{{.State.Status}}' "$c" 2>/dev/null || echo "not found")
            echo "$c: $state"
        done
        ;;
    *)
        echo "拒绝:只允许 start/stop/switch/status,不支持 '$ACTION'" >&2
        exit 1
        ;;
esac
EOF

这个脚本支持 4 个动作

动作

用法

效果

start

manage-model-containers.sh start llama-qwen36

启动指定容器

stop

manage-model-containers.sh stop llama-qwen36

停止指定容器

switch

manage-model-containers.sh switch llama-qwen36

先停掉另外两个,再启动目标容器(一键切换,保证同时只有一个模型在跑)

status

manage-model-containers.sh status

查看三个容器各自当前状态

无论哪个动作,只要容器名不在白名单数组里,一律直接拒绝,不会执行任何 docker 命令


第二步:设置脚本权限

chmod 755 /usr/local/bin/manage-model-containers.sh
chown root:root /usr/local/bin/manage-model-containers.sh

目的:只有 root 能修改这个脚本内容,trim.hermes 账号只能"调用"它,不能"篡改"它(比如往白名单里偷偷加别的容器名)。


第三步:配置 sudoers,只放行这一个脚本

echo 'trim.hermes ALL=(root) NOPASSWD: /usr/local/bin/manage-model-containers.sh' | sudo tee /etc/sudoers.d/hermes-model-containers
chmod 440 /etc/sudoers.d/hermes-model-containers

关键点

  • 用独立文件 /etc/sudoers.d/hermes-model-containers,不要直接改 /etc/sudoers 主文件——万一写错语法,只影响这一个文件,不会把整个 sudo 体系搞坏

  • NOPASSWD 只对这一个固定路径的脚本生效,trim.hermes 依然不能执行任何其他需要 sudo 的命令(包括原始的 docker 命令本身)

验证语法是否正确

visudo -c

看到类似 /etc/sudoers: parsed OK 的提示,说明没写错。


第四步:手动测试

先用 trim.hermes 身份模拟 Hermes 的真实调用效果:

# 测试正常启停(应该成功)
sudo -u trim.hermes sudo /usr/local/bin/manage-model-containers.sh stop llama-qwen36
sudo -u trim.hermes sudo /usr/local/bin/manage-model-containers.sh start llama-qwen36

# 测试一键切换(应该自动停掉另外两个,启动目标)
sudo -u trim.hermes sudo /usr/local/bin/manage-model-containers.sh switch llama-qwen3-2507

# 测试查看状态
sudo -u trim.hermes sudo /usr/local/bin/manage-model-containers.sh status

# 测试白名单拦截(关键安全测试,这条必须被拒绝!)
sudo -u trim.hermes sudo /usr/local/bin/manage-model-containers.sh stop frigate

最后这条"停 frigate"的测试非常重要,正确结果应该是:

拒绝:容器 'frigate' 不在白名单内

并且 Frigate 监控容器不会真的被停掉。如果这条测试通过(即容器没被停),说明权限边界生效了,可以放心让 Hermes 使用。


第五步:告诉 Hermes 怎么用

回到网页 Hermes 对话框,直接用自然语言告诉它(建议写进 SOUL.md 或作为长期记忆,一次说清楚以后不用重复交代):

以后我让你切换本地模型时,请执行: sudo /usr/local/bin/manage-model-containers.sh switch <容器名>

容器名只能是以下三者之一:llama-qwen3-2507llama-glm47llama-qwen36

想查看当前哪个模型在跑,执行: sudo /usr/local/bin/manage-model-containers.sh status

除了这三个模型容器的启停/切换/查状态,不要对任何其他 docker 容器执行任何 docker 相关命令。


效果总结

场景

结果

让 Hermes 切换到 qwen36

✅ 成功,其他两个模型自动停掉

让 Hermes 查看模型运行状态

✅ 成功

让 Hermes(不管是被诱导还是误操作)执行 docker rm 删除任意容器

❌ 无权限,直接失败

让 Hermes 停掉 Frigate / Immich / CompreFace 等其他服务容器

❌ 被脚本白名单拒绝

让 Hermes 直接用原始 docker start/stop 命令(绕过脚本)

❌ 没有 sudo 权限执行 docker 命令本身,只能走脚本这一条路

核心原则:安全边界建立在系统权限层面(脚本白名单 + sudoers 精确授权),不依赖 Hermes"自觉遵守指示"——即使指示被绕过、被遗忘、或被恶意注入,权限系统本身也会拦住。


以后新增/更换模型容器怎么办

只需要改一处:

# 用文本编辑器打开脚本
nano /usr/local/bin/manage-model-containers.sh

# 找到这一行,加上新容器名
ALLOWED_CONTAINERS=("llama-qwen3-2507" "llama-glm47" "llama-qwen36" "新容器名")

保存后不需要改 sudoers 配置,脚本本身的改动会立即生效。

0
AI

评论区