SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-10-21

为什么编码代理应该运行在一次性 VM 中

将编码代理放入可销毁的 VM,限制 SSH 密钥、浏览器配置、令牌和其他代码仓库的影响范围;小型 VPS 每月只需几美元,并支持快照回滚。

为什么一次性 VM 比你的笔记本电脑更合适

为编码代理提供一次性 VM 后,它最坏也只能摧毁一台你可以在十分钟内重建的机器。代理仍然可以获得 root 权限、安装软件包,并在无需为每一步都请求许可的情况下运行测试套件。区别在于损害发生在哪里。在笔记本电脑上,代理可以访问与你的 SSH 密钥、浏览器配置文件、.env 文件以及你曾经克隆过的所有其他代码仓库共享的主目录。在一次性服务器上,它只有一个 shell、一个代码检出目录,以及其他没有价值可供窃取的内容。

这就是全部理由。这个理由关注的是不对称性,而不是发生概率。即使是在配置完善的笔记本电脑上,谨慎的代理几乎每次也都不会出问题。但一旦出问题,代价就不只是一次错误提交。如果你有备份,还需要从备份恢复。

明确影响范围,再讨论争议

影响范围是指某个进程能够访问的一组对象。对于以普通用户身份运行在普通机器上的代理,其影响范围比大多数人想象的更大。

其中包括 ~/.ssh/id_ed25519。它通常未加密,因为您不想再反复输入密码短语。其中包括 ~/.aws/credentials 和 ~/.config/gh/hosts.yml,它们本来就是纯文本。其中包括 ~/code 下的所有同级代码仓库,包括那些本地环境文件中含有生产环境连接字符串的仓库。其中包括 shell 历史记录,里面可能保存着您曾粘贴过一次的令牌。其中还包括笔记本电脑所连接的网络。该网络通常是家庭或办公网络,并且可能运行着无需身份验证即可访问的服务。

