我想要的不是一台机器人,而是一套安全的托管系统

    5

我想要的不是一台机器人,而是一套安全的托管系统

发布时间:2026-05-09

我最近在整理一个问题:如果让 Hermes 这类 Agent 真正接管服务器运维,到底怎样才算安全?

单纯让它能 SSH 上去,其实不难。难的是另一件事:

我希望它足够自动化,能替我处理日常问题;但又不能因为“全托管”,变成一把没有保险的万能钥匙。

所以这次我把思路重新梳理成了一套“安全全托管”的组网方案。

---

先定一个原则:全托管不等于全权限

很多人一听“让 Agent 托管服务器”,第一反应就是:给它 root,完事。

这当然最省事,但也最危险。

真正可持续的做法应该是:

Agent 有能力做事,但权限分层、操作可审计、入口可撤销。

也就是说,Hermes 可以替我巡检、重启服务、修小问题、写文档、发告警;但涉及删数据、改 SSH、防火墙、大迁移、数据库恢复这类高风险动作时,仍然要进入审批链路。

这不是不信任 Agent,而是把它当成一个正式运维系统来设计。

---

整体架构:主控 + 私有内网 + 被托管节点

我倾向的架构很简单:

Telegram / 用户指令
        ↓
Hermes 主控节点
        ↓
Headscale / Tailscale 私有内网
        ↓
被托管服务器

主控节点负责:

  • 接收 Telegram 指令
  • 生成一次性接入命令
  • 维护节点清单
  • 执行 SSH 运维
  • 跑定时巡检
  • 记录事件日志
  • 写入文档中心
  • 在异常时发告警

被托管节点只保留必要组件:

  • 一个低权限运维用户
  • 一组 sudo 白名单
  • 一个状态上报器
  • 可选的本地 worker

这样做的好处是:大多数机器不需要常驻一个复杂 Agent,只要能被主控通过内网安全访问即可。

---

新机器接入:一条命令,但不是永久后门

我希望新机器接入体验尽量简单,最好就是一条命令:

