SpyBara
Go Premium

self-hosted-environments-deploy.md 2026-10-09 23:02 UTC to 2026-10-10 14:00 UTC

This page contains 133 additions and 18 deletions.

2026
Fri 2 22:59 Sun 4 23:58 Mon 5 23:58 Tue 6 23:59 Sat 10 15:01

將自託管環境部署到生產環境

在生產環境中執行自託管執行器:安全強化、網路出站流量控制、Git 認證、Kubernetes 和 Compose 配方,以及故障排除。

自託管環境在您部署在網路內的執行器上執行 Claude Code 雲端工作階段,在生產環境中,這些工作階段代表所有可以向環境分派工作階段的人執行模型導向的程式碼。本頁面適用於將正常運作的環境帶入生產環境的操作員。它按部署順序進行:在連接真實系統之前要鎖定什麼、執行器群需要的出站流量、工作階段如何向您的 Git 主機進行身份驗證、部署配方本身,以及當工作階段出現故障時要檢查什麼。

強化您的部署

自託管執行器代表所有可以向其環境分派工作階段的人在您的基礎設施上執行任意的、模型導向的程式碼。這是您 Anthropic 組織的任何成員,以及任何可以在所有者路由到環境的範圍內啟動 Claude Tag 頻道工作階段的人。在將環境連接到生產系統之前,請逐項進行:

  • 臨時的、每個工作階段的容器:在新鮮容器或 VM 中執行每個執行器程序,該容器或 VM 在程序退出時被銷毀,使用 --capacity 1 和預設的 --drain-grace-sec 0,以便每個容器恰好服務一個工作階段。在更高的容量或正的清空寬限期下,一個容器服務來自同一鎖定所有者的多個工作階段;請參閱執行器生命週期。不要在執行器重新啟動之間重複使用檔案系統,除非在刻意的預熱簽出設定中,並且永遠不要跨所有者。

    • 當執行器停止工作階段時,它不會向在其 shell 命令結束後仍在執行的程序傳送任何訊號,例如已轉為常駐程式(daemonized)的服務。銷毀容器或 VM 會結束該程序。
  • 映像中沒有廣泛的憑證:不要包含長期的 SSH 金鑰、雲端提供商憑證,或授予超過工作階段所需權限的個人存取 token。工作階段期間使用的憑證,例如推送或 API token,應從您的包裝器指令碼按工作階段產生。初始複製會在包裝器執行之前發生,因此請使用 checkout 生命週期 hook 處理,或在工作階段的所有儲存庫都位於 github.com 上時使用 --use-anthropic-git-proxy。關於這兩者,請參閱設定 git。

  • 讓工作階段無法接觸主機的 GitHub 憑證:Claude 可以使用工作階段能讀取的任何 GitHub 憑證,並擁有該憑證所授予的任何存取權。請將執行器主機本身範圍廣泛的 GitHub 憑證排除在工作階段可讀取的任何位置之外。此類憑證可能是個人存取 token、gh auth login 為您的帳戶儲存的 token,或執行器環境中的 GH_TOKEN。

    • 使用 Anthropic 管理的 git 時:若有此類憑證,Claude 會直接連線到 GitHub,而不是透過 Anthropic 管理的 git。
    • 不使用 Anthropic 管理的 git 時:如果您依照在映像中提供 git 設定所述嚴格限制其範圍,複製憑證可以保留在映像中。
  • 將環境祕密保留在執行工作階段的主機之外:環境祕密可以註冊執行器並拾取在環境上排隊的任何工作階段。在固定群中,它存在於每個執行器主機上,任何工作階段的程式碼都可以讀取祕密檔案。優先使用按需執行器,其中祕密保留在協調器主機上,該主機永遠不執行使用者程式碼,每個執行器接收單次使用的工作單據,該單據恰好註冊一個執行器。在固定群中,將環境祕密檔案視為可由每個工作階段讀取,並在任何懷疑的工作階段洩露後輪換祕密。

  • 預設拒絕網路出站流量:在每個環境上限制執行器和工作階段容器的出站流量在您自己的網路邊界;預設拒絕出站流量涵蓋允許什麼以及為什麼。

  • 最小權限主機 IAM:附加到執行器主機的計算身份,例如執行個體設定檔或節點服務帳戶,應僅授予執行器本身需要的內容。工作階段應通過您的包裝器指令碼而不是繼承主機的身份來獲得自己的認證。

  • 阻止工作階段的雲端中繼資料端點:將工作階段保留在主機身份之外需要阻止它們對雲端中繼資料端點的存取,子網級出站流量原則不會攔截連結本地中繼資料流量,因此在容器本身中阻止它:

    • IMDSv2,跳數限制為 1
    • GKE Workload Identity,具有中繼資料隱藏
    • 工作階段容器網路命名空間中 169.254.169.254 的明確拒絕

    該阻止也適用於您的包裝器指令碼和生命週期鉤子,因為它們共享容器。使用工作階段 JWT對您自己的令牌服務進行身份驗證,通過允許列表出站流量,或使用基於檔案的 Web 身份,例如 Amazon EKS 上的 IAM Roles for Service Accounts (IRSA)。

  • 每個執行器的檔案系統隔離:每個執行器程序獲得自己的工作目錄,主機上沒有其他程序可以讀取或寫入。使 --hooks-dir、包裝器指令碼和主機的 ~/.claude/ 對工作階段唯讀,無論是內置在映像中還是以唯讀方式掛載。

  • 分派沒有每個環境的存取控制:您 Anthropic 組織的任何成員都可以向其任何環境分派工作階段。如果所有者將 Claude Tag 頻道路由到環境,Claude Tag 存取設定允許的任何人都可以啟動在那裡執行的頻道工作階段。預設情況下,這是連接的 Slack 工作區中的任何人,無論是否有 Claude 帳戶。將每個執行器主機視為可由所有可以向其分派的人進行程式碼執行,並且只在執行器主機上放置所有這些人都被允許讀取的資料和認證。--lock-to-account限制給定主機執行哪個帳戶的工作階段,但它不會縮小誰可以分派到環境中。要使自託管環境成為唯一的選擇器選項,所有者可以從雲端環境頁面隱藏整個組織的 Anthropic 託管環境。

  • 強制執行儲存庫設定防護:使用 --confine-repo-settings選擇防護模式。預設的 warn 記錄違規並仍然生成工作階段,enforce 拒絕工作階段,off 禁用掃描。執行器掃描每個儲存庫的已提交設定以查找:

    • 在該工作階段自己的工作區之外解析的授予:additionalDirectories 項目、permissions.allow 中的 Edit、Write 或 NotebookEdit 規則,或 sandbox.filesystem.allowWrite 或 allowRead 項目
    • 非空的 env 塊
    • 操作員姿態覆蓋,例如 sandbox.enabled: false

    防護無論 --trust-workspace如何都會執行,並且不涵蓋儲存庫鉤子、.mcp.json 或 Bash 規則;請參閱權限和工具批准以了解這些授予應該在哪裡。

網路要求

執行器及其生成的工作階段子項進行出站連接到以下主機。將工作階段容器出站流量限制為這些主機和工作階段需要到達的特定內部服務;預設拒絕出站流量涵蓋如何以及為什麼。

這些主機始終是必需的:

主機 連接埠 用途
api.anthropic.com 443、HTTPS;WSS 用於 Anthropic 管理的 Git 執行器控制平面和工作階段串流、模型推理、功能旗標、產品分析、JWKS 金鑰提取、提交簽名,以及設定 --use-anthropic-git-proxy 時的 Anthropic 管理的 Git
您的 Git 主機,例如 github.com 或您的 GitHub Enterprise 主機 443 或 22 在執行器工作階段所使用的每個 Git 主機上複製和推送儲存庫。對於使用 --use-anthropic-git-proxy 的執行器,請參閱何時仍需要 github.com 路徑。

使用 --use-anthropic-git-proxy 的執行器會將其 github.com Git 流量路由通過 api.anthropic.com,因此不需要 github.com 的 Git 主機路徑。如果您設定了 --push-outcome-on-release 或從 post-session hook 推送,則仍需要該路徑。

這些主機是否需要取決於您的配置:

主機 連接埠 何時需要
downloads.claude.ai 443 在安裝時,當您使用原生安裝程式在主機上安裝或更新 Claude Code 時;install.sh 指令碼本身是從 claude.ai 提供的。在工作階段執行時,僅當工作階段從官方 Anthropic 市場安裝外掛程式時。
storage.googleapis.com 443 在工作階段執行時,用於 /plugin 中顯示的外掛程式安裝計數和中繼資料。
code.claude.com 和 claude.com 443 內置 claude-code-guide 代理的文件查詢和工作階段期間預先批准的 WebFetch 請求。阻止這些主機只會影響文件查詢。
*.frame.claudeusercontent.com 443 僅當工件工具對您組織中的工作階段可用時;預設值因方案而異,根據那裡的可用性表。在執行器上設定 CLAUDE_CODE_DISABLE_ARTIFACT=1 以保持工具禁用,無論組織設定如何。
registry.npmjs.org 443 當工作階段安裝外掛程式時,用於提取 npm 源外掛程式套件和安裝外掛程式的 Node.js 依賴項,或當 npx 啟動的 MCP 伺服器執行時
http-intake.logs.us5.datadoghq.com 443 Anthropic 操作指標。僅當設定 CLAUDE_CODE_BYOC_ENABLE_DATADOG=1 時;在自託管環境中預設關閉。
browser-intake-us5-datadoghq.com 443 Anthropic 錯誤報告上傳,僅在為工作階段帳戶啟用錯誤報告時發送。由 DISABLE_ERROR_REPORTING=1 或 DISABLE_TELEMETRY=1 抑制。
您的雲端供應商用於模型請求、模型查詢和更新憑證的端點,例如 bedrock-runtime.us-east-1.amazonaws.com 或 aiplatform.googleapis.com 443 僅當執行器將模型請求傳送至 Amazon Bedrock 或 Google Cloud 的 Agent Platform 時