这些风险都不需要恶意代理。只需要一条看似正确但实际错误的命令。例如,在未设置 BUILD_DIR 时运行 rm -rf "$BUILD_DIR"/*,该命令会展开为 /*,绕过 GNU rm 默认拒绝删除 / 本身的保护;在错误目录中执行 git clean -xfd;执行会连同本地数据库一起删除的 docker system prune -af --volumes;或者在主目录上运行看似有帮助的 chmod -R 777。代理所接受训练的数据,来自教会其他人这些命令的同一个互联网。

真正保护您的机制不是代理的判断力,而是承载损害的那台机器本来就是一台您愿意舍弃的机器。

成本核算很乏味,但这正是重点

一台小型 VPS 每月只需几美元。恢复一台开发者笔记本电脑需要一天时间;而这还算理想情况,因为你能立即发现问题,并且事先有备份。

用你自己的数字计算。先取你的时薪,再乘以重新安装操作系统、恢复主目录、轮换 SSH 密钥、轮换个人访问令牌以及重新克隆 20 个代码仓库所需的小时数。将这个结果与提供商销售的最小规格服务器 12 个月的费用进行比较。按几年发生不到 1 次事故计算即可达到盈亏平衡,而且事故不必是灾难性的。一整个下午因本地环境损坏而损失的时间,已经足以抵消一年的费用。

计算的另一部分是快照。在高风险操作前创建快照,可以将糟糕结果从“恢复我的整个工作环境”变成“回滚,然后尝试不同的提示词”。你正在用来输入本文的笔记本电脑无法提供这个选项,因为在把电脑当作工作台使用时,你无法对它创建快照。

截至 2026 年 10 月的现状

对于“代理应该在哪里运行”,有 3 个合理答案。它们都在权衡同样的两点:隔离边界有多强,以及您能接受多少配置工作。

本地微型 VM。 此类工具会在您自己的硬件上启动真正的虚拟机,将代码仓库挂载到虚拟机中,并让代理在其中拥有 root 权限。clawk 是当前的示例,其定位正是本文的核心观点:为编码代理提供一次性的 Linux VM,而不是让它运行在您的笔记本电脑上。截至 2026 年 10 月,它面向 Apple silicon 上的 macOS 14 及更高版本,并通过 Firecracker 实验性支持 Linux;使用 brew install clawkwork/tap/clawk 安装。在代码仓库中运行 clawk 可启动沙箱并连接代理,运行 clawk down 可停止沙箱,运行 clawk destroy 可删除沙箱。其隔离边界由 hypervisor 提供,强度较高。限制在于,VM 运行在您随身携带的设备上,因此会占用本机内存;合上笔记本电脑后,VM 也会停止。

容器。 Docker 是大多数人已经安装的方案,而且确实很有用。

docker run --rm -it -v "$PWD:/work" -w /work --network none ubuntu:24.04 bash

--rm 会在退出时删除容器,--network none 则完全禁止容器联网。这对于构建或测试运行来说是一个不错的默认设置。但请明确其限制:容器共享宿主机内核,因此内核漏洞可能成为逃逸路径;一旦添加 --privileged,或挂载 /var/run/docker.sock 让代理能够“使用 Docker”,隔离边界就会消失。将 Docker socket 挂载到容器中,等同于向该容器授予宿主机上的 root 权限。

可重建的普通 VPS。 无需引入新工具,具备真正的内核隔离边界,支持服务商快照,并且在您关闭笔记本电脑后仍会继续运行。本指南其余部分介绍的就是这种模式。它也最适合运行时间较长的代理任务,因为一个需要 4 小时的任务不会因为您下班回家而停止。

VPS 模式:为代理创建专用用户

从已加固的服务器开始。新 VPS 上的前十分钟涵盖与代理无关的基础工作:更新系统、创建非 root 登录、仅使用密钥的 SSH,以及配置防火墙。

然后创建一个仅供代理使用的账户。这样,即使代理内部发生错误,也无法影响服务器上的其他内容。

sudo adduser --disabled-password --gecos "" agent
sudo install -d -m 700 -o agent -g agent /home/agent/work
sudo -u agent -H bash -lc 'id; ls -la ~'

--disabled-password表示没有可供猜测的密码。您可以通过sudo -u agent或 SSH 密钥访问该账户。请注意,agent有意不属于sudo组。拥有sudo的代理可以获得 root 权限,而 root 可以读取其他所有用户的文件,因此刚刚建立的隔离就失去了意义。如果代理确实需要安装软件包,这说明它应使用自己拥有的独立服务器,而不是在共享服务器上授予它sudo。一般规则请参阅VPS 上 Linux 用户的最小权限原则。

在信任代理之前,先检查隔离边界。以agent用户身份尝试列出其账户的主目录:

sudo -u agent ls /home/you

您应该看到ls: cannot open directory '/home/you': Permission denied。如果看到的是文件列表,说明其他用户可以读取您的主目录。代理也就可以读取其中未单独限制访问权限的内容,例如全局可读的.env文件。使用sudo chmod 700 /home/you修复。此测试不会保护您的 SSH 私钥:如果其他用户可以访问私钥文件,ssh 会忽略该文件。因此,任何实际可用的密钥都已经无法被agent读取,与主目录的权限模式无关。

完全不要将凭据放在该机器上

如果将生产环境的机密复制到一次性机器上,就失去了使用一次性机器的意义。规则很简单:该机器上的任何内容都不应是你不愿意在今天下午轮换的凭据。

对于 git,应转发 SSH agent,而不是复制密钥。私钥保留在你的笔记本电脑上,连接中只传递签名请求。

ssh -A agent@203.0.113.10
ssh -T git@github.com

第二条命令应返回 Hi yourname! You've successfully authenticated, but GitHub does not provide shell access.。这证明 git push 在服务器上没有密钥文件的情况下也能正常工作。随后在该机器上运行 ls -la ~/.ssh,确认其中不存在私钥。

Agent 转发有一个必须明确说明的实际风险:在你连接期间,任何拥有该服务器 root 权限的人都可以使用转发的套接字,以你的身份进行身份验证。如果服务器上的其他用户只有你自己,这种权衡可以接受。在共享服务器上则不可接受,此时最好使用限定为单个仓库的部署密钥。相关选项见 SSH 密钥管理基础。

对于 API 密钥,应为 agent 单独创建一个密钥,并设置独立的消费限额。将密钥存储在由 agent 用户拥有、权限为 mode 600 的文件中。销毁机器时,应撤销该密钥,而不是猜测它是否已经泄露。按密钥单独查看模型消费,也是让 VPS 上的 AI agent 成本控制中的数字保持可预测的方式。

限制代理在网络上的可访问范围

文件系统隔离只是边界的一半。另一半是出站流量控制,即限制进程可以连接的目标。Linux 可以根据创建进程的用户过滤出站流量,这正好适用于此场景。

sudo iptables -A OUTPUT -m owner --uid-owner agent -o lo -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner agent -p udp --dport 53 -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner agent -p tcp --dport 443 -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner agent -j REJECT

规则按顺序读取,因此最后的 REJECT 会匹配前面规则未允许的所有流量。以代理身份进行测试:

sudo -u agent curl -sS -m 5 http://example.com

此命令应立即失败,并显示 curl: (7) Failed to connect to example.com 错误。后续提示文本会因 curl 版本而异,因为拒绝规则会立即返回响应,而不会让连接一直等待。对同一主机发起 HTTPS 请求仍应成功。

需要明确两点限制。第一,除非保存规则,否则这些规则会在下次重启时丢失;可以使用 sudo apt install -y iptables-persistent,然后使用 sudo netfilter-persistent save 保存。第二,这种过滤针对的是端口和地址,而不是名称。允许 443 端口就意味着允许访问互联网上所有 HTTPS 主机。这样既可以访问模型 API,也可以访问 pastebin。真正按域名限制访问,需要让流量经过能够读取请求主机名的代理;对于大多数单人开发环境而言,这需要配置更多组件。只声明你实际实现的能力:在一台你已做好丢失准备的机器上,提供端口级出站流量控制。

在任务之间恢复到干净状态

每个任务都使用干净状态,是一个常被低估的好处。某个代理处理上一个工单时运行了 3 个小时,留下了已安装的软件包、只完成一半的迁移、过期的 node_modules,以及一个包含未审核更改的 Git 工作树。下一个任务会继承全部这些内容,而您需要消耗审核时间来判断哪些问题属于哪次运行。更受限的代理一开始就会留下更少的内容,因此,将一次性机器与促使代理采用最小可行更改的技能结合,可以让差异和残留状态都保持在易于审核的范围内。

最简单的方法是为每个任务创建一个全新的检出副本。

sudo -u agent -H bash -lc 'rm -rf ~/work/repo && git clone git@github.com:you/repo.git ~/work/repo'

更可靠的方法是在机器设置完成后、任何代理使用它之前,创建一次提供商快照。恢复该快照后,整个系统(包括软件包)都会回到已知状态。大多数提供商通过控制面板或 API 提供此功能,而不是将其作为机器上的命令,因此具体步骤取决于您的提供商。关键是要在机器仍处于未使用状态时创建快照。

需要保留的内容都不要放在一次性机器上。通常,这意味着推送分支,而不是将其长期保存在本地。如果机器上确实保存了您不希望丢失的内容,请使用VPS 上的 restic 备份正确备份。只有在销毁机器确实不会引发问题时,一台可以销毁的机器才真正有用。

如果您希望拥有多个隔离环境,但不想为多个服务器付费,可以让一台配置更高的 VPS 直接托管客户机 VM。VPS 上的嵌套虚拟化介绍了具体实现方式,包括如何检查您的提供商是否允许此功能。隔离在这里也有两面性。如果您希望同一台机器上的两个代理彼此协调,而不是完全隔离,那么可以使用一个 Claude Code 会话直接向另一个会话发送文本,无需让每次交接都经过您。

真正谨慎使用笔记本电脑时完全可以

对此应实事求是,因为过度夸大隔离效果会让人不再听取建议。

如果您会在每条命令执行前进行审核,笔记本电脑完全可以胜任。权限提示确实是一项有效控制,而在服务器上安全运行 Claude Code会说明每个权限级别实际阻止哪些操作。如果您的工作只涉及一个代码仓库,且这台机器上没有任何生产环境凭据,那么潜在影响范围已经很小。如果代理会话时间较短,并且有人监督,暴露窗口也会相应缩短。

一旦跳过这些提示,情况就会改变。现在自动模式已成为 Claude Code 的默认模式,全新安装后,在修改文件或运行命令前不再征求您的确认,这一点尤其值得提前考虑。无人值守运行、通宵任务,以及您批准计划后离开的任何工作流,都会移除原本负责遏制风险的人工检查。这时就必须由机器来执行控制。同样,任何扩大代理操作范围的方式也适用,包括在 VPS 上运行编码代理并同时处理多个代码仓库。

这个决定并不取决于您有多信任模型,而取决于模型出错时,它身边还有什么。

FAQ

容器是否足以为编码代理提供隔离?

对于大多数工作,足够,但必须满足两个条件。容器不能以 --privileged 运行,也不能将 /var/run/docker.sock 挂载到容器中,因为这两种情况都会为进程提供一条获取主机 root 权限的路径。容器与主机共享内核,因此其隔离边界弱于虚拟机。如果代理运行的是从互联网获取的不受信任代码,优先使用真正的虚拟机或独立服务器。

代理是否需要服务器上的 sudo 权限?

不需要。授予 sudo 权限会破坏你建立的隔离,因为 root 可以读取服务器上其他所有账户的数据。创建代理用户时不要授予 sudo 权限,只允许它写入自己的工作目录。如果任务确实需要安装软件包,应为代理提供一台由它独占的完整机器,而不是让它在共享机器上获得 root 权限。

如何让代理推送到 git,同时不将我的 SSH 密钥放到服务器上?

连接时使用 ssh -A 转发 SSH agent。签名请求会通过连接传输,私钥仍保留在你的笔记本电脑上,因此 ssh -T git@github.com 可以完成身份验证,git push 也能正常工作,而服务器上无需保存私钥。需要注意的是,在你保持连接期间,该服务器上的 root 可以使用转发的套接字。因此,在与其他人共享的机器上,应使用限定仓库范围的 deploy key。

代理需要多大规格的 VPS?

代理的工作主要是编辑文件、运行构建和执行测试,因此应根据构建需求而不是模型需求确定机器规格。托管模型运行在服务提供商的硬件上,只会增加网络流量,几乎不会增加本地负载。代理本身仍然设定了最低配置:截至 October 20, 2026,Claude Code 的系统要求将 4 GB RAM 列为最低值。即使只是脚本任务,也应从 4 GB 起步;如果代码仓库会构建容器或编译大型项目,则应升级到 8 GB。

应多久销毁并重建一次机器?

当机器状态无法解释时应重建;只要服务器上的凭据可能已暴露,也至少应重建一次。任务之间使用全新 checkout 可以处理日常状态漂移,而在首次运行代理前创建快照,可以提供一个可恢复的干净系统映像。如果重建成本很高,说明有重要数据或状态正存放在一台你称为临时机器的服务器上。

这篇文章对您有帮助吗?