자체 호스팅 환경은 Team 및 Enterprise 플랜에서 공개 베타 상태입니다. 가용성 및 제한사항에서 활성화 경로를 다룹니다. 이 페이지는 프로덕션에서 플릿을 실행하는 것을 다룹니다. 첫 번째 러너 및 세션은 빠른 시작을 참조하세요.
배포 강화
자체 호스팅 러너는 환경에 세션을 전달할 수 있는 모든 사람을 대신하여 인프라에서 임의의 모델 지향 코드를 실행합니다. 이는 Anthropic 조직의 모든 멤버이며, Owner가 환경으로 라우팅한 범위에서 Claude Tag 채널 세션을 시작할 수 있는 모든 사람입니다. 환경을 프로덕션 시스템에 연결하기 전에 각 항목을 검토하세요:-
임시 세션별 컨테이너:
--capacity 1과 기본값--drain-grace-sec 0을 사용하여 각 러너 프로세스를 프로세스가 종료될 때 삭제되는 새로운 컨테이너 또는 VM에서 실행하므로 각 컨테이너는 정확히 하나의 세션을 제공합니다. 더 높은 용량이거나 양수 드레인 유예가 있으면 하나의 컨테이너가 동일한 잠긴 소유자의 여러 세션을 제공합니다. 러너 수명 주기를 참조하세요. 러너 재시작 간에 파일 시스템을 재사용하지 마세요. 의도적인 사전 준비된 체크아웃 설정을 제외하고, 소유자 간에는 절대 재사용하지 마세요. -
이미지에 광범위한 자격증명 없음: 장기 SSH 키, 클라우드 공급자 자격증명, 또는 세션이 필요한 것보다 더 많은 권한을 부여하는 개인 액세스 토큰을 포함하지 마세요. 세션 중에 사용되는 자격증명(예: 푸시 또는 API 토큰)을 래퍼 스크립트에서 세션별로 발급하세요. 래퍼가 실행되기 전에 발생하는 초기 클론의 경우
checkout수명 주기 훅 또는--use-anthropic-git-proxy를 사용하세요. git 구성을 참조하세요. - 세션 실행 호스트에서 환경 시크릿 유지: 환경 시크릿은 러너를 등록하고 환경에 대기 중인 모든 세션을 선택할 수 있습니다. 고정 플릿에서는 모든 러너 호스트에 있으며, 모든 세션의 코드가 시크릿 파일을 읽을 수 있습니다. 온디맨드 러너를 선호하세요. 여기서 시크릿은 사용자 코드를 실행하지 않는 오케스트레이터 호스트에 유지되며, 각 러너는 정확히 하나의 러너를 등록하는 단일 사용 작업 주문을 받습니다. 고정 플릿에서는 환경 시크릿 파일을 모든 세션이 읽을 수 있는 것으로 취급하고 의심되는 세션 손상 후 시크릿을 회전하세요.
- 기본 거부 네트워크 이그레스: 모든 환경에서 네트워크 경계에서 러너 및 세션 컨테이너 아웃바운드 트래픽을 제한하세요. 기본 거부 이그레스에서 허용할 항목과 이유를 다룹니다.
- 최소 권한 호스트 IAM: 러너 호스트에 연결된 컴퓨팅 ID(예: 인스턴스 프로필 또는 노드 서비스 계정)는 러너 자체가 필요한 것만 부여해야 합니다. 세션은 호스트의 ID를 상속하는 대신 래퍼 스크립트를 통해 자신의 자격증명을 얻어야 합니다.
-
세션에서 클라우드 메타데이터 엔드포인트 차단: 세션을 호스트 ID에서 벗어나게 유지하려면 클라우드 메타데이터 엔드포인트에 대한 액세스를 차단해야 하며, 서브넷 수준 이그레스 정책은 링크 로컬 메타데이터 트래픽을 가로채지 않으므로 컨테이너 자체에서 차단하세요:
- 홉 제한이 1인 IMDSv2
- 메타데이터 은폐가 있는 GKE Workload Identity
- 세션 컨테이너의 네트워크 네임스페이스에서
169.254.169.254에 대한 명시적 거부
-
러너별 파일 시스템 격리: 각 러너 프로세스는 호스트의 다른 프로세스가 읽거나 쓸 수 없는 자신의 작업 디렉토리를 가집니다.
--hooks-dir, 래퍼 스크립트, 호스트의~/.claude/를 이미지에 내장되거나 읽기 전용으로 마운트된 세션에 읽기 전용으로 만드세요. -
전달에는 환경별 액세스 제어가 없음: Anthropic 조직의 모든 멤버는 모든 환경에 세션을 전달할 수 있습니다. Owner가 Claude Tag 채널을 환경으로 라우팅하면, Claude Tag 액세스 설정이 허용하는 모든 사람이 거기서 실행되는 채널 세션을 시작할 수 있습니다. 기본적으로 Claude 계정이 있는지 여부와 관계없이 연결된 Slack 워크스페이스의 모든 사람입니다. 모든 러너 호스트를 코드 실행에 도달할 수 있는 것으로 취급하세요. 환경에 전달할 수 있는 모든 사람이 읽을 수 있는 데이터와 자격증명만 러너 호스트에 배치하세요.
--lock-to-account는 주어진 호스트가 실행하는 계정의 세션을 제한하지만, 환경에 전달할 수 있는 사람을 좁히지는 않습니다. 자체 호스팅 환경을 유일한 선택 옵션으로 만들려면 Owner가 전체 조직에 대해 클라우드 환경 페이지에서 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 규칙을 다루지 않습니다. 권한 및 도구 승인에서 이러한 권한이 어디에 속하는지 참조하세요. - 해당 세션의 자신의 워크스페이스 외부에서 해결되는 권한:
조직의 IP 허용 목록은 기본적으로 자체 호스팅 러너 트래픽을 다루지 않습니다. 러너 또는 세션 트래픽에 대한 네트워크 제어로 의존하지 마세요. 대신 자신의 네트워크 경계에서 기본 거부 이그레스를 적용하고, 조직에 대한 IP 허용 목록 적용을 원하면 Anthropic 계정 팀에 문의하세요.
네트워크 요구사항
러너 및 생성하는 세션 자식은 아래 호스트에 아웃바운드 연결을 만듭니다. 세션 컨테이너 이그레스를 이러한 호스트 및 세션이 도달해야 하는 특정 내부 서비스로 제한하세요. 기본 거부 이그레스에서 방법과 이유를 다룹니다. 이러한 호스트는 항상 필요합니다:
이러한 호스트가 필요한지 여부는 구성에 따라 다릅니다:
러너는
statsig.anthropic.com, *.sentry.io, claude.ai, 또는 platform.claude.com에 도달하지 않습니다. 이러한 호스트는 일부 이전 엔터프라이즈 네트워크 체크리스트에 나타나지만, 러너 또는 세션 트래픽에 대해 허용 목록에 추가할 필요가 없습니다: 기능 플래그 가져오기는 api.anthropic.com으로 이동하고, 러너는 대화형 OAuth가 아닌 환경 시크릿으로 인증합니다. 두 호스트 측 흐름은 claude.ai에 도달하므로 세션 컨테이너 이그레스를 넓히는 대신 이그레스를 허용하는 호스트에서 실행하세요: 한 줄 설치 프로그램은 설치 시간에 claude.ai에서 install.sh를 가져오고, 대화형 claude auth login은 안내 설정, doctor의 서명된 모드, 및 CI 전달이 사용하며, claude.ai, claude.com, 및 platform.claude.com을 통해 서명합니다. mcp-proxy.anthropic.com도 필요하지 않습니다: 자체 호스팅 세션은 이를 사용하지 않으며, 조직의 claude.ai 커넥터를 세션에 전달하는 것(조직에 대해 활성화된 경우)은 api.anthropic.com을 통해 라우팅됩니다. MCP 서버를 참조하세요.
기본 거부 이그레스
러너 및 세션 컨테이너를 네트워크 요구사항 테이블의 호스트, git 호스트, 및 세션이 도달해야 하는 특정 내부 서비스로 제한되는 네트워크 세그먼트 또는 네임스페이스에 배포하세요. 제품은 이를 확인하거나 적용할 수 없으므로 모든 환경에서 자신의 네트워크 경계에 적용하세요. 세션 코드는 모델 지향이며 임의의 호스트에 대한 연결을 시도할 수 있습니다. 네트워크 계층에서 기본 거부 이그레스는 이러한 시도가 도달할 수 있는 위치를 제한합니다. 이는 권한 모드와 관계없이 적용됩니다: 기본 사전 승인 도구 세트에는 이미Bash가 포함되어 있으므로 자동 모드 없이도 셸 이그레스가 프롬프트 없이 실행됩니다.
각 세션이 내보내는 원격 분석 및 이를 끄는 방법에 대한 자세한 내용은 원격 분석을 참조하세요.
이그레스 프록시에 인증
일부 기업 이그레스 프록시는 모든 연결에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 토큰을 생성하는 방법과 일치하는 플래그를 선택하세요:
--proxy-authorization-command <command>: 온디맨드로 생성하는 토큰의 경우 이를 선택하세요. 러너는 셸 명령을 실행하고 트리밍된 stdout을 헤더 값으로 사용합니다(예:Bearer <token>).--proxy-authorization-file <path>: 다른 프로세스가 제자리에서 회전하는 토큰의 경우 이를 선택하세요. 러너는 파일을 읽고 트리밍된 내용을 헤더 값으로 사용합니다.
러너가 시작을 거부하는 구성
각 플래그에는 러너 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 ID 또는 자격증명을 구성하지 않습니다. 러너의 이미지와 프로세스 환경을 제어하므로 git 구성을 제어합니다. 두 가지 접근 방식 중 하나를 선택하세요:- 러너가 git을 구성하도록 허용:
--configure-git으로 러너를 시작하여 Anthropic 호스팅 세션이 사용하는 동일한 ID 및 커밋 서명 구성을 작성하도록 합니다. - 이미지에 git 구성 제공: ID 및 푸시 자격증명을 직접 설정하세요(예: 자신의 봇 ID로 커밋하기 위해).
--configure-git SSH 커밋 서명에는 Git 2.34 이상이 필요하고, --use-anthropic-git-proxy에는 2.32 이상이 필요하며, --push-outcome-on-release로 푸시된 분기에서 세션을 재개하려면 2.29 이상이 필요합니다. 세 가지를 모두 생략하고 git ID를 직접 관리하면 Git 2.24로 충분합니다.
러너가 git을 구성하도록 허용
--configure-git으로 러너를 시작하거나 SELF_HOSTED_RUNNER_CONFIGURE_GIT=1을 설정하여 시작 시 전역 git 구성을 작성하도록 합니다:
user.name = Claude및user.email = noreply@anthropic.com, Anthropic 호스팅 세션과 일치- SSH 형식 커밋 및 태그 서명, 러너 관리 shim을 통해 라우팅되어 세션의 자신의 자격증명을 사용하여 Anthropic의 서명 서비스를 통해 각 커밋에 서명합니다. 서명은 Anthropic의 게시된 SSH 서명 키에 대해 GitHub에서 확인할 수 있습니다.
이미지에 git 구성 제공
git ID는 모든 커밋에 필요합니다. Dockerfile에서 시스템 전체로 설정하여 러너 프로세스가 실행되는 사용자와 관계없이 구성이 적용되도록 합니다:git commit이 Please tell me who you are로 실패하고 세션이 진행할 수 없습니다. 대신 자신의 봇 ID를 사용할 수 있습니다. 러너는 이러한 값을 재정의하지 않습니다.
공유 러너 이미지에 장기 또는 광범위 푸시 자격증명을 굽지 마세요: 이미지의 자격증명은 이미지가 실행하는 모든 세션에서 사용 가능하며, 이를 시작한 사람과 관계없습니다. 대신 래퍼 스크립트에서 세션 JWT에서 디코딩된 세션 작성자의 ID를 사용하여 세션별로 단기, 최소 범위 토큰을 발급하세요. 이를 임시 세션별 컨테이너와 쌍으로 만드세요. --capacity 1이 필요하므로 어떤 자격증명도 이를 발급한 세션보다 오래 살지 않습니다. 강화 섹션을 참조하세요.
이미지 수준에서 푸시 자격증명을 구성해야 하는 경우(예: 읽기 전용 배포 키의 경우) git 호스트가 허용하는 만큼 좁게 범위를 지정하세요:
- 한 리포지토리로 제한되고
url.<base>.insteadOf다시 쓰기가 있는 SSH 배포 키 - 최소 범위 토큰을 반환하는
credential.helper - 좁게 범위가 지정된 키를 가리키는
GIT_SSH_COMMAND
- 러너는
GIT_TERMINAL_PROMPT=0을 설정하므로 git은 사용자 이름이나 암호를 요청하지 않습니다. - 러너는
BatchMode=yes로 SSH를 실행하며, 설정한 경우GIT_SSH_COMMAND에 추가되므로 SSH는 암호 또는 호스트 확인을 요청하지 않습니다. - 러너는
GCM_INTERACTIVE=never을 설정하므로 Git Credential Manager는 서명 대화를 열지 않습니다. - 러너는
core.askPass를 지우므로 askpass 헬퍼를 사용하는 경우GIT_ASKPASS환경 변수를 통해 설정하세요.
safe.directory를 추가하세요:
Anthropic git 프록시 사용
--use-anthropic-git-proxy로 러너를 시작하거나 CLAUDE_RUNNER_USE_GIT_PROXY=1을 설정하여 Anthropic의 git 프록시를 통해 클론하도록 합니다. 세션의 자신의 단기 토큰으로 인증됩니다. 일반 사용자 세션의 경우 프록시는 세션 작성자를 위해 저장된 GitHub 또는 GitHub Enterprise OAuth 토큰을 사용합니다. 봇 및 에이전트 세션의 경우 조직의 GitHub App 설치 토큰을 사용합니다. 어느 쪽이든 러너 이미지는 git 자격증명이 필요하지 않습니다: SSH 키, 자격증명 헬퍼, .netrc 없음. 이는 Anthropic 호스팅 환경이 사용하는 동일한 인증 경로입니다.
프록시는 --capacity 1이 필요합니다. 프록시 URL은 세션별이고 Git 2.32 이상이 필요합니다. 더 오래된 git은 프록시가 세션을 서로 격리하는 데 사용하는 구성 메커니즘을 무시합니다. 러너는 요구사항이 충족되지 않으면 시작을 거부합니다. 프록시가 Anthropic 측에서 가져오기 때문에 git 호스트는 Anthropic 인프라에서 도달할 수 있어야 합니다. 이는 Anthropic 호스팅 세션이 가진 동일한 요구사항입니다. 네트워크 내부에서만 라우팅 가능한 git 호스트의 경우 대신 checkout 수명 주기 훅을 사용하세요. 각 러너 프로세스는 한 번에 하나의 세션을 처리하므로 병렬 처리를 위해 더 많은 복제본을 실행하세요. 프록시가 활성화되면 --git-host-rewrite 및 --git-ssh-rewrite는 효과가 없습니다: 프록시 URL은 git 호스트가 아닌 api.anthropic.com을 가리킵니다.
개인 네트워크에 대한 git URL 다시 쓰기
리포지토리 URL은 제어 평면에서 HTTPS로 도착하며 git 호스트의 호스트 이름이 있습니다. GitHub Enterprise의 경우 claude.ai의 Claude Code 관리 설정에서 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를 사용하므로 하나의 컨테이너는 동일한 잠긴 소유자의 최대 4개의 동시 세션을 제공합니다. 이는 강화 섹션의 세션별 컨테이너 격리를 제공하지 않습니다: 환경을 프로덕션 시스템에 연결하기 전에 레시피를 --capacity 1로 실행하여 세션당 하나의 컨테이너를 사용하거나 온디맨드 러너를 사용하세요. 이는 또한 환경 시크릿을 세션 실행 호스트에서 벗어나게 유지합니다.
이 Dockerfile은 최소한의 시작점입니다:
linux-x64를 linux-arm64로 바꾸거나, Alpine과 같은 musl 기반 이미지에서 linux-x64-musl 또는 linux-arm64-musl로 바꾸세요. musl 이미지가 필요로 하는 추가 패키지는 Alpine Linux 설정을 참조하세요. URL은 표준 Claude Code 릴리스 위치이므로 바이너리 무결성 및 코드 서명에 설명된 대로 릴리스의 서명된 매니페스트에 대해 다운로드된 바이너리를 확인할 수 있습니다. Claude Code 버전 2.1.224 이상으로 이미지를 빌드한 다음 레지스트리로 푸시하고 아래 레시피에서 참조하세요:
세션에 대한 CPU 및 메모리 크기 조정
러너 프로세스가 아닌 실행하는 세션에 대해 러너의 컨테이너 또는 호스트 크기를 조정하세요. 러너 자체는 작업을 폴링하고, 각 세션의 체크아웃을 준비하고, 수명 주기 훅을 실행하고, 세션 프로세스를 시작하고 감독합니다. 로드는 세션에서 나옵니다: 각 세션은 Claude Code 프로세스와 빌드, 테스트 스위트, 패키지 설치, MCP 서버와 같이 시작하는 모든 것입니다. 한 세션의 경우 다음 값으로 시작하세요. Kubernetes 요청 및 제한 또는 플랫폼의 동등한 것으로 표시되며, 요구사항이 아닌 시작점으로 취급하세요:- 메모리: 각각 4 GiB의 요청 및 제한. Claude Code의 시스템 요구사항의 4 GB 최소값을 충족합니다. 두 개를 같게 유지하여 스케줄러가 컨테이너의 전체 메모리를 고려하도록 합니다. 컨테이너가 메모리 제한에 도달하면 커널이 내부 프로세스를 종료하여 세션을 중간에 종료할 수 있습니다.
- CPU: 2 CPUs의 요청 및 4 CPUs의 제한. 세션이 빌드 중에 요청 위로 버스트할 수 있습니다. 커널은 CPU 제한에서 프로세스를 종료하는 대신 스로틀링하므로 제한에서 세션이 더 느리게 실행되지만 계속 실행됩니다.
resources 블록으로 이러한 시작 값을 설정하세요:
--capacity를 사용하여 한 번에 실행하는 세션 수를 제한합니다. CPU 또는 메모리를 나누지 않으므로 러너의 세션은 컨테이너의 CPU 및 메모리를 공유합니다. 한 세션의 공유를 제한하려면 래퍼 스크립트에서 제한을 적용하세요. 따라서 한 컨테이너에 제공할 항목은 한 번에 제공하는 세션 수에 따라 다릅니다:
- 러너당 한 세션: 각 컨테이너에 한 세션의 값을 제공하세요.
--capacity 1에서 이 크기 조정을 사용하세요. 강화 섹션이 권장하고, 온디맨드 러너의 경우, 값을spawn-runner훅이 제출하는 워크로드(예: Kubernetes Job의 pod 템플릿)에 설정합니다. - 러너당 여러 세션:
--capacity1 이상에서 한 세션의 값에 용량을 곱하세요. 컨테이너에서 한 번에 최대 그 많은 세션이 실행될 수 있기 때문입니다. Kubernetes 및 Docker Compose 레시피는 CPU 또는 메모리 제한 없이--capacity 4를 실행하므로 실행하는 용량에 맞게 크기가 조정된 제한을 추가하세요.
Kubernetes
러너는 기본적으로 포트 8080에서GET /healthz를 제공하며, --health-port로 구성할 수 있으므로 Kubernetes 프로브는 추가 설정 없이 작동합니다. 엔드포인트는 프로세스가 살아있을 때마다 200을 반환하므로 아래 프로브는 막힌 프로세스가 아닌 죽은 프로세스를 감지합니다. 폴링을 중지한 러너를 잡으려면 /metrics의 last_poll_age_seconds 시리즈에 대해 경고하세요. 아래 Deployment는 Kubernetes Secret에서 환경 시크릿을 마운트하고, 활성 및 준비 프로브를 /healthz로 가리키며, 90초 종료 유예 기간을 설정합니다. 종료 타이밍에서 유예 기간이 중요한 이유를 참조하세요.
매니페스트는 러너 컨테이너에 CPU 또는 메모리 resources를 설정하지 않습니다. 실행하는 용량에 맞게 크기가 조정된 블록을 추가하세요. 세션에 대한 CPU 및 메모리 크기 조정에서 설명합니다.
claude-runners 네임스페이스에 있습니다. 먼저 네임스페이스를 생성하세요:
(umask 077 && cat > ./environment-secret)을 실행하고, 시크릿을 붙여넣고, Enter를 누른 다음 Ctrl-D를 누르세요. 그런 다음 Secret을 생성하고 파일을 삭제하세요:
Docker Compose
아래 Compose 서비스는 종료될 때마다 러너를 재시작합니다. 이는 충돌과 드레인 후 정상 종료를 모두 다룹니다. Docker 재시작 정책은 쓰기 가능한 계층이 그대로 있는 동일한 컨테이너를 재시작하므로 러너는 강화 태세가 권장하는 새로운 파일 시스템이 아닌 재사용된 파일 시스템에서 돌아옵니다. 평가를 위해 이 레시피를 사용하고, 프로덕션의 경우 실행당 컨테이너를 재생성하거나 이를 수행하는 오케스트레이터를 사용하세요.종료 타이밍
SIGTERM에서 러너는 새 작업을 받지 않고, --defer-shutdown-max-min을 설정하지 않으면 --drain-wait-sec(기본값 0)까지 대기하여 진행 중인 턴이 완료되도록 하고, 각 세션의 프로세스 트리를 종료하고, post-session 수명 주기 훅을 실행합니다. 해당 프로세스 트리에는 Claude가 여전히 세션에서 실행 중인 명령이 포함됩니다.
전체 드레인 경로는 --session-stop-grace-sec + --drain-wait-sec + --post-session-hook-timeout-sec까지 필요하며, 프로세스 정리를 위해 15초의 고정 오버헤드를 더하고, --push-outcome-on-release가 설정되었을 때 30초를 더합니다. 기본값에서 80초이며, 러너는 시작 시 합계를 기록합니다. 세션은 이 하나의 예산 아래에서 병렬로 드레인되므로 합계는 --capacity에 따라 증가하지 않습니다.
기본값 --drain-wait-sec 0에서 롤링 재시작은 진행 중인 턴을 중단합니다. 각 세션은 다른 러너에서 재개되어 알려진 문제에 설명된 대로 푸시되지 않은 작업을 잃습니다. --drain-wait-sec을 설정하고 유예 기간을 일치하도록 올려서 턴이 먼저 완료되도록 합니다.
전체 경로 전체에서 러너는 0 용량으로 제어 평면에 계속 하트비트를 보내므로 세션 임대가 만료되지 않고 post-session 훅이 여전히 커밋되지 않은 작업을 작성하는 동안 다른 러너로 재큐되지 않습니다. 하트비트는 러너가 등록 해제되기 직전에 중지됩니다.
호스트가 이를 중지하기 전에 러너에 시작 시 기록하는 합계 이상을 제공하세요. 설정하는 위치는 호스트가 중지되는 방식에 따라 다릅니다:
SIGTERM유예 기간 포함: Kubernetes에서terminationGracePeriodSeconds, Docker Compose에서stop_grace_period, 또는 오케스트레이터의 동등한 것을 최소한 그 합계로 설정하세요. Kubernetes 기본값 30초는 러너의 드레인 경로보다 짧으므로 Kubernetes는 러너가 드레인을 완료하기 전에 pod를 중지합니다.--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초입니다.
--defer-shutdown-max-min 없이 첫 신호에서처럼 즉시 드레인합니다. 드레인이 진행 중이면 다음 신호는 러너를 강제 종료합니다. 이는 두 번째 신호 또는 사후 릴리스 유예가 드레인을 시작했는지 여부와 관계없이 유지됩니다.
중지 타임아웃 크기 조정
호스트의 중지 타임아웃에 세 부분의 합계를 최소한 제공하세요: 구성하는n분, 사후 릴리스 유예, 종료 타이밍에서 설명하는 전체 드레인 경로. 기본 설정에서 사후 릴리스 유예는 75초이고 드레인 경로는 80초이므로 n분 + 155초를 허용하세요. 러너는 --defer-shutdown-max-min이 설정되었을 때마다 시작 시 이 합계를 인쇄합니다.
중지 타임아웃이 러너가 완료되기 전에 끝나면 호스트는 러너를 종료합니다. 여전히 보유한 세션은 post-session 훅을 받지 않습니다. 러너는 등록 해제되지 않으며 제어 평면은 약 1분 후에 세션을 재큐합니다. 중지 타임아웃을 그 합계로 제공할 수 없으면 --defer-shutdown-max-min을 설정하지 않은 상태로 두어 러너가 첫 신호에서 드레인하도록 합니다.
실행 중인 post-session 훅에 도달하는 것
post-session 훅과 Claude 세션 자식은 각각 자신의 POSIX 프로세스 그룹에서 실행되며, 러너와 분리되어 있으므로 중지 메커니즘이 다르게 도달합니다:
- 러너가 이미 드레인 중일 때
SIGTERM: 러너를 즉시 강제 종료하여 드레인 경로의 나머지를 건너뜁니다.--defer-shutdown-max-min없이 이는 러너가 받는 두 번째SIGTERM입니다. 아무것도 실행 중인post-session훅에 신호를 보내지 않으므로 고아를 채택하는 init 프로세스가 있는 베어 호스트에서 자신의 감독 없이 완료되지만: 타임아웃 예산이 더 이상 적용되지 않으며, 닫힌 로그 파이프에 쓰면SIGPIPE로 종료될 수 있으므로 강제 종료에서 생존해야 하는 훅은 자신의 출력을 파일로 리디렉션해야 합니다. 이 페이지의 컨테이너 레시피에서 러너는 컨테이너의 PID 1이고 그 종료는 컨테이너를 종료하며, systemd의 기본KillMode=control-group아래에서 cgroup 전체 킬은 Cgroup 전체 킬 항목에서 설명하는 대로 훅에도 도달합니다. 둘 다에서 강제 종료를 훅에 대해 치명적인 것으로 취급하고 유예 기간 대신 의존하세요. - 프로세스 그룹 전체 신호(예: 래퍼 스크립트의
kill -- -<pid>, 셸 작업 제어, 또는 그룹 전체 감시자): 러너 및 중간checkout훅 서브프로세스에 도달합니다. 의도적으로 그룹 연결 상태를 유지하지만 실행 중인post-session훅 또는 세션 자식에는 도달하지 않습니다. - Cgroup 전체 킬(예: systemd의 기본
KillMode=control-group또는terminationGracePeriodSeconds가 만료될 때 Kubernetes가 전체 컨테이너에 전달하는SIGKILL): 훅을 포함한 모든 것에 도달합니다. 프로세스 그룹 격리는 이에 대해 보호하지 않으므로 유예 기간은 전체 드레인 경로를 포함해야 합니다. - 훅의 자신의 타임아웃: 훅이
--post-session-hook-timeout-sec을 초과하면 러너는 훅의 전체 프로세스 그룹에SIGTERM을 보낸 다음 2초 후SIGKILL을 보내므로 훅이 포크한 워커(예: tar, rsync, git)는 래퍼 셸과 함께 종료되고 고아로 생존하지 않습니다. 러너의 감독은 훅의 stdio가 닫히면 끝납니다: 자신의 출력을 파일로 리디렉션하고SIGTERM단계를 능가하는 워커는 러너의 범위를 벗어납니다.
post-session 훅의 수를 기록하므로 조용한 드레인과 스냅샷 중간 드레인을 구분할 수 있습니다.
기본 디렉토리 및 용량을 러너 간에 동일하게 유지
러너가 세션 중간에 죽으면 서버는 세션을 재큐하고 환경의 다른 러너가 이를 선택합니다. 해당 러너는 자신의--base-dir 및 --capacity에서 체크아웃 경로를 파생합니다: --capacity 1은 --base-dir 아래에 직접 체크아웃하고, --capacity 1 이상은 대신 세션별 worktree를 사용합니다. 동일한 환경의 러너가 두 플래그에 대해 다른 값을 사용하면 재개된 세션의 작업 디렉토리가 변경되고, 에이전트가 이전에 기록한 절대 경로(편집, 도구 호출, 또는 자신의 노트)는 더 이상 존재하지 않는 위치를 가리킵니다.
환경의 모든 러너에서 동일한 --base-dir 및 --capacity를 사용하고, 인스턴스 ID 또는 호스트 이름과 같은 호스트별 값을 사용하지 마세요.
기본 디렉토리는 --base-dir 참조 행이 기록하는 예외를 제외하고 /workspace로 기본값입니다. 러너는 쓰기 액세스가 필요합니다. 시작 시 등록하기 전에 러너는 디렉토리를 생성하고 쓸 수 있는지 확인하고, 할 수 없으면 cannot create or write to base directory로 종료합니다. root로 시작된 러너는 기본값 /workspace를 자체 생성합니다. root가 아닌 러너의 경우 디렉토리를 생성하고 러너를 시작하기 전에 러너의 사용자에게 소유권을 제공하거나 --base-dir을 해당 사용자가 이미 소유한 디렉토리로 가리키세요.
사전 준비된 체크아웃 재사용
대규모 리포지토리의 경우 클론이 세션 시작을 지배할 수 있습니다.--capacity 1에서 checkout 훅 없이 러너는 <base-dir>/<repo-owner>/<repo>에서 리포지토리당 하나의 정규 클론을 유지하고 세션 간에 재사용합니다: 요청된 ref를 가져오고, HEAD를 분리하고, 이에 대해 하드 리셋합니다. 거의 변경되지 않았을 때 거의 즉시입니다. 콜드 클론을 건너뛰려면 다음 두 가지 방법 중 하나로 클론을 제공하세요:
- 이미지에 클론: 러너 이미지를 해당 경로에 빌드합니다. 모든 새로운 컨테이너는 디스크를 재사용하지 않고 준비된 클론으로 시작합니다.
- 지속적인 볼륨에 클론:
--lock-to-account로 한 사용자의 계정에 사전 잠긴 러너에서--base-dir을 지속적인 볼륨으로 가리키므로 디스크는 해당 계정만 제공합니다. 사전 잠긴 러너는 Claude Tag 채널 세션을 절대 선택하지 않으므로 이 옵션은 이들을 제공하는 러너에 적용되지 않습니다.
- 모든 클론 형태가 작동합니다: 경로의 전체, 얕은, 또는 단일 분기 클론은 그대로 사용됩니다. 러너는 기존 클론으로 가져올 때
--depth를 절대 전달하지 않으므로 전체 사전 준비는 전체 기록을 유지하고 얕은 것은 얕게 유지됩니다.CLAUDE_RUNNER_FETCH_DEPTH(full,0, 또는 숫자; 기본값 50)는 클론이 아직 없을 때 러너가 만드는 콜드 클론만 제어합니다. - 추적된 변경 사항 리셋, 추적되지 않은 파일 유지: 각 세션은 이전 세션의 추적된 수정을 지우는 하드 리셋에서 시작하지만 러너는 절대
git clean을 실행하지 않으므로 잠긴 소유자의 이전 세션의 추적되지 않은 파일은 트리에 유지됩니다. - git 프록시 포함, 리셋은 체크아웃이 됩니다:
--use-anthropic-git-proxy로 러너는 각 세션 전에 클론의.git/을 정제하여 객체 저장소, refs, 얕은 상태를 유지하지만 인덱스를 삭제하므로 각 세션은 거의 즉시 리셋 대신 전체 작업 트리 체크아웃을 지불합니다. 여전히 절대 재클론하지 않습니다. Submodule 사전 준비는 프록시 아래에서 지원되지 않습니다. - 긴 클론은 해결 방법이 필요하지 않습니다: 러너는 각 git 작업을 120초 진행 없음 감시자 및 30분 하드 캡으로 제한하며, 플랫 타임아웃이 아니므로 진행을 계속 보고하는 느린 콜드 클론이 완료됩니다.
버전 고정
각 세션의 자식 Claude Code 프로세스는 러너의 자신의 바이너리를 실행하고, 러너는 생성하는 세션 내에서 자동 업데이트를 끕니다. 따라서 모든 세션은 호스트에 설치하거나 이미지에 빌드한 버전을 실행합니다. 호스트 수준 업데이트는 러너가 다음 번에 시작할 때 적용됩니다.- 플릿을 한 버전으로 유지하려면: 이미지를 고정된 버전으로 빌드하거나 베어 호스트에 특정 버전을 설치하고 자동 업데이트를 비활성화하세요.
- 업그레이드하려면: 새로운 버전을 설치하거나 이미지를 다시 빌드한 다음 러너를 재시작하세요.
- 플러그인: 플러그인 마켓플레이스도 자동 업데이트되지 않습니다. 바이너리가 고정된 상태로 유지되는 동안 플러그인이 자동 업데이트되도록 하려면 러너의 환경에서
FORCE_AUTOUPDATE_PLUGINS=1을 설정하세요.
플릿 확장
오케스트레이터는 러너를 추가하거나 제거할 시기를 결정합니다. 소유자별 러너 잠금 때문에 최소 복제본 수는 동시에 활성화될 것으로 예상되는 사용자 및 Claude Tag 에이전트의 수입니다.--capacity는 소유자 간이 아닌 한 소유자의 세션 내에서 병렬 처리를 제어합니다.
두 가지 확장 접근 방식을 사용할 수 있습니다:
- 고정 플릿: 정적 러너 복제본 세트를 실행하고 각 러너가 제공하는 Prometheus 메트릭에서 확장하세요.
- 온디맨드 러너:
claude self-hosted-runner orchestrator서브명령을 실행하세요. 이는 Anthropic에서 사용 가능한 러너 없이 대기 중인 세션을 폴링하고spawn-runner훅을 호출하여 세션당 하나를 부팅합니다. 온디맨드 러너를 참조하세요.
알려진 문제 및 제한사항
다음은 이 릴리스의 제한사항이며, 해결 방법이 있는 경우 포함됩니다.커넥터 트래픽이 네트워크를 떠남
Anthropic은 GitHub, Slack, Linear, 및 기타 claude.ai 커넥터와 같은 커넥터 도구를 자신의 인프라에서 호출하므로 Claude가 자체 호스팅 세션에서 커넥터를 사용할 때 해당 트래픽은 러너 내부에서 발생하는 대신api.anthropic.com을 통해 이동합니다. 자체 호스팅 세션에서 커넥터를 제외하려면 다른 MCP 서버처럼 allowedMcpServers 및 deniedMcpServers 정책 설정으로 필터링하세요. Claude Code는 구성하는 서버뿐만 아니라 Anthropic이 전달하는 커넥터에도 이러한 설정을 적용하므로 다른 서버에 대한 허용 목록을 배포하면 Claude Code는 전달된 커넥터도 차단합니다. 다른 서버와 함께 커넥터를 사용 가능하게 유지하려면 전달된 커넥터에 대한 Anthropic 프록시 경로와 일치하는 항목을 추가하세요:
https://api.anthropic.com/v2/ccr-sessions/*https://api.anthropic.com/v1/code/sessions/*https://api.anthropic.com/v1/code/mcp/*
일부 세션은 유휴로 계산되지 않음
절대 완료되지 않는 배경 작업을 보유한 세션은 유휴로 계산되지 않으므로--release-idle-session-min은 해당 세션의 슬롯을 릴리스하지 않습니다. 실행 중인 도구 호출 내에서 요청된 승인을 기다리는 세션도 유휴로 계산되지 않습니다. 항상 --kill-session-after-min을 함께 설정하여 어떤 세션도 슬롯을 무한정 보유할 수 없도록 하는 하드 백스톱으로 사용하세요.
--kill-session-after-min은 폭주 세션에 대한 백스톱입니다. 러너는 제한에 도달한 모든 세션을 종료합니다. 누군가가 여전히 사용 중인 세션도 마찬가지이므로 플래그를 예상되는 가장 긴 세션보다 훨씬 높게 설정하세요(예: 8시간의 경우 --kill-session-after-min 480). 유휴 대화에서 슬롯을 해제하려면 대신 --release-idle-session-min을 사용하세요.
추가 제한사항
- 재개된 세션은 푸시되지 않은 작업을 잃음: 세션이 유휴 타임아웃 또는 러너 재시작에서 릴리스되고 사용자가 다른 메시지를 보내면 세션은 리포지토리를 시작 분기에서 다시 클론하는 새로운 러너에서 재개되므로 세션이 푸시하지 않은 작업은 사라집니다.
--push-outcome-on-release를 설정하여 러너가 릴리스하기 전에 세션의 결과 분기를 최선의 노력으로 푸시하도록 합니다. 재개된 세션은 대신 이러한 커밋에서 시작합니다. 이는 커밋된 작업을 보존하며, 더티 작업 트리는 아닙니다. 활성화하기 전에 소스 원격에서claude/*refs로 푸시할 수 있는 사람을 제한하세요(예: 분기 규칙 세트 포함): 재개 시 러너는 이전에 푸시된 분기를 누가 푸시했는지 확인하지 않고 가져오므로 이러한 refs에 푸시 액세스가 있는 모든 사람이 재개된 워크스페이스에 콘텐츠를 배치할 수 있습니다. 러너는 또한 재개 시 세션별 구성을 버립니다. 즉, 세션의 Claude 구성 디렉토리 및 세션이 작성한 모든 셸 상태입니다.--push-outcome-on-release는 이를 다루지 않습니다. - 개인 리포지토리는 세션 중간에 추가할 수 없음: 세션이 시작된 후 세션에 추가된 리포지토리는 자체 호스팅 러너에서 자격증명으로 클론되지 않으므로 추가가 실패합니다. 세션을 생성할 때 세션이 필요로 하는 모든 리포지토리를 선택하세요.
- 일부 커넥터는 자체 호스팅 세션에 나타나지 않음: claude.ai 설정에서 아직 연결하지 않은 커넥터는 자체 호스팅 세션에 나열되지 않으며, 세션은 연결하라는 메시지를 표시하지 않습니다. 먼저 설정에서 연결한 다음 새로운 세션을 시작하세요. 이미 실행 중인 세션에 커넥터를 추가해도 Claude가 도구를 사용할 수 없게 됩니다. 새로 추가된 커넥터를 선택하려면 새로운 세션을 시작하세요.
문제 보고
자체 호스팅 환경의 문제는 Anthropic 계정 팀에 문의하세요.문제 해결
안내 진단을 위해 러너 호스트에서 doctor 서브명령을 실행하세요. doctor 서브명령은 러너의 로그 및 상태가 첨부된 대화형 Claude Code 세션을 시작합니다. 해당 호스트에서 먼저claude auth login으로 서명하여 세션이 환경, 러너, 대기 중인 세션을 쿼리할 수 있도록 합니다. 해당 서명 없이(예: 호스트가 API 키로 인증할 때) 로컬 상태 엔드포인트, 메트릭, 러너의 로그로 제한되며, --log-file로 러너를 시작한 경우에만 로그를 읽습니다.
- 러너가 환경에 나타나지 않음: 호스트가 HTTPS를 통해
api.anthropic.com에 도달할 수 있는지, 환경 시크릿이 현재인지, 호스트 시계가 실제 시간의 5분 이내인지 확인하세요. 더 큰 스큐는 인증 실패를 유발합니다. 러너는 인증 실패 시 거부 이유와 함께[runner:fatal]을 기록합니다. - 러너가
cannot create or write to base directory로 시작 시 종료됨: 러너가--base-dir을 생성하거나 쓸 수 없습니다. 기본값은/workspace입니다. 디렉토리의 소유권을 수정하거나--base-dir을 쓰기 가능한 경로로 가리키세요. 기본 디렉토리 및 용량을 러너 간에 동일하게 유지에서 설명합니다. 러너가 대신 기본 디렉토리 확인이 시간 초과되었다고[runner:fatal]을 기록하면 디렉토리는 행(hung) 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 자격증명 및 설치되지 않은 빌드 도구입니다. 쓰기 불가능한 기본 디렉토리는 세션 실패 대신 시작 시 러너를 중지합니다. 이 목록의 러너가
cannot create or write to base directory로 시작 시 종료됨 항목을 참조하세요. - 세션이 인증하는 이그레스 프록시를 통해 네트워크에 도달할 수 없음:
--proxy-authorization-command또는--proxy-authorization-file로 설정한 소스가 실패하거나 30초 후 시간 초과되거나 빈 값을 생성하면 러너는 해당 연결에502 Bad Gateway로 응답하고 이유를 기록합니다. 러너는 해당 로그에서 명령의 stderr를 수정하고 헤더 값을 절대 기록하지 않습니다.--proxy-authorization-command로 호스트에서 명령을 직접 실행하여 전체 헤더 값을 stdout에 인쇄하는지 확인하세요. 러너가 대신could not start the proxy-authorization listener로 시작 시 종료되면 루프백 리스너를 열 수 없습니다. - 러너 로그에
rejecting the malformed poll response를 포함하는Poll failed라인: 러너가 큐의 예상 JSON이 아닌 본문을 가진 작업 폴 응답을 받았습니다. 가장 자주 러너와api.anthropic.com사이의 무언가(예: 가로채는 프록시 또는 캡티브 포털)가 자신의 페이지로 응답했기 때문입니다. 러너는 응답을 거부하고claude_code_self_hosted_runner_poll_errors_total메트릭의transport종류 아래에서 계산하고 세션 수명 주기에서 설명하는 실패한 폴 일정에서 재시도합니다. 러너는 라이브 세션을 계속 제공합니다. 프록시를 구성하여api.anthropic.com의 응답을 변경되지 않은 상태로 전달하세요. v2.1.246 이전에 러너는 그러한 응답을 빈 작업 큐로 읽었으며, 이는 라이브 세션을 종료하거나 종료하게 할 수 있습니다. - 세션의 분기가 원격에 더 이상 존재하지 않음: 세션이 읽기만 하는 git 소스의 경우 러너는 해당 소스를 건너뛰고 나머지에서 계속합니다. 세션이 결과를 푸시하는 소스의 경우 삭제된 분기(일반적으로 병합되고 자동 삭제되었기 때문)는 리포지토리 및 분기를 이름 지정하고 분기를 복원하고 재시도하도록 요청하는 오류로 세션을 실패합니다. 러너는 건너뛰기가 리포지토리 없이 남겨질 때 동일한 오류로 세션을 실패합니다. v2.1.228 이전에 그러한 세션은 빈 디렉토리에서 시작했습니다.
- 세션이 시작하는 데 분이 걸림: 초기 클론이 일반적으로 지배합니다.
claude_code_self_hosted_runner_session_init_duration_seconds메트릭을 확인하여 확인하고 사전 준비된 체크아웃 또는 더 작은CLAUDE_RUNNER_FETCH_DEPTH로 클론을 자르세요. - Pod이 드레인 중간에 종료됨:
terminationGracePeriodSeconds를 최소한 러너가 시작 시 기록하는 값으로 올리세요. 종료 타이밍을 참조하세요.
[runner:fatal] 라인 포함)를 stdout에 쓰고 디버그 출력을 stderr에 씁니다. 위의 문제 해결 항목에서 설명하는 시작 실패는 그 지점 전에 stderr에 인쇄됩니다. --log-file로 두 스트림을 캡처하세요. 이는 또한 self-hosted-runner doctor가 이들을 추적하도록 합니다. 또는 플랫폼의 로그 수집으로 캡처하세요. 각 세션의 자식 프로세스는 별도의 디버그 로그를 작성합니다. 실패 시 러너는 로그를 보존하고, 러너 로그에서 로그의 경로를 인쇄하고, claude.ai/code의 세션과 함께 로그의 꼬리를 표시합니다.
다음 단계
- 세션 사용자 정의: 래퍼 스크립트, 수명 주기 훅, 온디맨드 러너, MCP 서버, 권한
- 엔드 투 엔드 테스트: CI에서 새로운 러너 이미지를 확인한 후 프로모션
- 참조: 모든 CLI 플래그, 환경 변수, 메트릭