您不需要為執行器或工作階段流量將這些主機加入允許清單:

  • statsig.anthropic.com、*.sentry.io、claude.ai 和 platform.claude.com:這些主機出現在一些較舊的企業網路檢查清單中,但執行器不會連線到它們。功能旗標提取會前往 api.anthropic.com,而執行器使用環境祕密而非互動式 OAuth 進行身分驗證。
  • mcp-proxy.anthropic.com:自託管工作階段不使用它。當您的組織啟用連接器傳遞時,您組織的 claude.ai 連接器會透過 api.anthropic.com 到達工作階段。請參閱 MCP 伺服器。

以下主機端流程確實會連線到 claude.ai,因此請從出站流量允許連線到它的主機執行這些流程,而不是擴大工作階段容器的出站流量:

  • 單行安裝程式:在安裝時從 claude.ai 提取 install.sh。
  • 互動式 claude auth login:透過 claude.ai、claude.com 和 platform.claude.com 登入。引導式設定、doctor 的已登入模式和 CI 分派會使用它。您用來登入的瀏覽器也會從 hcaptcha.com、*.hcaptcha.com 和 challenges.cloudflare.com 載入 claude.ai 登入頁面的瀏覽器檢查。

預設拒絕出站流量

在網路區段或命名空間中部署執行器和工作階段容器,其出站流量限制為網路要求表中的主機、您的 Git 主機和工作階段需要到達的特定內部服務。該產品無法驗證或強制執行此操作,因此在每個環境上的您自己的網路邊界應用它。工作階段程式碼是模型導向的,可以嘗試連接到任意主機;網路層的預設拒絕出站流量限制這些嘗試可以到達的位置。這無論權限模式如何都適用:預設預先批准的工具集已包括 Bash,因此 shell 出站流量在沒有自動模式的情況下執行而不提示。

有關每個工作階段發出的遙測詳細資訊以及如何關閉它,請參閱遙測。

向出站代理進行身份驗證

某些企業出站代理在每個連接上需要 Proxy-Authorization 標頭。該標頭中的令牌通常輪換得太快,無法寫入您在 HTTPS_PROXY 中設定的代理 URL。像往常一樣將 HTTPS_PROXY 或 HTTP_PROXY 設定為您的代理 URL,然後設定 --proxy-authorization-command 或 --proxy-authorization-file 以告訴執行器從何處讀取標頭值。兩個旗標都需要 Claude Code v2.1.238 或更新版本。

選擇 `Proxy-Authorization` 值的來源

選擇與您如何產生 Proxy-Authorization 令牌相符的旗標:

執行器拒絕啟動的配置

每個旗標也有環境變數形式,在執行器 CLI 旗標參考中列在其旁邊。在執行器聯繫您的代理或控制平面之前,它檢查旗標及其變數,並在三種情況下拒絕啟動:

  • 兩個旗標都設定:一個旗標加上另一個旗標的環境變數計為設定兩個。
  • 沒有代理 URL:HTTPS_PROXY 和 HTTP_PROXY 都不包含 http:// 或 https:// URL。執行器以大寫或小寫讀取兩個變數,不查詢 ALL_PROXY。
  • 任一旗標傳遞給協調器子命令:self-hosted-runner orchestrator 不接受旗標或其環境變數。改為將旗標傳遞給協調器啟動的每個執行器。

設定代理授權旗標時執行器更改的內容

設定任一旗標後,執行器啟動自己的偵聽器並通過該偵聽器發送來自自己、其生命週期鉤子和其工作階段的代理流量。偵聽器在前往您的代理的途中添加 Proxy-Authorization 標頭。

  • 偵聽器:偵聽器是 127.0.0.1 上的轉發代理。執行器在向控制平面註冊之前啟動偵聽器,如果偵聽器無法啟動則在啟動時退出。
  • 代理變數:執行器重寫您設定的 HTTPS_PROXY 和 HTTP_PROXY 中的任一個,使其指向偵聽器。該重寫的值到達執行器本身、其生命週期鉤子和它執行的每個工作階段。
  • 令牌輪換:輪換的令牌無需重新啟動即可生效。對於偵聽器打開到您的代理的每個連接,執行器再次執行您的命令或讀取您的檔案並將結果添加為標頭。
  • 工作階段環境:工作階段僅通過偵聽器到達您的代理。在每個工作階段的環境中,執行器移除 ALL_PROXY、移除您未設定的 HTTPS_PROXY 或 HTTP_PROXY 的任何拼寫,並將 NO_PROXY 固定到執行器自己的值。
  • 日誌:執行器永遠不會記錄標頭值。

配置 Git

執行器管理儲存庫簽出但預設不配置 Git 身份或認證。您控制執行器的映像和程序環境,因此您控制 Git 配置。選擇兩種方法之一:

  • 讓執行器配置 Git:使用 --configure-git 啟動執行器,以使其寫入 Anthropic 託管工作階段使用的相同身份和提交簽名配置
  • 在映像中提供 Git 配置:自己設定身份和推送認證,例如在您自己的機器人身份下提交

對於 github.com 上的儲存庫,您也可以使用 --use-anthropic-git-proxy 啟動執行器,或設定 CLAUDE_RUNNER_USE_GIT_PROXY=1,請 Anthropic 為執行器的工作階段提供 Git 服務。

執行器主機上的 Git 版本下限:--configure-git SSH 提交簽名需要 Git 2.34 或更新版本,--use-anthropic-git-proxy 需要 2.32 或更新版本,從 --push-outcome-on-release 推送的分支恢復工作階段需要 2.29 或更新版本。如果您省略所有三個並自己管理 Git 身份,Git 2.24 就足夠了。

讓執行器配置 Git

使用 --configure-git 啟動執行器,或設定 SELF_HOSTED_RUNNER_CONFIGURE_GIT=1,以使其在啟動時寫入全域 Git 配置:

  • user.name = Claude 和 user.email = noreply@anthropic.com,與 Anthropic 託管工作階段相符
  • SSH 格式提交和標籤簽名,通過執行器管理的填充程式路由,該填充程式使用工作階段自己的認證通過 Anthropic 的簽名服務簽名每個提交。簽名可在 GitHub 上針對 Anthropic 的已發佈 SSH 簽名金鑰進行驗證。
  • push.negotiate = true,因此 Git 在打包推送之前詢問您的 Git 主機它已經擁有哪些提交。需要 Claude Code v2.1.257 或更新版本。
  • core.hooksPath 指向執行器管理的 hook 目錄。其 commit-msg 和 prepare-commit-msg hook 會為每個提交加上工作階段建立者的 Co-authored-by: trailer。該 trailer 由 CCR_SESSION_ACCOUNT_EMAIL 中的電子郵件建立,當該變數未設定時則省略。如果您的映像已設定 core.hooksPath,且執行器未使用 Anthropic 管理的 Git,執行器會保留您的設定、跳過安裝這些 hook,並列印 [runner:git] 警告。

提交簽名需要 Git 2.34 或更新版本;執行器在啟動時檢查並在您的 Git 較舊時以錯誤退出。此旗標不配置推送認證,您仍在映像中提供。

在 v2.1.280 或更新版本的執行器上,您從 checkout 或 post-session 生命週期 hook 所建立的提交也會以工作階段身分簽署,但不會加上 Co-authored-by: trailer。生命週期 hook 內的 Git 設定說明了執行器在這些 hook 內固定的 Git 設定。

無論是否使用 --configure-git,Claude Code 都會指示 Claude 在提交訊息結尾加上 Claude-Session: <url> trailer,並在 pull request 描述結尾加上工作階段的 URL。若要省略兩者,請在執行器主機的 ~/.claude/settings.json 中將 attribution.sessionUrl 設為 false,然後重新啟動執行器。

在映像中提供 Git 配置

Git 身份對任何提交都是必需的。在您的 Dockerfile 中系統範圍設定它,以便配置無論執行器程序以哪個使用者身份執行都適用:

RUN git config --system user.name "Claude" && \
    git config --system user.email "noreply@anthropic.com"

沒有身份,git commit 失敗並顯示 Please tell me who you are,工作階段無法取得進展。您可以改用自己的機器人身份;執行器不會覆蓋這些值。

請勿將長期或範圍廣泛的推送憑證內建到共用的執行器映像中:映像中的憑證可供該映像執行的每個工作階段使用,無論是誰啟動的。請改為從您的包裝指令碼為每個工作階段產生短期、最小範圍的 token,並使用從工作階段 JWT 解碼出的工作階段建立者身分。搭配每個工作階段專用的臨時容器(這需要 --capacity 1),使任何憑證都不會比產生它的工作階段存活更久;請參閱強化部分。

如果您必須在映像級別配置推送認證,例如對於唯讀部署金鑰,請盡可能緊密地限制它們:

  • SSH 部署金鑰限制為一個儲存庫,帶有 url.<base>.insteadOf 重寫
  • 傳回最小範圍 token 的 credential.helper
  • 指向範圍狹小之金鑰的 GIT_SSH_COMMAND