HERMES_JOIN_TOKEN="j_xxxxx" bash <(curl -fsSL https://sh.example.com/hmi)

但这里有一个关键点:

脚本本体不能携带长期秘密。

脚本只是公开逻辑,负责安装依赖、读取 token、请求主控、执行初始化。真正敏感的东西,比如组网 auth key、节点上报 token、策略配置,都应该由主控临时下发。

这个 join token 应该满足几个条件:

  • 一次性
  • 默认 30 分钟过期
  • 用完立即失效
  • 可手动撤销
  • 绑定托管等级
  • 绑定节点标签
  • 不写进长期文档

也就是说,即使这条命令泄露了,它的危害窗口也很小。

---

授权分三层:join token、node token、admin token

我把授权拆成三类。

第一类:join token

只用于新机器首次接入。

它像一张临时门票,拿它可以向主控领取接入配置,但只能用一次。接入完成后,主控立刻把它标记为已使用。

第二类:node token

节点接入后,后续用 node token 上报状态。

它的权限应该非常低:只能汇报“我是谁、状态如何、服务有没有挂”,不能拿其他节点配置,也不能执行管理动作。

第三类:admin token / 管理登录态

这个只留在主控或 Web 管理端,不应该下发到任何被托管节点。

如果后面做 Web 管理端,也应该用登录态、管理员密码、CSRF 防护和操作审计,而不是把一个裸 token 塞得到处都是。

---

托管等级:A、B、C 三档

为了避免一上来就给过高权限,我把节点托管分成三档。

A 档:观察托管

适合刚接入的新机器。

Hermes 可以:

  • 查状态
  • 看日志
  • 盘点资产
  • 写文档
  • 发告警

但不能改配置、重启服务、删文件。

B 档:日常托管

这是我认为最适合长期使用的默认档。

Hermes 可以处理低风险运维动作,比如:

  • 重启指定服务
  • 重启指定容器
  • 验证后 reload Caddy/Nginx
  • 清理可确认的日志
  • 补充 swap
  • 更新巡检文档

但它需要做到:变更前备份,变更后验证,操作写日志。

C 档:应急全托管

只在救援、迁移、严重故障时临时开启。

比如修 SSH、修防火墙、恢复备份、迁移服务、处理数据库问题。

C 档必须是临时的,用完要收权。

---

sudo 白名单比 root 全权限更适合长期托管

长期来看,我不希望默认给 Hermes:

hermes ALL=(ALL) NOPASSWD: ALL

这太粗暴。

更合理的方式是为 B 档准备一组白名单,例如允许它执行:

  • systemctl status
  • systemctl restart 指定服务
  • docker ps
  • docker logs
  • docker restart 指定容器
  • journalctl
  • df
  • free
  • ss

这样 Hermes 能处理日常故障,但不能随意删除数据、格式化磁盘、改 SSH 或改防火墙默认策略。

真正危险的动作,仍然进入 Telegram 审批。

---

组网层:只解决“怎么连上”,不代表全网互信

我更倾向用 Headscale + Tailscale 做私有内网。

但 VPN 不是万能安全边界。它只解决“怎么连上”,不应该被当成“连上就全信任”。

我会把节点分成几类:

  • admin:我的手机、电脑、Hermes 主控
  • managed:普通被托管服务器
  • worker:备用 worker 或 AI 源节点
  • infra:文件中心、监控、数据库

默认规则应该是:

admin -> managed:22
master-hermes -> managed:22
worker -> master-hermes:指定 webhook/API
managed -> infra:必要服务端口
其他默认拒绝

关键点是:

worker 不应该能横扫所有机器,普通服务器之间也不应该默认互通。

这样即使某台节点出问题,也不至于一台失守,全网裸奔。

---

Web 管理端要不要做?可以,但不要一开始做重

我觉得 MVP 阶段不需要复杂后台。

最开始用 Telegram 命令就够:

/join new
/join list
/join revoke <id>
/nodes
/node <name>
/trust <name> A|B|C

因为实际操作里,我更常用 Telegram 直接说:

生成一条 B 档 worker 接入命令。

然后主控直接回一条一次性命令。

Web 管理端可以放到第二阶段,定位成“看板 + 低风险管理”:

  • 节点列表
  • token 生成/撤销
  • 托管等级切换
  • 巡检结果
  • 操作日志
  • 风险提醒

但高危操作仍然应该走 Telegram 审批,而不是在网页上随手点一下就执行。

---

自动巡检和自愈:先小步自动化

接入后,主控可以定期做几类事情。

比如:

  • 每 5 分钟检查节点心跳
  • 每 15 分钟检查服务状态
  • 每天生成资产快照
  • 每周跑安全基线检查

自愈也要分级。

低风险可以自动做:

  • 服务挂了,重启指定服务
  • 容器异常,重启指定容器
  • Caddy 配置验证通过后 reload
  • 日志爆量时清理已确认日志

中风险可以自动做但必须汇报:

  • 补 swap
  • 重启 Docker
  • 回滚最近配置
  • 切换备用上游

高风险必须先审批:

  • 删除数据
  • 数据库恢复
  • 改 SSH
  • 改防火墙
  • 大迁移
  • 重启整机

---

文档不是收尾,是系统的一部分

这套方案里,文档不是“做完顺手写一下”,而是托管系统的一部分。

每台机器接入后,主控应该自动生成机器文档:

server/<hostname>/
├── README.md
├── inventory.md
├── hardening.md
├── network-and-ingress.md
└── next-steps.md

服务也要按服务维度单独记录:

service/<service-name>.md

这样以后维护时,可以通过机器名、服务名、域名、入口、项目名任一锚点反查,不会每次都重新问“这服务在哪台机器”。

敏感信息则统一打码,不写明文密码、token、cookie、数据库密码。

---

我最终想要的状态

这套方案最终不是为了炫技,而是为了达到一种很舒服的运维体验:

  • 新机器一条命令接入
  • 平时自动巡检
  • 小问题自动修
  • 中风险动作自动修后汇报
  • 高风险动作等我确认
  • 所有操作有记录
  • 所有资产有文档
  • 节点丢了能撤权
  • 主控能继续调度备用 worker

也就是:

我只提需求,Hermes 负责接管;但系统边界始终清楚。

这才是我想要的“安全全托管”。

不是把 root 密码丢给一个机器人,而是把 Agent 放进一套有权限、有审计、有撤销机制的运维系统里。

这样它才真的能长期用,而不是只在一次演示里看起来很酷。

消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息