Claude Code 2.1.238 让 Self-Hosted Runner 支持动态代理授权和优雅停机

2.1.238 为 self-hosted runner 新增 --proxy-authorization-command 和 --proxy-authorization-file,彻底解决企业出口代理的短期凭证问题。同时引入 --defer-shutdown-max-min,并将 headersHelper 扩展到插件 marketplace 目录请求。

发布于 来源 Anthropic

归档条目:由 AI 根据所引信源辅助生成,发布时未经逐篇审阅。责任编辑:Joe Werner。

Self-hosted runner 节点通过企业出口代理连接时动态签发授权 token 的抽象示意图

Claude Code 2.1.238 有三处变动直接影响企业部署 self-hosted runner 的方式。第一是每次连接动态生成代理授权头,第二是 SIGTERM 触发时的优雅排空,第三是扩展了 headersHelper 的信任模型,覆盖范围从 MCP 连接延伸到插件 marketplace 的目录请求。

这三项改动在 changelog 里各自只是一两行记录,但背后改变的生产运维习惯值得展开说。

企业代理认证的问题所在

企业网络通常会把 Claude Code 的出站 HTTP 流量引入一台需要认证的出口代理。2.1.238 之前,把 Proxy-Authorization 头传给代理的唯一办法,是在 runner 进程启动前把值写进环境变量。

这个方案在代理开始签发短期凭证时就失效了,OAuth 2.0 bearer token、来自 Vault 或 AWS Secrets Manager 的轮换凭证,以及基于 Kerberos/SPNEGO 的 service ticket,有效期通常只有几分钟。一个写死在启动时的环境变量,活不过几次请求。

2.1.238 给 claude self-hosted-runner 增加了两个新参数。

--proxy-authorization-command "<shell 命令>"
--proxy-authorization-file "<文件路径>"

--proxy-authorization-command 在每次新建出站连接时执行指定命令,把 stdout 作为 Proxy-Authorization 头的值。命令可以是任何能输出头部值的脚本,一次 Vault read、一次 AWS STS 调用、或者访问内部 token endpoint 的自定义脚本都行。runner 每次连接都会重新执行,因此代理侧 5 分钟的 token 有效期不再要求重启 runner 进程。

--proxy-authorization-file 从文件路径读取值,而不是执行命令。这种模式适合由外部 sidecar 或凭证刷新脚本定期把最新凭证写到固定路径,runner 每次连接时读取该文件,无需感知刷新侧的逻辑。

2.1.238 之前,绕开这个限制的常见做法是写一个 wrapper script,定时重启 runner 来刷新凭证。这样做有一个代价,runner 重启会中断所有尚未到达自然停顿点的 session,而 Claude Code 的 session 并不总能干净地 checkpoint。

SIGTERM 时的优雅停机

--defer-shutdown-max-min <分钟数> 改变了 runner 收到 SIGTERM 时的行为。加这个参数之前,容器编排(Kubernetes 缩容、ECS 排水、systemd stop)发出 SIGTERM 后,runner 会立刻退出,所有已连接的 session 被直接切断。

加了 --defer-shutdown-max-min 5 后,runner 的流程如下。

  1. 停止从服务端接受新 session。
  2. 继续为已连接的 session 提供服务。
  3. 超过指定分钟后将剩余 session park。
  4. 干净退出。

这意味着 Kubernetes 的 terminationGracePeriodSeconds、ECS 的 drain hook 和 systemd 的 stop timeout 现在可以配合 Claude Code runner 实际生效。以前这些参数设多长都没用,因为 runner 不等它们到期就退了。现在把它们配成和 --defer-shutdown-max-min 相同的时长,正在编码的 session 就有机会跑完当前轮次再被清理。

在按计划周期轮换节点的自动扩缩容环境里,这项改动的价值最直接。

headersHelper 扩展到 marketplace 目录请求

headersHelper 在 Claude Code 里已经存在数月,最初用于让 MCP server 连接时接收动态 HTTP 头。2.1.238 把它扩展到两个新请求路径。

插件 marketplace 目录请求方面,当 url 类型的 marketplace 或其 catalog 条目定义了 headersHelper 时,runner 会执行它为目录列表请求和插件包下载请求生成 HTTP 头。之前只有安装/更新步骤才会触发 headersHelper,浏览目录时的请求是未认证的。

项目级 helper 的信任门槛也收严了。定义在项目 .mcp.json 里的 headersHelper、项目或 --add-dir agent 文件里的内联 MCP server,现在必须先通过对应目录的信任对话框才能执行。这防止了恶意仓库在未经用户同意的情况下悄悄运行凭证收集脚本。在 claude -p(非交互式)模式下,headersHelper 脚本从 Claude 配置目录启动,不再继承启动 shell 的凭证环境变量。

第一项改动对部署私有插件 marketplace 的团队影响最直接。如果你维护了一套内部插件目录,2.1.238 之前 claude plugin list 访问目录 endpoint 是不带认证的;现在 marketplace 定义里的 headersHelper 覆盖了这个请求。

升级后的检查点

已有代理认证绕过方案的 runner 建议升级到 2.1.238 后迁移到 --proxy-authorization-command,不再需要维护定时重启的 wrapper 脚本。

用 Kubernetes 或 ECS 部署 runner 的团队,建议把 --defer-shutdown-max-min 与编排层的 termination grace period 对齐,避免两者出现方向相反的不匹配。

维护私有插件 marketplace 的团队,需要在 marketplace 定义里验证 headersHelper 是否能覆盖目录请求,并在更新后测试 claude plugin list 的行为。

在非交互式 claude -p 流程里用过项目级 headersHelper 的场景,要检查相关脚本是否依赖从启动 shell 继承的凭证变量,2.1.238 已经阻断了这个继承路径。

Claude Code 文档 →

帮助与联系