您配置的任何機制都必須無需提示即可工作,因為執行器的內置複製和提取禁用 Git、SSH 和 Git Credential Manager 否則會顯示的提示:

  • 執行器設定 GIT_TERMINAL_PROMPT=0,因此 Git 不會要求使用者名稱或密碼。
  • 執行器使用 BatchMode=yes 執行 SSH,附加到您的 GIT_SSH_COMMAND(如果您設定了),因此 SSH 不會要求密碼短語或主機確認。
  • 執行器設定 GCM_INTERACTIVE=never,因此 Git Credential Manager 不會打開登入對話框。
  • 執行器清除 core.askPass,因此如果您使用 askpass 幫助程式,請改為通過 GIT_ASKPASS 環境變數設定它。

如果您的 Git 主機拒絕認證,或您沒有配置認證,執行器會重試幾次,然後失敗儲存庫準備當儲存庫是工作階段推送結果的儲存庫時。對於工作階段僅從中讀取的儲存庫,Troubleshooting 涵蓋執行器何時改為跳過它。執行器不會將這些設定傳遞到工作階段的環境中。

保持您在 GIT_SSH_COMMAND 或 GIT_ASKPASS 中命名的任何程式,工作階段無法寫入它,就像強化檢查清單要求鉤子目錄和包裝器指令碼的方式一樣。該程式命令行上的任何金鑰或檔案也是如此。執行器自己的 Git 在複製或提取時執行該程式。

如果簽出目錄由與執行器程序不同的 uid 擁有,Git 拒絕對其進行操作;添加 safe.directory:

RUN git config --system --add safe.directory '*'

使用 Anthropic Git 代理

使用 Anthropic Git 代理伺服器(也稱為 Anthropic 管理的 Git)時,執行器映像不需要為工作階段本身準備任何 SSH 金鑰、憑證輔助程式、.netrc 或其他 Git 憑證。執行器會改為請 Anthropic 為其工作階段提供 Git 服務。對於 Anthropic 所服務的使用者工作階段,執行器的複製以及工作階段自己的提取和推送都會經過 Anthropic,Anthropic 使用為工作階段建立者儲存的 GitHub OAuth token。Anthropic 如何為工作階段提供 Git 服務說明了機器人和 agent 工作階段的情況。

除非您將其開啟,否則 Git 代理伺服器是關閉的。以自己的憑證連線到 Git 主機的執行器不需要它,其 Git 可搭配任何 Git 主機運作。

相對地,Git 代理伺服器會限制執行器支援的範圍,並改變執行器所需的條件:

請將非機密的 Git 設定(例如身分和 safe.directory)保存在系統 Git 設定中。

開啟 Anthropic Git 代理伺服器

在使用 --use-anthropic-git-proxy 啟動執行器之前,請確認執行器主機符合以下每項要求。當容量或 Git 要求未滿足時,執行器會拒絕啟動:

  • Claude Code v2.1.267 或更新版本:較早的版本接受該旗標,但不會回報請 Anthropic 提供 Git 服務的請求,也不會列印 Registering as opted in 行,因此 Anthropic 不會服務其工作階段。
  • --capacity 1(預設值):每個執行器程序一次處理一個工作階段,因此請執行更多副本以實現平行處理。
  • Git 2.32 或更新版本:較舊的 Git 會忽略執行器為 Git 代理伺服器設定的每個工作階段 Git 設定。

若要開啟 Git 代理伺服器,請在執行器的命令中加入 --use-anthropic-git-proxy,或在執行器的環境中設定 CLAUDE_RUNNER_USE_GIT_PROXY=1。以下命令在執行器主機的 shell 中執行,會以開啟 Git 代理伺服器的方式啟動快速入門中的執行器:

claude self-hosted-runner --environment-secret-file '/etc/claude/environment-secret' --base-dir '<writable-dir>' --use-anthropic-git-proxy

啟動時,執行器會列印 Registering as opted in to Anthropic-managed git (--use-anthropic-git-proxy)。接著 Anthropic 會針對該執行器上的每個工作階段決定是否為其提供 Git 服務。對於每個被服務的工作階段,執行器會記錄一行包含 governed git ACTIVE 的 [runner:session]。如果工作階段反而無法啟動,請參閱在使用 Git 代理伺服器的執行器上工作階段無法啟動時。

Anthropic 如何為工作階段提供 Git 服務

對於 Anthropic 所服務的工作階段,執行器的複製以及工作階段自己的提取和推送都會經過 Anthropic,並以工作階段自己的短期 token 進行身分驗證:

  • 使用者工作階段:Anthropic 使用為工作階段建立者儲存的 GitHub OAuth token。
  • 機器人和 agent 工作階段:Anthropic 使用您組織的 GitHub App 安裝 token。
  • URL 重寫:--git-host-rewrite 和 --git-ssh-rewrite 對 Git 代理伺服器所服務的儲存庫沒有作用。

在使用 Git 代理伺服器的執行器上工作階段無法啟動時

在以 --use-anthropic-git-proxy 啟動的執行器上,當 Anthropic 不為工作階段提供 Git 服務時,該工作階段將無法啟動。請在執行器的日誌中尋找指出包含 /git_proxy/ 之 api.anthropic.com 位址的 Git 錯誤。

對於每個工作階段,Claude Code v2.1.267 或更新版本的執行器也會記錄以下其中一行:當 Anthropic 服務該工作階段的 Git 時,記錄一行包含 governed git ACTIVE 的 [runner:session];若未服務,則記錄一行包含 the server withheld Anthropic-managed git for this session 的 [runner:warn]。請在以下情況中找出您看到的那一行:

  • 既沒有 governed git ACTIVE 也沒有 withheld 行:早於 Claude Code v2.1.267 的執行器兩行都不會記錄,且 Anthropic 不會服務其工作階段。請依照固定版本將執行器更新至 v2.1.267 或更新版本。
  • withheld 行:Anthropic 未服務該工作階段。先前可搭配 Git 代理伺服器運作的執行器,也可能在您這邊沒有任何變更的情況下以這種方式失敗。
    • 有儲存庫不在 github.com 上:只要工作階段中有任何一個儲存庫位於其他 Git 主機(例如 GitHub Enterprise Server),該工作階段就不會被服務,包括其 github.com 儲存庫在內。請為該環境的執行器關閉 Anthropic Git 代理伺服器。
    • 所有儲存庫都在 github.com 上:請將此失敗連同 withheld 行中的工作階段 ID 回報給您的 Anthropic 客戶團隊。Anthropic 會在其端記錄原因。
  • 包含 remote: access denied by the git proxy 的行:即使是 Anthropic 所服務的工作階段仍可能被拒絕,例如當組織政策拒絕該工作階段的 Git 存取,或該工作階段未獲授權存取該儲存庫時。此時執行器的日誌會顯示一行包含 remote: access denied by the git proxy 的內容,該行其餘部分會說明原因。
  • GitHub authentication required:當工作階段建立者在 claude.ai 上沒有可用的 GitHub 連結時會出現此訊息。工作階段的複製會失敗,Git 錯誤訊息為 GitHub authentication required. Please reconnect your GitHub account. 請該使用者在其 claude.ai 設定中連結或重新連結 GitHub。

修正原因後,請重新啟動失敗的工作階段。

關閉 Anthropic Git 代理伺服器

如果某個環境中的工作階段使用位於 github.com 以外 Git 主機(例如 GitHub Enterprise Server)上的儲存庫,請為該環境的執行器關閉 --use-anthropic-git-proxy。

1

移除旗標

從執行器的命令中移除 --use-anthropic-git-proxy。如果您在執行器的環境中(例如 pod spec 或 Compose 檔案)設定了 CLAUDE_RUNNER_USE_GIT_PROXY,請在該處將其移除。在 shell 中,請取消設定它:

unset CLAUDE_RUNNER_USE_GIT_PROXY
2

為執行器提供 Git 憑證

為執行器工作階段使用的每個 Git 主機(包括 github.com)提供無需提示即可運作的憑證。執行器使用者全域 Git 設定中原有的任何憑證都已消失,因為在設定 --use-anthropic-git-proxy 期間,執行器已刪除該設定。請在映像中提供憑證,或使用 checkout 生命週期 hook。

3

開放網路路徑

允許執行器透過連接埠 443 或 22 連線到執行器工作階段使用的每個 Git 主機。請參閱網路需求中的 Git 主機列。

4

重新啟動執行器

重新啟動執行器,讓它們在不使用 Git 代理伺服器的情況下註冊。然後重新啟動每個失敗的工作階段。

不使用 GitHub CLI 存取 GitHub API

如果您的執行器映像不包含 GitHub CLI,Claude Code 可以提供內建的 gh,讓 Claude 仍能開啟 pull request、留言以及讀取 CI 結果。內建的 gh 適用於使用 Anthropic 管理之 Git 的執行器。它支援一個命令 gh api,用於呼叫 GitHub 的 REST API。執行器映像中需要 Claude Code v2.1.287 或更新版本。

以下命令會開啟 pull request,取代 gh pr create。內建的 gh 會為目前的儲存庫填入 {owner} 和 {repo}:

