在服务器上安全运行 Claude Code
Claude Code 能运行您的用户能运行的任何命令。本文说明跳过权限标志改变了什么,以及如何把影响范围控制住,从内置沙箱到用完即弃的 VPS。
在服务器上安全运行 Claude Code 意味着什么
要在服务器上安全运行 Claude Code,请保持它的权限提示开启,用一个专用的非特权用户来运行它,并为无人值守的运行提供一道真正的边界,而不是依赖信任:内置沙箱、容器,或者一台不存放任何您在意的东西的用完即弃 VPS。--dangerously-skip-permissions 标志会移除模型与您的 shell 之间的审批环节。对无人值守的工作来说,这种取舍可以是合理的,但前提是它处在一道能限制单条错误命令波及范围的边界之内。本指南会说明这个标志实际改变了什么,以及如何按隔离程度递增的层级来搭建那道边界。
Claude Code 在您的机器上能做什么
Claude Code 是一个运行在您终端里的编程 agent。它以启动它的那个用户的身份读取文件、写入文件并运行 shell 命令。这正是这个工具的全部价值:它能克隆仓库、编辑代码、运行测试、读取失败信息,再修复代码,如此循环,而无需您逐条输入命令。如果您还没有在服务器上把它装起来,用 tmux 在 VPS 上运行 Claude Code 介绍了安装与会话管理。本文讲的是它就位之后,您交到它手上的那份权力。
风险就是同一句话再读一遍。一个以您的用户身份运行 shell 命令的进程,能做您的用户能做的任何事。它能读取 ~/.ssh/id_ed25519、~/.aws/credentials,以及您的用户能打开的每一个 .env 文件。它能运行 curl,把数据发送到服务器可达的任何主机。它能运行 git push --force。这个 agent 本身没有任何动机。危险在于某个任务出了岔子,或者它工作时读到的文本里夹带着别人写的指令:它抓取的一个网页,或者它被要求修复的 issue 里的一条评论。后一种情况叫做提示注入(prompt injection),正因如此,"模型通常是明智的"算不上一套安全方案。您要为出问题的那次运行做打算,而不是为平均情况。
用大白话讲权限系统
默认情况下,Claude Code 会在动手之前先询问。读取项目内的文件会静默进行,但编辑文件或运行 shell 命令时,它会先把确切的改动或命令展示给您,并等待您同意。您可以批准单次操作,也可以在本次会话余下的时间里批准这一类操作。这些批准的作用范围仅限于当次会话:退出 CLI 后,下一次会话又会从谨慎状态开始。对于您想长期保留的规则,设置文件里保存着持久的 allow、ask 和 deny 列表。例如:允许 git status,对 git push 询问,拒绝读取 .env。deny 规则始终优先。
这套设计假设有人正盯着终端,在笔记本电脑上确实如此。而在服务器上,关键往往恰恰是没人在盯着。您在 tmux 里启动一个长时间任务后就去睡觉,一个凌晨两点停下来提问的 agent,要到早上才会有进展。这就是人们在服务器上求助于跳过标志的真实原因,它要解决的问题也确实存在。本指南余下的部分,讲的是如何在不放弃全部护栏的前提下解决这个问题。
--dangerously-skip-permissions 改变了什么
claude --dangerously-skip-permissions 会关掉审批环节。编辑不再提示。shell 命令不再提示直接运行。平时守护敏感位置的受保护路径检查也会被跳过。您显式设置的 deny 规则仍然生效,少数极端操作也仍会停下来询问,但可以这样简单概括:模型决定运行什么,就会运行什么。
关于这个标志,有两点在服务器上很重要。第一,当 Claude Code 以 root 身份、或在 Linux 和 macOS 上通过 sudo 运行时,它会被禁用,因为没有提示的 root 能改动机器上的任何文件或服务。反正这个 agent 本来就该有自己的非特权账户,而这个标志强制了这一点。第二,这个标志不会以任何方式改变模型的行为。它只是把人从环节里移走,其他什么都没变,因此每一个本可被提示拦下的错误,现在都会照样执行。
于是有了这样一笔实在账。如果您跳过权限,安全问题就从"agent 会不会做坏事"变成了"一次错误操作能造成多大破坏"。您不再试图控制每一个决定,转而开始控制影响范围。答案是隔离控制,而它分成一级级的层级。
Claude Code 内置的沙箱
在进入这些层级之前,请先知道 Claude Code 现在为它运行的命令自带了一个操作系统级别的沙箱,它消除了人们求助于跳过标志的大部分理由。在 Linux 上,它用 bubblewrap 做文件系统隔离,再用 socat 把网络流量经由一个代理转发。在沙箱内,一条命令只能写入项目目录和一个会话临时目录,而且只能通过一个代理访问网络,这个代理会拿每个域名去比对一份允许列表。当某条命令第一次想访问一个新域名时,Claude Code 会询问您。
在会话内用 /sandbox 命令把它打开。在 Ubuntu 和 Debian 上,先安装它需要的两个软件包:
sudo apt install bubblewrap socat在 Ubuntu 24.04 及更高版本上,默认的 AppArmor 策略会阻止 bubblewrap 创建它所需的用户命名空间。缺少什么东西时,沙箱面板会告诉您,而 Claude Code 的沙箱文档里给出了修复它的那份简短 AppArmor 配置。
沙箱有一个自动允许模式:被沙箱包裹的命令不经任何提示就运行,因为现在这道强制边界替代了以往提示所做的工作。无法在沙箱内运行的命令会退回到普通的权限流程,因此真正不寻常的操作仍会询问。对大多数服务器工作流来说,这是跳过标志的正确替代方案,因为您用一道由操作系统强制的边界换来了少得多的提问,而不是干脆没有边界。
要老实看待它的局限。默认情况下,除非您拒绝那些路径,被沙箱包裹的命令仍能读取文件系统的大部分内容,包括凭据文件;sandbox.credentials 设置正是为此而存在的。网络代理检查的是域名,并不检查流量本身,因此像 github.com 这样宽泛的允许项,仍然给数据外泄留了空间。Docker 在它里面无法工作。沙箱把底线抬高了很多。它并不是一道完整的隔离边界,这也正是下面这些层级仍然重要的原因。
隔离控制的阶梯
三个层级,按隔离程度递增排列。挑选与机器上还住着哪些东西相匹配的那个最低层级。
第 1 级:一个专用的非特权用户。 让 agent 拥有自己的账户、自己的主目录、自己的项目目录,并且没有 sudo:
sudo adduser --disabled-password --gecos "" agent账户边界把 agent 挡在您的文件之外:您的 SSH 密钥,以及机器上其他每一个项目。它还让跳过标志变得可用,因为这个标志拒绝以 root 身份运行。这与让每个服务都以非特权用户身份运行是同一个原则,只是套用到了 agent 上。第 1 级没有约束住的东西:网络,以及机器上任何全体可读的内容。
第 2 级:一个容器。 Anthropic 发布了一个参考用的 devcontainer,它以非 root 用户身份运行 Claude Code,并用防火墙规则限制 agent 能访问哪些主机,而您自己搭建的容器也能完成同样的工作。文件系统缩小到您挂载的那些卷,出站流量缩小到容器规则所允许的范围。当服务器上还托管着您在意的其他服务时,这是合适的中间层级。它的局限在于容器共享宿主机的内核,一次粗心的挂载就会让边界失效;把 /var/run/docker.sock 交给容器,它就能触及整台宿主机。
第 3 级:一台专用的 VPS。 最强的层级也是最直白的:给 agent 一整台不存放任何您在意的东西的机器。一台小型 VPS 每月只要几美元。用新 VPS 头十分钟操作手册把它配置好,对干净状态拍一个快照,然后让 agent 去干活。那里不住任何别的东西。没有个人 SSH 密钥,只有一把作用范围限定在那一个仓库的部署密钥。没有云凭据,没有生产数据。当一次运行出了岔子,或者您只是想要一块干净的白板时,几分钟内就能恢复快照,或者销毁并重建这台机器。影响范围就是那点租金。在这套配置下,--dangerously-skip-permissions 不再吓人,因为现实中最坏的结果不过是重建一台服务器和吊销一个令牌。
这些层级可以叠加。一个被沙箱包裹、以非特权用户身份运行、跑在用完即弃 VPS 上的 agent,几乎不增加额外成本,却能让失败的故事变得平淡无奇。平淡无奇正是目标。
保护好凭据
那条能带来其余一切好处的规则:agent 的用户绝不能读取属于其他任何东西的机密。
把 API 密钥只给 agent,别给其他任何东西。把它放进一个由 agent 的用户拥有、权限为 600 的文件里,并在 shell 启动时加载它:
install -m 600 /dev/null /home/agent/claude.env
echo 'export ANTHROPIC_API_KEY=your-key-here' >> /home/agent/claude.env
echo 'source ~/claude.env' >> /home/agent/.bashrc然后堵住另一个方向。在 Debian 和 Ubuntu 上,主目录创建时往往对机器上的每个用户都可读,所以请收紧您自己的:chmod 750 /home/youruser。用 ls -ld /home/* 检查一下,把 agent 的账户能列出的任何目录都修好。
给每一个令牌限定作用范围。一个限定在单个仓库的细粒度 GitHub 令牌,或者一把每仓库一把的部署密钥,意味着一份泄露的凭据只会丢掉一个项目,而不是您的整个账户。如果您使用沙箱,请加上它的凭据设置,让 ~/.ssh 和 ~/.aws 连读取都被拒绝。并且把生产凭据完全挡在这台机器之外,因为 agent 无法泄露一个从未存在于此的机密。
Git 是那张安全网
agent 做的每一处改动都应当可审查、可回退,而只要 agent 在一个分支上工作,git 就免费给了您这两样:
git switch -c agent/refactor-auth事后用 git diff main...agent/refactor-auth 审查这次运行,把好的部分合并进来,如果这次运行毫无成果就删掉分支。在代码托管平台一侧保护好 main 分支,这样 agent 的令牌既不能推送到它,也不能对任何地方强制推送。提交历史同时充当了您睡觉时都发生了什么的审计日志,这比任何数量的终端滚动记录都更有价值。
网络也是影响范围的一部分
agent 能运行 curl。这一句话就是整个出站问题:agent 能读取的任何东西,它也能发送到某个地方,而一个被提示注入的 agent 或许真会这么做。一个普通的非特权用户根本约束不住这一点,因为任何用户都能访问服务器所能访问的一切。沙箱通过它的代理按域名来约束它。容器可以用自己的防火墙规则来约束它。而专用 VPS 从一开始就约束了有什么东西可供泄露,这是三者中最稳妥的答案。
不要试图单靠 ufw 来解决出站问题。ufw 默认允许所有出站流量,而要编写既能放行 apt、npm、git 和 Claude API 又仍然管用的出站规则,是一件琐碎且会悄无声息失效的活儿。请改在沙箱、容器或机器这一层级上选定边界,在那里,一份域名允许列表或一台空机器能干净利落地完成同样的工作。
如果您是在基于 API 构建自己的 agent,而不是运行 Claude Code,同样的思路原封不动地适用。在 VPS 上用 Claude 构建 AI agent介绍了那条路径,而它那个 agent 同样应当拥有一个专用用户、同样限定范围的令牌,以及同样用完即弃的机器。
先把机器加固好
无论您选择哪一级,在 agent 入住之前,机器本身仍然需要那些基本功:只用 SSH 密钥、禁止 root 登录、一道默认拒绝的防火墙、自动安全更新。在这里生成您的清单,照着从头做一遍:
FAQ
在服务器上使用 --dangerously-skip-permissions 安全吗?
单独用并不安全。这个标志移除了每一个审批提示,因此第一条错误命令在模型一产生出来的瞬间就会运行。当影响范围被控制住时,它就成了一笔站得住脚的取舍:至少要有一个专用的非特权用户,而对于真正无人值守的工作,则要有一个容器,或者一台只存放一个项目和一个限定范围令牌的用完即弃 VPS。绝不要在一台存放着生产凭据、或您丢不起的数据的机器上使用它。
Claude Code 有沙箱吗?
有。Claude Code 为 shell 命令自带了一个内置沙箱,用 /sandbox 命令打开。它在 Linux 上用 bubblewrap,在 macOS 上用 Seatbelt,把写入限制在项目目录内,并把网络访问经由一个只放行已批准域名的代理转发。它的自动允许模式不经提示就运行被沙箱包裹的命令,因此它像跳过标志一样减少打断,同时又保留了一道由操作系统强制的边界。它并不是一道完整的隔离边界,所以对无人值守的运行,请把它与一个专用用户或一台专用机器搭配使用。
为什么跳过标志拒绝以 root 身份运行?
因为没有权限提示的 root 能修改系统上的任何文件和任何服务,所以当 Claude Code 以 root 身份、或在 Linux 和 macOS 上通过 sudo 运行时,它会禁用 --dangerously-skip-permissions。解决办法不是去对抗这项检查。请为 agent 创建一个非特权用户,并在那里运行它;那道账户边界就是隔离控制中第一层、也是最廉价的一层。
Claude Code 能读取我的 SSH 密钥和 .env 文件吗?
它能读取它所运行身份的那个用户能读取的一切,而且即便是沙箱的默认策略,在您把凭据路径拒绝掉之前也允许读取它们。所以请让 agent 以它自己的用户身份运行,把您自己的主目录保持在 750 或更严的权限,在沙箱设置里拒绝凭据路径,并把生产机密完全挡在机器之外。一个机器从未持有过的机密,既无法被读取,也无法被泄露。
无人值守运行 Claude Code 最安全的方式是什么?
一台只用于 agent 工作的廉价专用 VPS:十分钟加固好,拍下干净快照,在一个非特权用户下开着沙箱运行 Claude Code,用一个权限 600 的文件存放 API 密钥,用一把每仓库一把的部署密钥,所有工作都在您合并前会审查的分支上进行。如果一次运行出了岔子,您吊销一个令牌、恢复快照,您拥有的其他任何东西都不受影响。