gh api repos/{owner}/{repo}/pulls -f title='Fix' -f head='my-branch' -f base='main'
  • 憑證:內建的 gh 透過 Anthropic 管理的 Git 傳送其 REST 請求,由 Anthropic 端提供 GitHub 憑證,因此映像不需要為此準備 GitHub token
  • 哪些工作階段會取得它:Anthropic 會針對每個工作階段決定是否由 Anthropic 管理的 Git 提供該工作階段的 gh。若有提供,執行器為該工作階段記錄的 [runner:session] governed git ACTIVE 行會顯示 gh_path_shim=true。若沒有提供,該工作階段就沒有 gh
  • jq:如果您希望 --jq 能運作,請在映像中安裝 jq
  • CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:如果工作階段環境設定了它,Claude Code 不會提供內建的 gh,該工作階段就沒有 gh

當映像包含 GitHub CLI 時,工作階段會使用它。

使用 Anthropic 管理的 Git 信任私有憑證授權單位

如果您在執行器的環境中設定 GIT_SSL_CAINFO 或 GIT_SSL_NO_VERIFY,其工作階段使用 Anthropic 管理的 Git,本部分適用。它描述的處理需要執行器執行 Claude Code v2.1.283 或更新版本。

當執行器上的 Git 必須信任私有憑證授權單位 (CA)(例如 TLS 檢查代理簽署的憑證授權單位)時,通常的方法如下所示:

  • 系統憑證存放區:在執行器主機的系統憑證存放區中安裝您的 CA,Git 無需任何變數即可信任它。
  • GIT_SSL_CAINFO:將其設定為您的 CA 的 PEM 檔案,例如 GIT_SSL_CAINFO=/etc/ssl/corp-ca.pem。
  • GIT_SSL_NO_VERIFY:在重新簽署代理後沒有幫助。執行器自己通過 Anthropic 管理的 Git 複製檢查憑證,即使設定了變數,因此複製失敗直到 Git 通過其他兩種方法之一信任您的 CA。

對於將工作階段令牌傳遞到 Anthropic 管理的 Git 的 Git 連線,執行器應用這兩個變數如下。command 鉤子以工作階段的環境開始,因此它獲得 Git 在工作階段內獲得的內容:

  • GIT_SSL_CAINFO:Git 檢查 Anthropic 管理的 Git 的內容取決於 Git 執行的位置:
    • 執行器自己的複製和提取:執行時不使用變數,並根據執行器寫入的每個工作階段憑證檔案檢查 Anthropic 管理的 Git。該檔案保存執行器主機的系統 CA 套件加上您的檔案中的憑證。
    • 工作階段內的 Git:獲得 http.sslCAInfo 配置,命名您的檔案代替變數,加上 http.<url>.sslCAInfo 項目,根據每個工作階段檔案檢查 Anthropic 管理的 Git。
    • checkout 和 post-session 鉤子:繼承變數不變。
  • GIT_SSL_NO_VERIFY:哪些憑證檢查保持關閉取決於 Git 執行的位置:
    • 執行器自己的複製和提取:執行時不使用變數,並檢查它們呈現的憑證。
    • 工作階段內的 Git:獲得 http.sslVerify=false 配置代替變數,因此檢查對其他主機保持關閉。它也獲得 http.<url>.sslVerify=true 項目,為 Anthropic 管理的 Git 保持檢查開啟。
    • checkout 和 post-session 鉤子:當工作階段在 Anthropic 管理的 Git 上有儲存庫時,獲得 http.sslVerify=false 配置代替變數。它們也獲得 http.<url>.sslVerify=true 項目,為 Anthropic 管理的 Git 保持檢查開啟。

每個工作階段憑證檔案需要在執行器主機上的 /etc/ssl/certs/ca-certificates.crt 或 /etc/pki/tls/certs/ca-bundle.crt 處的系統 CA 套件。它也需要執行器的使用者可以讀取的 GIT_SSL_CAINFO 檔案,保存 PEM CERTIFICATE 區塊,最多 1 MiB。當執行器無法建立每個工作階段檔案時,它記錄包含 did not build the certificate file 和原因的 [runner:warn] 行。Git 隨後按原樣為 Anthropic 管理的 Git 使用您的檔案。修復該行命名的內容。

對於使用 Anthropic 管理的 Git 的每個工作階段,執行器也記錄以 governed git: GIT_SSL_CAINFO is set 或 governed git: GIT_SSL_NO_VERIFY is set 開始的 [runner:warn] 行。該行說明執行器對其自己的 Git、工作階段內的 Git 和您的生命週期鉤子對該變數所做的操作。它以您是否需要更改任何內容結束。

為私有網路重寫 Git URL

儲存庫 URL 從控制平面以 HTTPS 形式傳來,並帶有您 Git 主機的主機名稱;對於 GitHub Enterprise,這是您在 claude.ai 上為 GitHub Enterprise 整合設定的主機名稱。兩個可重複使用的旗標會在複製之前重寫這些 URL:

  • --git-host-rewrite <from>=<to>:用於分割視界 DNS,其中 Anthropic 通過外部主機名到達您的 Git 主機,但執行器必須使用內部主機名
  • --git-ssh-rewrite <host>:用於僅接受 SSH 的 Git 主機,將 https://<host>/owner/repo 重寫為 git@<host>:owner/repo

主機重寫首先執行,因此如果您需要兩者,請在 --git-ssh-rewrite 中列出內部主機名。為了完全控制簽出,使用 checkout 生命週期鉤子。

構建執行器映像

Anthropic 不發佈預構建的執行器映像。在 claude 二進位檔案周圍構建您自己的,分層您的儲存庫需要的任何工具鏈:語言執行時、編譯器、套件管理器和 MCP 邊車。

下面的配方使用 --capacity 4,因此一個容器服務來自同一鎖定所有者的最多四個並發工作階段。這不提供強化部分中的每個工作階段容器隔離:在將環境連接到生產系統之前,要麼以 --capacity 1 執行配方,每個工作階段一個容器,要麼使用按需執行器,它也將環境祕密保留在執行工作階段的主機之外。如果您將Anthropic git 代理新增至其中一個配方,也請將 --capacity 變更為 1。

此 Dockerfile 是一個最小的起點:

FROM debian:bookworm-slim
ARG CLAUDE_CODE_VERSION
RUN apt-get update && apt-get install -y --no-install-recommends git curl ca-certificates openssh-client jq \
 && rm -rf /var/lib/apt/lists/*
RUN curl -fsSL "https://downloads.claude.ai/claude-code-releases/${CLAUDE_CODE_VERSION:?set with --build-arg CLAUDE_CODE_VERSION}/linux-x64/claude" \
      -o /usr/local/bin/claude && chmod +x /usr/local/bin/claude
RUN git config --system user.name "Claude" \
 && git config --system user.email "noreply@anthropic.com" \
 && git config --system --add safe.directory '*'
ENTRYPOINT ["claude"]

如果您的節點是 ARM,將 linux-x64 交換為 linux-arm64,或在 Alpine 等 musl 基礎映像上交換為 linux-x64-musl 或 linux-arm64-musl;請參閱 Alpine Linux 設定以了解 musl 映像需要的額外套件。URL 是標準 Claude Code 發佈位置,因此您可以根據二進位檔案完整性和程式碼簽名中描述的發佈的已簽名清單驗證下載的二進位檔案。執行器需要 Claude Code 版本 2.1.224 或更新版本。構建映像,然後將其推送到您的登錄檔並在下面的配方中引用它:

docker build \
  --build-arg CLAUDE_CODE_VERSION="$(curl -fsSL https://downloads.claude.ai/claude-code-releases/stable)" \
  -t <your-registry>/claude-runner:latest .

命令替換會查詢目前的 stable 發佈號碼,並將其作為構建引數傳遞,因此在新的穩定版本發佈後執行相同的命令會使用較新的二進位檔案重新構建下載層。若要為可重現的構建固定特定版本,請直接將版本號碼作為 CLAUDE_CODE_VERSION 傳遞。當您需要比穩定通道更新的版本(例如新推出的模型所需的版本)時,在查詢 URL 中將 stable 替換為 latest。

為工作階段調整 CPU 和記憶體大小

為執行器執行的工作階段而不是執行器程序本身調整執行器的容器或主機大小。執行器本身輪詢工作、準備每個工作階段的簽出、執行您的生命週期鉤子,以及啟動和監督工作階段程序。負載來自工作階段:每個都是 Claude Code 程序加上它啟動的任何內容,例如構建、測試套件、套件安裝和 MCP 伺服器。

對於一個工作階段,從以下值開始,表示為 Kubernetes 請求和限制或您的平台的等效項,並將它們視為起點而不是要求:

  • 記憶體:請求和限制各 4 GiB,滿足 Claude Code 系統要求中的 4 GB 最小值。保持兩者相等,以便調度器考慮容器的完整記憶體。當容器達到其記憶體限制時,核心會殺死其中的程序,這可能會結束工作階段中途。
  • CPU:2 個 CPU 的請求和 4 個 CPU 的限制,因此工作階段可以在構建期間突發超過請求。核心在其 CPU 限制處限制容器,而不是殺死其中的程序,因此限制處的工作階段執行速度較慢但保持執行。

在 Kubernetes 容器規格中,使用以下 resources 塊設定這些起始值:

resources:
  requests:
    cpu: "2"
    memory: 4Gi
  limits:
    cpu: "4"
    memory: 4Gi

構建和測試通常是工作階段負載中最大和最可變的部分,因此執行您的儲存庫的代表性構建,測量其峰值 CPU 和記憶體,並提高任何在該峰值之上沒有為 Claude Code 程序留下空間的起始值。

執行器使用 --capacity 來限制它一次執行多少個工作階段。它不在它們之間分割 CPU 或記憶體,因此執行器上的工作階段共享容器的 CPU 和記憶體。要限制一個工作階段的份額,從您的包裝器指令碼應用限制。因此,給一個容器什麼取決於它一次服務多少個工作階段:

  • 每個執行器一個工作階段:給每個容器一個工作階段的值。在 --capacity 1 使用此調整大小,強化部分推薦,以及按需執行器,您在工作流程的 spawn-runner 鉤子提交的工作負載上設定值,例如 Kubernetes Job 的 pod 範本。
  • 每個執行器多個工作階段:在 --capacity 高於 1 時,將一個工作階段的值乘以容量,因為最多那麼多工作階段可以在容器中同時執行。Kubernetes 和 Docker Compose 配方執行 --capacity 4,沒有 CPU 或記憶體限制,因此添加為您執行的容量調整大小的限制。

Kubernetes

執行器預設在連接埠 8080 上提供 GET /healthz,可使用 --health-port 配置,因此 Kubernetes 探針無需額外設定即可工作。端點在程序活著時返回 200,因此下面的探針檢測死程序,而不是卡住的程序;要捕捉停止輪詢的執行器,請在 /metrics 的 last_poll_age_seconds 系列上發出警報。下面的 Deployment 從 Kubernetes Secret 掛載環境祕密,將活躍度和就緒探針指向 /healthz,並設定 90 秒的終止寬限期。請參閱關閉時序以了解為什麼寬限期很重要。

清單在執行器容器上設定沒有 CPU 或記憶體 resources。添加為您執行的容量調整大小的塊,如為工作階段調整 CPU 和記憶體大小所述。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: claude-runner
  namespace: claude-runners
spec:
  replicas: 3
  selector:
    matchLabels:
      app: claude-runner
  template:
    metadata:
      labels:
        app: claude-runner
        app.kubernetes.io/part-of: claude-code-self-hosted-runner
    spec:
      terminationGracePeriodSeconds: 90
      containers:
        - name: runner
          image: <your-registry>/claude-runner:latest
          args:
            - self-hosted-runner
            - --environment-secret-file
            - /etc/claude/environment-secret
            - --capacity
            - "4"
          volumeMounts:
            - name: environment-secret
              mountPath: /etc/claude
              readOnly: true
          ports:
            - name: health
              containerPort: 8080
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 30
      volumes:
        - name: environment-secret
          secret:
            secretName: claude-runner-environment-secret

上面的 Deployment 位於 claude-runners 命名空間中。首先建立命名空間:

kubectl create namespace claude-runners

從保存您在管理 UI 的複製環境金鑰步驟中複製的值的本地檔案建立支持 Secret,以便祕密永遠不會出現在您的 shell 歷史記錄中。執行 (umask 077 && cat > ./environment-secret),貼上祕密,按 Enter,然後按 Ctrl-D。然後建立 Secret 並刪除檔案:

kubectl create secret generic claude-runner-environment-secret -n claude-runners --from-file=environment-secret=./environment-secret

Docker Compose

下面的 Compose 服務會在執行器退出時重新啟動它,這涵蓋了崩潰和正常排空後的退出。Docker 重新啟動原則會使用其可寫層保持完整的方式重新啟動同一個容器,因此執行器會在重複使用的檔案系統上恢復,而不是強化部署建議的全新檔案系統;請使用此配方進行評估,而對於生產環境,請每次執行時重新建立容器,或使用執行協調器。

Docker 在容器不斷退出時,會在每次重新啟動之前等待更長的時間,直到達到上限,因此無法啟動的執行器在此配方下不會在緊密迴圈中持續重新啟動。當執行器退出時描述了發生這種情況時要檢查的內容。

services:
  claude-runner:
    image: <your-registry>/claude-runner:latest
    command:
      - self-hosted-runner
      - --environment-secret-file
      - /run/secrets/environment-secret
      - --capacity
      - "4"
    secrets:
      - environment-secret
    restart: always
    stop_grace_period: 90s

secrets:
  environment-secret:
    file: ./environment-secret

關閉時序

在 SIGTERM 之後,執行器需要時間乾淨地關閉其工作階段,然後您的協調器才會終止它。它會在啟動時記錄所需的時間,在預設設定下,該行日誌包含 This runner needs up to 80s。請將協調器的停止逾時設定為至少該秒數:Kubernetes 上的 terminationGracePeriodSeconds、Docker Compose 上的 stop_grace_period,或您平台的等效設定。Kubernetes 預設為 30 秒,因此若沒有此設定,它可能會在執行器完成之前就停止 pod。

收到 SIGTERM 時,執行器會停止接受新的工作階段。接著它會開始正常關閉(稱為清空),除非您設定 --defer-shutdown-max-min 來延遲它。清空包含三個步驟:

  1. 執行器等待最多 --drain-wait-sec 秒(預設為 0),讓仍在執行的回合完成。
  2. 它終止每個工作階段的程序樹,包括 Claude 仍在執行的任何命令,但不包括在其 shell 命令結束後仍在執行的程序。
  3. 它執行 post-session 生命週期 hook。

執行器在整個清空過程中持續輪詢 Anthropic。這會讓其工作階段保持指派給它,因此在您的 post-session hook 仍在儲存未提交的工作時,其他執行器不會接手這些工作階段。

由於 --drain-wait-sec 預設為 0,滾動重新啟動會中斷任何仍在執行的回合,而工作階段會在另一個執行器上恢復,但不包含其未推送的工作。若要讓回合先完成,請設定 --drain-wait-sec,並相應提高停止逾時。

記錄的時間是以下各值的總和:

在預設設定下,總計為 0 + 5 + 60 + 15 = 80 秒。較高的 --capacity 不會增加此時間,因為執行器會同時清空其所有工作階段。

如果您設定以下任一旗標,請預留更多時間:

  • 使用 --retire-at:在退休時間與主機停止時間之間保留足夠的時間,以涵蓋典型回合完成所需的時間、加上執行器生命週期所述的背景任務等待時間、再加上記錄的時間。請在每次啟動時計算退休時間,例如 date +%s 加上執行器的預期生命週期。
  • 使用 --defer-shutdown-max-min:停止逾時還必須涵蓋您設定的分鐘數,以及清空開始前的額外等待時間(預設設定下為 75 秒)。延遲清空超過第一個信號會說明這兩者。執行器也會在啟動時記錄這個較長的時間。

延遲清空超過第一個信號

如果您想要重新啟動的執行器繼續服務它持有的工作階段最多 n 分鐘,而不是在第一個信號上清空它們,請設定 --defer-shutdown-max-min <n>。在第一個 SIGTERM 或 SIGINT 上,執行器停止接受新工作並繼續服務它持有的工作階段。它保持輪詢,以便控制平面不會重新排隊這些工作階段。需要 Claude Code v2.1.238 或更新版本。

第一個信號後執行器持有的工作階段會發生什麼

在信號後的前兩個階段中,執行器釋放工作階段,釋放的工作階段在其使用者發送下一條訊息時在新執行器上恢復。從第一個信號開始計數,執行器通過三個階段移動:

  • 在前 n 分鐘內:執行器正常服務其工作階段並繼續強制執行 --startup-timeout-min 和 --kill-session-after-min。如果您也設定 --release-idle-session-min,執行器釋放任何使用者已閒置該長時間的工作階段;沒有它,閒置工作階段保留在執行器上。
  • 當 n 分鐘用完時:執行器釋放它仍然持有的每個工作階段,閒置或不閒置。執行器等待中途轉向的轉向結束,並為該轉向的背景任務再等待最多 60 秒,然後釋放該工作階段。
  • 當發佈後寬限期用完時:執行器清空它仍然持有的任何工作階段,控制平面立即將每個清空的工作階段重新排隊到另一個執行器。發佈後寬限期在 n 分鐘用完時開始,預設值為 75 秒。如果您將 --drain-wait-sec 設定為 60 秒以上,發佈後寬限期改為 --drain-wait-sec 加 15 秒。

在任何階段,執行器在不持有任何工作階段時立即以 0 退出。第二個信號縮短階段:執行器立即清空,就像在沒有 --defer-shutdown-max-min 的第一個信號上一樣。一旦清空進行中,下一個信號強制退出執行器。這無論第二個信號還是發佈後寬限期用完啟動清空。

調整停止超時大小

給您的主機停止逾時至少三個部分的總和:您設定的 n 分鐘、釋放後寬限期,以及關閉時序所述的清空。在預設設定下,釋放後寬限期為 75 秒,清空最多需要 80 秒,因此請預留 n 分鐘加 155 秒。每當設定 --defer-shutdown-max-min 時,執行器都會在啟動時列印此總和。

如果停止逾時在執行器完成之前用完,主機會終止執行器。它仍然持有的工作階段不會執行 post-session hook。執行器不會取消註冊,控制平面會在幾分鐘內重新排隊這些工作階段。如果您無法給停止逾時該總和,請保留 --defer-shutdown-max-min 不設定,讓執行器改為在第一個信號時清空。

什麼到達執行中的 post-session 鉤子

post-session 鉤子和 Claude 工作階段子項各自在自己的 POSIX 程序組中執行,與執行器的分開,因此停止機制以不同方式到達它們:

  • 執行器已在清空時的 SIGTERM:立即強制退出執行器,跳過清空的任何剩餘部分。若沒有 --defer-shutdown-max-min,這就是執行器收到的第二個 SIGTERM。沒有任何信號會送達執行中途的 post-session hook,因此在由 init 程序收養孤兒程序的裸主機上,它會自行完成,但不受監督:其逾時預算不再適用,寫入已關閉的日誌管道可能會以 SIGPIPE 終止它,因此需要在該處撐過強制退出的 hook 應將其自己的輸出重新導向到檔案。在此頁面的容器配方中,執行器是容器的 PID 1,其退出會結束容器;而在 systemd 的預設 KillMode=control-group 下,cgroup 範圍的終止也會到達 hook,如Cgroup 範圍的終止項目所述;在這兩種情況下,請將強制退出視為對 hook 致命,並改為依賴寬限期。
  • 程序組範圍的信號,例如包裝器指令碼中的 kill -- -<pid>、shell 工作控制或組範圍的看門狗:到達執行器和中途 checkout 鉤子子程序,該子程序故意保持組附加,但不是中途執行的 post-session 鉤子或工作階段子項。
  • Cgroup 範圍的終止,例如 systemd 的預設 KillMode=control-group,或 terminationGracePeriodSeconds 到期時 Kubernetes 傳遞到整個容器的 SIGKILL:會到達所有內容,包括 hook。程序群組隔離無法防範這些情況,這就是為什麼寬限期必須涵蓋整個清空過程。
  • 鉤子自己的超時:當鉤子超過 --post-session-hook-timeout-sec 時,執行器向鉤子的整個程序組發送 SIGTERM,然後 2 秒後發送 SIGKILL,因此鉤子分叉的工作者(例如 tar、rsync 或 git)與包裝器 shell 一起終止,而不是作為孤兒存活。執行器的監督在鉤子的 stdio 關閉後結束:重定向其自己的輸出到檔案並超過 SIGTERM 階段的工作者超出執行器的範圍。

當清空開始時,以及在強制退出時,執行器記錄仍在執行多少 post-session 鉤子,因此您可以區分安靜清空和中途快照的清空。

在執行器之間保持基本目錄和容量相同

如果執行器在工作階段中途死亡,伺服器重新排隊工作階段,環境中的另一個執行器拾取它。該執行器從其自己的 --base-dir 和 --capacity 派生簽出路徑:--capacity 1 直接在 --base-dir 下簽出,--capacity 高於 1 改用每個工作階段的工作樹。當同一環境中的執行器對任一旗標使用不同的值時,恢復的工作階段的工作目錄會更改,代理之前記錄的絕對路徑(在編輯、工具呼叫或其自己的筆記中)指向不再存在的位置。

在環境中的每個執行器上使用相同的 --base-dir 和 --capacity,並且不要使用每個主機的值,例如執行個體 ID 或主機名。

基本目錄預設為 /workspace,除了 --base-dir 參考行記錄的例外。執行器需要對其的寫入存取。在啟動時,在註冊之前,執行器建立目錄並確認它可以寫入它,當它無法時以 cannot create or write to base directory 退出。以 root 身份啟動的執行器自己建立預設 /workspace。對於非 root 執行器,在啟動執行器之前建立目錄並給執行器的使用者所有權,或將 --base-dir 指向該使用者已擁有的目錄。

重複使用預熱簽出

對於大型儲存庫,複製可能主導工作階段啟動。要跳過冷複製,請自行在執行器保存其自身複製的路徑上提供一個複製。在沒有 checkout hook 的情況下,執行器在 <base-dir>/<repo-owner>/<repo> 為每個儲存庫保持一個規範複製,並在工作階段之間重複使用它:

  • 在 --capacity 1 時:執行器提取請求的 ref、分離 HEAD 並硬重置為它,當變化不多時幾乎是瞬間的。
  • 在 --capacity 大於一時:執行器提取到該複製中,然後為每個工作階段從中簽出一個單獨的 worktree。預熱複製可節省下載,但無法節省簽出。

在映像中或在持久卷上提供複製:

  • 在映像中複製:在該路徑將複製構建到您的執行器映像中。每個新容器然後以預熱複製啟動,而不重複使用磁碟。
  • 在持久卷上複製:在您使用 --lock-to-account 預鎖定到一個使用者帳戶的執行器上,將 --base-dir 指向持久卷,因此磁碟只服務該帳戶。預鎖定的執行器永遠不會拾取 Claude Tag 頻道工作階段,因此此選項不適用於服務它們的執行器。

重複使用路徑做什麼和不保證什麼:

  • 任何複製形狀都有效:路徑上的完整、淺或單分支複製按原樣使用。執行器在提取到現有複製時永遠不會傳遞 --depth,因此完整預熱保持其完整歷史記錄,淺複製保持淺。CLAUDE_RUNNER_FETCH_DEPTH(full、0 或數字;預設 50)僅控制執行器在不存在複製時進行的冷複製。

  • 追蹤的變化重置,未追蹤的檔案持續:在 --capacity 1 時,每個工作階段從硬重置開始,該重置擦除前一個工作階段的追蹤修改,但執行器永遠不執行 git clean,因此鎖定所有者的早期工作階段的未追蹤檔案保留在樹中。

  • 每工作階段目錄也持續:在簽出旁邊,執行器在 <base-dir>/_sessions/ 下為它執行的每個工作階段建立每工作階段項目。工作階段的 Claude 設定目錄保存對話記錄的本地副本。在它旁邊是工作階段的上傳檔案,當工作階段有任何時。工作階段目錄也坐在那裡:它在工作階段執行時保存任何每工作階段 worktrees 和 checkout 鉤子簽出,並保持 Claude 在其中寫入的任何其他內容。

    預設情況下,執行器在工作階段結束時將這些留在原地,因此在超越執行器程序的磁碟上它們會累積。每個工作階段都以執行器自己的使用者身份執行,因此該磁碟服務的任何後續工作階段都可以讀取它們。如果您保持持久 --base-dir,請為該增長調整卷的大小。相同的適用於任何在相同檔案系統上重新啟動執行器的設定,包括 Docker Compose 配方。

  • 使用 --remove-session-state,每工作階段目錄不持續:使用 --remove-session-state 啟動執行器,以便在工作階段結束時刪除每個工作階段的每工作階段目錄。刪除是盡力而為:當執行器在其清理執行之前被殺死時,目錄保留。規範複製和工作階段在主機上其他地方寫入的檔案,例如臨時目錄,無論如何都保留。

  • 使用 Git 代理,重置變成簽出:使用 --use-anthropic-git-proxy,執行器在每個工作階段之前清理複製的 .git/,保持物件存儲、refs 和淺狀態,但刪除索引,因此每個工作階段支付完整工作樹簽出而不是幾乎瞬間的重置;它仍然永遠不重新複製。子模組預熱在代理下不受支援。

  • 長複製不需要解決方法:執行器使用 120 秒無進度看門狗和 30 分鐘硬上限限制每個 Git 操作,而不是平面超時,因此保持報告進度的慢冷複製完成。

固定版本

每個工作階段的子 Claude Code 程序執行執行器自己的二進位檔案,執行器在它生成的工作階段內關閉自動更新,因此每個工作階段執行您在主機上安裝或構建到映像中的版本。主機級更新在執行器下次啟動時生效。

選擇您的工作階段執行哪個版本,以及何時變更:

  • 在固定版本之前:針對工作階段使用的每個模型,檢查模型所需的 Claude Code 版本。如果某個模型需要比工作階段執行的版本更新的版本,伺服器會以 Claude Code 不支援此模型 拒絕該模型的請求。
  • 將群保持在一個版本上:使用固定版本構建映像,或在裸主機上安裝特定版本並禁用自動更新
  • 升級固定機群:閱讀從您目前版本到要安裝版本之間的 changelog 項目,然後安裝較新版本或重新建置映像,並重新啟動執行器
  • 升級隨需執行器:閱讀從您目前版本到要安裝版本之間的 changelog 項目,然後變更您的 spawn-runner hook 所啟動的映像。每個新的執行器都會取得新版本。已在執行中的執行器,包括由 --min-idle 啟動的待命執行器,會保留其版本直到結束。請勿重新啟動它,因為其工作指令只能使用一次。
  • 外掛程式:外掛程式市場也不自動更新;在執行器的環境中設定 FORCE_AUTOUPDATE_PLUGINS=1 以讓外掛程式自動更新,同時二進位檔案保持固定

擴展群

您的協調器決定何時添加或移除執行器。由於每個執行器一個所有者鎖,最小副本計數是您期望同時活躍的使用者和 Claude Tag 代理的數量;--capacity 控制一個所有者的工作階段內的並行性,而不是跨所有者。

有兩種擴展方法可用:

  • 固定群:執行靜態執行器副本集並在每個執行器服務的 Prometheus 指標上擴展
  • 按需執行器:執行 claude self-hosted-runner orchestrator 子命令,它輪詢 Anthropic 以查找沒有可用執行器排隊的工作階段,並調用您的 spawn-runner 鉤子為每個工作階段啟動一個。請參閱按需執行器。

已知問題和限制

以下是此版本中的限制,其中存在解決方法。

連接器流量離開您的網路

Anthropic 從其自己的基礎設施而不是從您的執行器呼叫連接器工具。連接器工具是 claude.ai 連接器,例如 GitHub、Slack 和 Linear。當 Claude 在自託管工作階段中使用連接器時,該流量通過 api.anthropic.com 而不是源自您的網路邊界內。

要將連接器保留在自託管工作階段之外,使用 allowedMcpServers 和 deniedMcpServers 原則設定進行篩選。Claude Code 將這些設定應用於 Anthropic 傳遞的連接器以及您從執行器主機播種的伺服器和使用者添加的伺服器,因此如果您為其他伺服器部署允許列表,Claude Code 也會阻止傳遞的連接器。要在 URL 型允許列表旁邊保持連接器可用,添加與傳遞連接器的 Anthropic 代理路徑相符的項目:

  • https://api.anthropic.com/v2/ccr-sessions/*
  • https://api.anthropic.com/v1/code/sessions/*
  • https://api.anthropic.com/v1/code/mcp/*

如果工具流量必須保留在您的網路內,改為在執行器映像上執行等效工具作為本地 MCP 伺服器。請參閱 MCP 伺服器。

某些工作階段不計為閒置

持有永遠不完成的背景任務的工作階段不計為閒置,因此 --release-idle-session-min 不會釋放該工作階段的插槽。等待從執行中工具呼叫內部請求的批准的工作階段也不計為閒置。始終將 --kill-session-after-min 與其一起設定作為硬後擋,以便沒有工作階段可以無限期地持有插槽。

--kill-session-after-min 是失控工作階段的後擋。在 v2.1.260 或更新版本上的執行器上,達到限制的工作階段不會立即終止。執行器給它一個寬限窗口,預設 15 分鐘,您可以使用 SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS 更改:

  • 如果工作階段等待其使用者,執行器會釋放它。如果其轉向已結束並且它僅持有背景任務,執行器會等待最多 60 秒讓這些任務完成,然後釋放它。當其使用者發送下一條訊息時,工作階段會恢復。
  • 如果轉向仍在執行,執行器等待轉向完成,或工作階段下一次等待其使用者,然後釋放它。
  • 如果工作階段在寬限窗口結束時仍在執行器上,執行器終止它,任何執行中轉向的工作都會丟失。等待從執行中工具呼叫內部請求的批准的轉向是工作階段超過窗口的一種方式。

釋放的工作階段從新複製恢復,因此它未推送的工作無論如何都消失了;請參閱恢復的工作階段丟失未推送的工作。在 v2.1.260 之前,執行器在限制處終止每個工作階段,最多等待寬限窗口以完成執行中的轉向。

將該旗標設定為高於您預期的最長工作階段時間,例如 --kill-session-after-min 480 為 8 小時。要從進入閒置的對話中釋放插槽,改用 --release-idle-session-min。

其他限制

  • 恢復的工作階段丟失未推送的工作:新的執行器會從其起始分支再次複製儲存庫,因此工作階段未推送的工作會消失。
    • 若要保留已提交的工作:在環境中的每個執行器上設定 --push-outcome-on-release,因為沒有此旗標的執行器會從其起始分支恢復工作階段。具有此旗標的執行器會在釋放之前盡力推送工作階段的結果分支,恢復的工作階段便會從這些提交開始。推送會使用執行器主機本身的 git 憑證,包括在使用 Anthropic 管理的 git 的執行器上。未提交的變更仍會遺失。
    • 使用 checkout hook 時:透過 checkout 生命週期 hook 簽出的儲存庫不會被推送。請改為從 post-session hook 建立這些儲存庫的快照。
    • 啟用旗標之前:限制誰可以推送到來源遠端上的 claude/* refs。在恢復時,執行器會提取先前推送的分支,而不驗證是誰推送的。
  • 工作階段中途新增的儲存庫可能無法複製:Claude 透過 HTTPS 使用 git clone 複製它。在未使用 --use-anthropic-git-proxy 的執行器上,如果主機上沒有任何項目能讀取該儲存庫,複製會因 git 身分驗證錯誤而失敗。在可行的情況下,請在建立工作階段時選擇工作階段需要的每個儲存庫。
  • 某些連接器不出現在自託管工作階段中:您在 claude.ai Settings 中尚未連接的連接器不在自託管工作階段中列出,工作階段不會提示您連接它。首先在 Settings 中連接它,然後啟動新工作階段。將連接器添加到已執行的工作階段也不會使其工具可用於 Claude;啟動新工作階段以拾取新添加的連接器。

報告問題

對於自託管環境的問題,請聯繫您的 Anthropic 帳戶團隊。

故障排除

為了進行引導式診斷,在執行器主機上執行 doctor 子命令。doctor 子命令啟動互動式 Claude Code 工作階段,附加執行器的日誌和狀態。首先在該主機上使用 claude auth login 登入,以便工作階段可以查詢您的環境、其執行器和其排隊的工作階段。沒有該登入,例如當主機使用 API 金鑰進行身份驗證時,它限制為本地健康端點、指標和執行器的日誌,並且僅在您使用 --log-file 啟動執行器時讀取日誌。

claude self-hosted-runner doctor

常見問題:

  • 執行器不出現在環境中:確認主機可以通過 HTTPS 到達 api.anthropic.com,環境祕密是最新的,主機時鐘在真實時間的五分鐘內;更大的偏差導致身份驗證失敗。執行器在身份驗證失敗時記錄 [runner:fatal] 及拒絕原因。

  • 執行器在啟動時以 cannot create or write to base directory 退出:執行器無法建立或寫入 --base-dir,預設為 /workspace。修復目錄的所有權或將 --base-dir 指向可寫路徑,如在執行器之間保持基本目錄和容量相同中所述。如果執行器改為記錄 [runner:fatal] 說基本目錄檢查超時,目錄在掛起的 NFS 或 CSI 掛載上。檢查掛載健康而不是權限。執行器在打開 --log-file 之前將這兩個啟動失敗列印到 stderr,因此在終端或您的平台的容器日誌中尋找它們,而不是日誌檔案。在 v2.1.225 之前,執行器在啟動時沒有檢查基本目錄,此配置錯誤在拾取後失敗工作階段。

  • 工作階段保持排隊:每個線上執行器可能被鎖定到不同的所有者。檢查每個執行器的 claude_code_self_hosted_runner_locked_account 指標或其 [runner:health] 日誌行的 locked_account 欄位以查看誰持有它。兩者僅在執行器被發佈攜帶 act.email 聲明的工作階段令牌後顯示所有者的電子郵件,Claude Tag 代理的工作階段永遠不會這樣做。沒有聲明,執行器不發出 locked_account 系列並記錄 locked_account=yes,這告訴您執行器被鎖定但不知道到哪個所有者。添加副本,或等待現有執行器清空並重新啟動。如果環境使用按需執行器,改為檢查協調器;請參閱按需執行器。

  • 工作階段在拾取後立即失敗:在 claude.ai/code 中開啟工作階段以查看錯誤。最常見的原因是執行器映像中缺少 Git 憑證,以及未安裝建置工具。在以 --use-anthropic-git-proxy 啟動的執行器上,請參閱當工作階段無法在使用 Git 代理伺服器的執行器上啟動時。不可寫入的基本目錄會在啟動時停止執行器,而不是使工作階段失敗。請參閱此清單中的執行器在啟動時以 cannot create or write to base directory 退出項目。

  • 工作階段無法在設定了 --use-anthropic-git-proxy 的執行器上啟動:在執行器的日誌中尋找 access denied by the git proxy,或指名包含 /git_proxy/ 的 api.anthropic.com 位址的 Git 錯誤。若要判斷 Anthropic 是否有服務該工作階段並修正原因,請參閱當工作階段無法在使用 Git 代理伺服器的執行器上啟動時。

  • 工作階段無法通過身份驗證出站代理到達網路:當您使用 --proxy-authorization-command 或 --proxy-authorization-file 設定的來源失敗、在 30 秒後超時或產生空值時,執行器以 502 Bad Gateway 回答該連接並記錄原因。執行器在該日誌中編輯命令的 stderr,永遠不記錄標頭值。使用 --proxy-authorization-command,自己在主機上執行命令以確認它在 stdout 上列印整個標頭值。如果執行器改為在啟動時以 could not start the proxy-authorization listener 退出,它無法打開其環回偵聽器。

  • 執行器記錄 Poll failed 行包含 rejecting the malformed poll response:執行器接收到工作輪詢回應,其主體不是隊列的預期 JSON,最常見的原因是執行器和 api.anthropic.com 之間的某些內容(例如攔截代理或強制入口網站)以自己的頁面回答。執行器拒絕回應,在 claude_code_self_hosted_runner_poll_errors_total 指標的 transport 種類下計數,並在工作階段生命週期中描述的失敗輪詢時間表上重試。執行器保持服務其活躍工作階段。配置代理以從 api.anthropic.com 無更改地傳遞回應。在 v2.1.246 之前,執行器將此類回應讀取為空工作隊列,這可能結束其活躍工作階段或使其退出。

  • 工作階段的分支不再存在於遠端:對於工作階段僅從中讀取的 Git 來源,執行器跳過該來源並在其餘來源上繼續。對於工作階段推送結果的來源,已刪除的分支(通常因為它被合併並自動刪除)使工作階段失敗,並出現命名儲存庫和分支的錯誤,要求您恢復分支並重試。當跳過會使其沒有儲存庫時,執行器使用相同的錯誤使工作階段失敗。在 v2.1.228 之前,此類工作階段在空目錄中啟動。

  • 工作階段啟動時沒有其中一個儲存庫:在沒有 checkout hook 的執行器上,Git 主機可以拒絕執行器對工作階段僅從中讀取的儲存庫的存取檢查。執行器隨後跳過該儲存庫,記錄命名拒絕的 [runner:warn] could not access context source 行,並在其餘儲存庫上啟動工作階段。

    執行器僅跳過明確的拒絕:主機回答儲存庫未找到,Git 找不到主機的認證,或身份驗證失敗。網路故障、超時或 HTTP 403 仍然會失敗工作階段啟動,對於工作階段推送結果的儲存庫的拒絕也是如此。執行器仍然會失敗跳過會使其沒有儲存庫的工作階段。使用 --use-anthropic-git-proxy,執行器僅跳過 Git 代理本身拒絕的儲存庫。

    存取檢查在每次工作階段在執行器上啟動時再次執行,因此一旦執行器的 Git 身份具有讀取存取權限,下一次啟動會複製儲存庫。在 v2.1.274 之前,這些拒絕中的每一個都失敗了工作階段啟動。

  • 工作階段需要幾分鐘才能啟動:初始複製通常主導。觀看 claude_code_self_hosted_runner_session_init_duration_seconds 指標以確認,並使用預熱簽出或較小的 CLAUDE_RUNNER_FETCH_DEPTH 切割複製。

  • 回合以 401 失敗:當回合以來自 Anthropic API 的 401 或 403 結束時,執行器會從 Anthropic 取得新的 CLAUDE_CODE_OAUTH_TOKEN 並將其傳遞給工作階段。失敗的回合不會重試。此 token 為短期有效,執行器會透過工作階段的 stdin 輪換它。

    當獲取失敗時,執行器記錄 inference_token refresh failed 行,說明何時會重試,並且只要工作階段運行就會繼續重試。

    如果每個呼叫在工作階段約 30 分鐘後開始失敗,包裝指令碼可能已切斷工作階段的 stdin,因此令牌輪換無法到達它;請參閱保持 stdin 和檔案描述符 3 附加。

    在 v2.1.274 之前,執行器在幾次嘗試後停止重試失敗的獲取,並等待下一個排定的獲取。失敗的輪次沒有觸發獲取,因此每個輪次都以 401 失敗,直到下一個排定的獲取。

  • Pod 在清空中途被殺死:將 terminationGracePeriodSeconds 提高到至少執行器在啟動時記錄的值。請參閱關閉時序。

日誌初始化後,執行器將其生命週期日誌(包括 [runner:fatal] 行)寫入 stdout,將調試輸出寫入 stderr,全部作為純文字行而不是 JSON。上面故障排除項中描述的啟動失敗在該點之前列印到 stderr。使用 --log-file 捕捉兩個流,這也讓 self-hosted-runner doctor 尾隨它們,或使用您的平台的日誌收集。

每個工作階段的子程序寫入單獨的調試日誌。失敗時執行器在 claude.ai/code 中的工作階段旁邊顯示日誌的尾部。除非您使用 --remove-session-state 啟動執行器,否則它也會在磁碟上保留失敗工作階段的日誌,並在執行器日誌中列印其路徑。

當執行器退出時

不要重新啟動按需執行器,因為其工作訂單是一次性的。執行器在啟動後立即退出需要與因任何其他原因退出的執行器不同的處理。

  • 正常退出:執行器完成了其工作階段並清空、達到其退休時間或被告知停止。重新啟動它以便環境再次具有容量。執行器生命週期描述這些退出。
  • 失敗的啟動:執行器無法使用給定的設定或主機啟動,因此它在啟動後幾秒鐘退出,每次您重新啟動它時都以相同的方式退出。更快地重新啟動它沒有幫助。有人需要閱讀其輸出並修復原因。
  • 失去聯繫:無法連線到 Anthropic 的時間超過其租約的執行器(例如在其主機休眠期間)可能會從環境中移除。當已移除的執行器重新連線時,它會退出。其日誌中可能會出現包含 runner record gone server-side 的 [runner:fatal] 行,或在較長的中斷之後出現 poll auth failed。執行器不會自行重新註冊,因此請重新啟動它。

配置您的監督程序以在執行器退出時重新啟動它,在執行器持續在啟動後立即退出時等待更長時間再重新啟動,並在這種情況持續發生時告知某人。

識別失敗的啟動

當執行器無法啟動時,它會列印一行說明原因,然後退出。對於大多數原因,該行包含 [runner:fatal]。對於某些原因,該行以 error: 開頭,包括當執行器無法解析其旗標、無法讀取環境祕密或無法建立或寫入基本目錄時。下一行然後指向 --help。

大多數日誌行以時間戳和 [self-hosted-runner] 開頭,下面的範例省略了。例如,使用 Anthropic Git 代理和容量大於 1 啟動的執行器會列印如下一行:

[runner:fatal] --use-anthropic-git-proxy requires --capacity 1 (the proxy URL is per-session and linked worktrees share origin). Omit --use-anthropic-git-proxy or set --capacity 1.

在執行器的標準輸出和標準錯誤、您的平台的容器日誌或您使用 --log-file 設定的檔案中尋找該行。執行器在打開日誌檔案之前列印 error: 行,因此在終端或您的容器日誌中尋找它,如故障排除所述。

當您閱讀失敗的啟動時,這些也有幫助:

  • 根本沒有行:主機殺死的執行器不會列印任何一個。如果輸出以沒有 [runner:fatal] 行和沒有 error: 行結束,檢查主機或您的協調器是否停止了程序,例如超過記憶體限制。
  • 退出代碼:執行器不會為在每次啟動時重複的錯誤預留退出代碼。它對配置錯誤(例如不支援的旗標組合)和可以自行清除的失敗(例如 API 通過執行器自己的重試保持無法到達)以相同的代碼退出。根據執行器退出的速度快慢來決定是否等待更長時間,並閱讀執行器的輸出以了解原因。
  • 看起來健康的環境:某些啟動步驟在執行器向您的環境註冊後執行,例如 --configure-git 和 Anthropic Git 代理的認證設定。如果其中一個步驟失敗,環境可以在程序退出後幾分鐘內繼續列出該執行器,雲端環境頁面可以讀取健康,而沒有執行器拾取工作。如果工作階段在看起來健康的環境中保持排隊,檢查您的監督程序是否在重新啟動執行器。

使用增長的等待時間重新啟動

您如何獲得增長的等待時間取決於您的監督程序。

  • Kubernetes:此頁面上的 Deployment 不需要更改。容器退出後,kubelet 預設會在重新啟動容器之前等待,並且等待時間在每次重新啟動時增長到上限。一旦容器運行了一段時間而沒有退出,等待時間就會重新開始。

    kubelet 在容器運行時間很短時的正常退出後應用相同的等待。經常清空的執行器因此也可以顯示 CrashLoopBackOff 狀態,因此在得出執行器無法啟動的結論之前閱讀輸出。下面的命令從 Deployment 的一個 pod 讀取上次運行的輸出:

    kubectl logs --previous -n claude-runners deploy/claude-runner
    

    當上次運行是失敗的啟動時,[runner:fatal] 或 error: 行在輸出的最後幾行中。要讀取另一個 pod 的上次運行,在 deploy/claude-runner 的位置命名該 pod。

  • Docker 和 Docker Compose:此頁面上的 Compose 配方不需要更改。使用 restart: always,Docker 在持續退出的容器的每次重新啟動之前等待更長時間,直到上限。在下面的命令中用容器的名稱替換 <container>,該命令讀取 Docker 重新啟動容器的次數:

    docker inspect --format '{{.RestartCount}}' <container>
    

    該命令列印一個數字。持續增長的數字意味著 Docker 持續重新啟動執行器。

  • systemd 單位:預設情況下,systemd 在每次重新啟動之前等待相同的 RestartSec,並且不會延長它,因此具有 Restart=always 的單位以相同的間隔重新啟動無法啟動的執行器。當啟動速度足夠快以達到單位的啟動速率限制時(預設為 10 秒內 5 次啟動),systemd 停止重新啟動該單位。該單位保持停止狀態,直到有人再次啟動它,systemd 允許在速率限制的間隔已過或在 systemctl reset-failed 之後。因為 RestartSec 適用於每次重新啟動,更長的值也會延遲正常退出後的重新啟動。選擇一個平衡兩者的值,並對單位的重新啟動計數發出警報。

  • shell 迴圈或您自己的監督程序:自己應用相同的規則。從 5 秒的等待開始。在每次在一分鐘內結束的運行之後,將下一次重新啟動的等待加倍,最多 5 分鐘。在運行持續一分鐘或更長時間後,回到 5 秒。

檢查執行器為什麼持續退出

當執行器連續多次在啟動後立即退出時,停止並在重新啟動之前檢查這些。

  • 最後的 [runner:fatal] 或 error: 行:它說明執行器停止的原因。故障排除列出常見原因。
  • 旗標的組合:Anthropic Git 代理需要 --capacity 1。此頁面上的配方使用更高的容量,因此在將代理添加到其中一個時降低它。
  • 服務的環境可以到達什麼:如果執行器手動啟動並在您的監督程序下失敗,比較使用者、主目錄、PATH 和記憶體限制。--configure-git 和 Anthropic Git 代理需要 PATH 上的 Git 和可寫的 ~/.gitconfig。
  • 環境祕密:如果您撤銷了祕密或輸入錯誤,執行器會列印包含 RegisterRunner auth failed 的行。
  • 環境的活動標籤:打開環境並選擇活動。如果新執行器持續出現在那裡,沒有任何執行器拾取工作,您的監督程序正在重新啟動執行器。

為了在執行器主機上進行引導式診斷,執行 doctor 子命令。

下一步

  • 自訂工作階段:包裝器指令碼、生命週期鉤子、按需執行器、MCP 伺服器和權限
  • 端到端測試:在推廣新執行器映像之前從 CI 驗證它
  • 參考:每個 CLI 旗標、環境變數和指標