GitHub Enterprise Server 설계·설치부터 Entra 연동·CI/CD·운영까지
VMware 기반 GHES를 주 경로로, Microsoft Entra ID의 SAML·SCIM,
GitHub Enterprise 라이선스·Connect, Azure Blob Storage·자체 호스팅 Runner,
백업·복구·업그레이드·장애 대응을 단계별로 연결합니다.
전체 구조를 먼저 이해한 뒤 12단계의 준비값 → 조작 → 화면 → 완료 조건을 따라갑니다.
GitHub Enterprise ServerVMware / AzureEntra SAML + SCIMActions + Azure Blob절차 기준 GHES 3.213.22 차이 별도 확인일반 기업용12단계 화면 안내
문서의 범위와 사용 원칙
특정 사용자·회사·프로젝트를 전제하지 않는 범용 구축·운영 안내입니다. 개인 이름·실제 테넌트/서버 식별자·내부 대화 이력은 포함하지 않습니다. 호스트는 github.example.com, 식별자는 예시입니다. 실제 값·권한·승인·설치 버전으로 바꾼 뒤 사용하세요. 공식 캡처의 데모 계정·ID는 설명용이며 실제 입력값이 아닙니다.
Runner·Actions·Packages와 모니터링, 변경 관리, 장애 인계를 검증합니다.
설명용 개념도. GHES 중심의 구성 경계. Cloud·Entra·외부 Storage·Runner·백업은 별도 구성 요소이며 선택 기능은 지원 조건을 확인합니다.
구조도 읽기: SAML은 브라우저 로그인, SCIM은 Entra 서비스의 계정 생성·변경,
라이선스 파일은 서버의 한도·만료, Connect는 서버 사용량 보고입니다.
Runner는 GHES 밖에서 작업을 실행하고 Blob에 작업 로그·artifact를 저장합니다.
화살표가 연결돼 있어도 해당 기능의 인증·권한·실제 통신이 자동으로 완료되는 것은 아닙니다.
먼저 구분해야 하는 제품과 계정
대상
무엇을 하는가
이 문서에서의 경계
GHES
고객이 운영하는 가상 appliance. Git 저장소·협업·Actions 등을 고객 인프라에서 제공
직접 패치·백업·네트워크·리소스·인증을 운영. 일반 Linux 서버처럼 패키지나 에이전트를 임의 설치하지 않음
GHEC / EMU
GitHub 운영 Cloud 서비스 및 Cloud 관리형 사용자 방식
GHES와 별도 계정·별도 SSO/SCIM 대상. Cloud EMU의 shortcode_admin·OIDC 화면을 GHES에 그대로 적용하지 않음
GitHub Connect
조건에 맞는 Cloud Enterprise와 GHES 기능·라이선스 사용량 연결
계정 자동 복제 또는 기존 GHES 라이선스 파일의 자동 좌석 증설이 아님
GitHub Copilot
별도 구독·인증·정책을 가진 AI 개발 도구
GHES를 설치한다고 Copilot 모델·Cloud Agent가 appliance 안에 설치되는 것은 아님
단계별 통과 기준
작업을 했다는 기억이나 체크 표시가 아니라 아래 증거로 판단합니다. 미사용 기능은 사유와 승인자를 남겨 N/A로 처리합니다.
Gate
통과 증거
미충족 시
G0 · 설계·승인
제품·버전·배포 플랫폼·과금 모델, 담당·RPO/RTO·변경 창·사용자 범위 확정
Trial/유료·Cloud/Server·기능별 비용 혼선부터 해소
G1 · 인프라 준비
VM·별도 데이터 디스크, DNS·TLS 설계, 경로별 포트·외부 의존성·보안 승인
사설 주소에 포트만 열고 연결된다고 간주하지 않음
G2 · 안전한 기본 설치
실제 버전·유효 라이선스·FQDN/TLS·관리 콘솔·SSH·비상 계정 접근
SSO/SCIM 활성화나 대량 사용자 할당 보류
G3 · 신원 인수
해당 GHES Entra 앱 연결, 대표 사용자·운영 Owner 생성, SAML 로그인·회수 시험
Actions/Blob/Runner·artifact, Packages push/pull 등 선택한 기능의 실제 시험
기본 서버 설치 완료와 기능 운영 완료를 구분
G6 · 운영 인수
모니터링·비밀 회전·백업·격리 복원·업그레이드 계획·담당자 인수 증거
운영 확대 보류 또는 제한 범위·잔여 위험을 승인
작업 분류와 문서 동작
표시
뜻
대표 예
조회
고객 설정을 바꾸지 않는 확인. 인증·네트워크 권한과 결과의 민감성은 별도
GET API, 라이선스 정보, 로그 범위 조회
로컬 세션·파일
관리 PC 인증 컨텍스트나 증거 파일 생성
az login, 제한된 디렉터리, CSV·번들 다운로드
승인 후 변경
자원·권한·서비스·데이터·과금에 영향을 주는 작업
Save settings, SCIM on-demand, 라이선스 적용, workflow 실행, Storage 쓰기
실행 안전장치
명령은 자동 실행되지 않습니다. 복사 전에 실행 위치·도구·인증 주체·실제 값을 확인합니다. 관리 SSH는 122/admin, Git SSH는 22, 관리 콘솔은 8443입니다. curl -k, SSH 호스트키 검증 해제, 전체 재프로비저닝·계정 삭제·인증 해제를 일반 해결책으로 쓰지 않습니다. 토큰·연결 문자열·비밀번호·개인키는 문서나 셸 이력에 넣지 않습니다.
삽화는 설명용 개념도이며 실제 구축 화면이 아닙니다.
공식 화면 이미지는 해당 문서의 예시로 별도 출처를 표시합니다.
UI·명령·라이선스 조건은 설치 버전과 계약에 따라 달라질 수 있으므로 변경 전 해당 버전 원문을 재확인합니다.
아래 순서는 VMware 기반 GHES + Entra SAML/SCIM을 기준으로 합니다.
Cloud 병용·Actions·Packages·Copilot은 계약과 사용 목적에 따라 선택합니다.
기존 환경에서는 처음부터 재설치하지 말고 현재 단계의 설정·증거를 읽은 뒤 필요한 변경만 승인받습니다.
설명용 개념도. 기반 → 신원·연계 → 선택 기능·운영 순서로 진행합니다. 기존 배포는 현재 설정을 검증하고, 미적용 선택 항목은 N/A로 기록합니다.
캡처는 Microsoft/GitHub 공식 문서의 실제 예제 화면입니다. 개인·특정 기업의 운영 화면은 사용하지 않습니다. 각 화면의 ① 클릭 위치 → ② 입력·대조 값 → ③ 확인 결과를 따라가며 예시 이름·ID·날짜·좌석은 복사하지 않습니다. 검증된 캡처가 없는 화면은 조작 경로와 입력표로 설명하고 실제 UI처럼 새로 그리지 않습니다.
STEP 01 / 12 · 기본 순서 · 조작 전 승인 확인
01. 설계와 입력값 확정
담당
설계·서비스·보안 책임자
준비값
업무 범위·계약·버전·담당 역할
작업 위치
승인된 설계·변경 작업표
사용 범위·버전·책임자 결정
GHES 설치 버전·지원 패치, VMware/다른 플랫폼, 예상 사용자·Git/Actions 부하, Cloud 병용과 과금 모델을 결정합니다. 인프라·네트워크·Entra·GHES·DevOps·백업 담당 역할과 변경 승인자를 지정합니다.
비상 접근·변경 창·백업 계획 준비
Console root 암호·관리 SSH 키의 보관·복구 담당을 정하고 RPO/RTO·백업 위치를 설계합니다. 기존 환경의 인증·라이선스를 바꾸기 전에는 현재 설정·유효한 백업·복구 접근을 확보합니다.
입력표 작성
아래는 형식 예시입니다. 실제 값은 승인된 별도 작업표에 기록하고 토큰·개인키·암호는 비밀 저장소에 둡니다.
입력
예시 또는 확인 위치
혼동하지 않을 것
GHES FQDN / TLS
github.example.com / SAN·전체 체인·만료일
Cloud enterprise URL이나 IP로 대체하지 않음
VM / 디스크
지원되는 이미지·승인 CPU/RAM·root / data 분리
Runner를 GHES appliance에 설치하지 않음
DNS / NTP / proxy
승인된 resolver·time server·HTTP proxy·예외
사내 PC 접속 성공과 서비스 경로 성공은 다름
Cloud enterprise / 계약
선택한 기업과 Volume / Metered / Trial
계정 수·Copilot 좌석·Enterprise 소비·서버 키를 구분
Entra tenant / GHES 앱
Tenant ID + Enterprise application Object ID
Application(client) ID 및 사용자 Object ID와 다름
일반 파일럿 / 운영 Owner
승인된 소수 사용자 Object ID·직접 할당·역할
앱 Owners와 GitHub app role을 구분
Storage / Runner
실제 Blob endpoint·인증 모드 / OS·label·runner group
선택하지 않으면 STEP 09–10은 N/A
다음 단계로 넘어갈 조건: 실제 입력값·권한·승인 범위가 정리되고 미사용 기능은 N/A로 합의됐습니다.
Volume/Trial은 계약·Sales 또는 공식 Enterprise 다운로드 경로를 사용합니다. PAYG는 선택한 Cloud enterprise의 Licensing에서 consumed Cloud licenses를 확인합니다. Server-only 요구와 셀프서비스 발급 가능 범위가 다르면 Sales/Support에 먼저 확인합니다.
Cloud에서 파일 생성·다운로드
Cloud 프로필 → Enterprises → 대상 기업 → Billing and licensing → Licensing. Cloud 소비 증가 또는 키 만료 임박 안내가 있으면 Generate new license를 실행하고 Enterprise Server licenses → Download로 파일을 받습니다. 단순 다운로드가 용량 증설을 뜻하지는 않습니다.
후보 파일과 계약 대조
발급 대상·한도·만료일을 확인하고 제한된 위치에 보관합니다. 신규 설치는 STEP 04에서 적용합니다. 기존 서버가 있다면 설치 키의 seats와 실제 seats_used/seats_available를 비교하고 후보 파일 읽기 검사를 사용합니다.
키 교체 여부
기존 유효 키에 충분한 잔여 좌석이 있으면 신규 사용자마다 교체하지 않습니다. 용량 확대·만료 갱신이 필요할 때 새 파일을 승인 후 적용합니다. License sync는 파일 한도를 늘리지 않습니다.
Cloud 발급 화면의 검증된 캡처는 수록하지 않았습니다. 위 메뉴 경로와 공식 문서의 현재 UI를 대조합니다.
다음 단계로 넘어갈 조건: 유효한 GHES용 파일과 필요한 한도·만료일이 확인됐고 발급 기록이 남았습니다.
공식 OVA의 버전·무결성을 확인하고 Deploy OVF Template으로 배포합니다. 전원 투입 전 승인 자원·root 용량·별도 빈 data 디스크·네트워크 매핑을 대조합니다. OS를 따로 설치하지 않습니다.
최초 설정 보호·초기화
설치 담당자만 접근하도록 제한한 뒤 전원을 켭니다. https://github.example.com/setup의 최초 설정에서 라이선스를 올리고 Console root 암호를 정합니다. FQDN·Time·TLS를 구성하고 승인된 Save settings → 적용 완료 후 첫 웹 관리자 계정을 즉시 생성합니다.
관리 접근 확인
관리 SSH 공개키를 등록하고 ssh -p 122 admin@HOSTNAME으로 버전·시각·라이선스를 조회합니다. 웹 관리자, Console 자격, SSH admin을 서로 다른 접근으로 확인합니다. 기본 서비스·HTTPS·비상 로그인을 시험합니다.
기존 서버의 라이선스 갱신은 별도 경로
재설치하지 않습니다. 아래 L1/L2처럼 Update license → License file → Upload를 사용하고 백그라운드 반영 후 한도·유효성을 재조회합니다. 전체 OS 재부팅을 자동 후속 단계로 추가하지 않습니다.
L1 · User licenses → Update license
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
기존 상태부터 읽습니다. GHES Enterprise settings → Settings → License에서 현재 좌석·만료일을 확인하고, 승인된 갱신 때만 Update license로 이동합니다.
② 입력 / 대조할 값 · Input
대상 GHES는 https://github.example.com 같은 승인된 호스트입니다. 발급 대상·좌석 수·유효기간을 계약 및 새 라이선스 파일과 대조합니다.
③ 확인할 결과 · Expected
같은 GHES의 라이선스 업로드 화면으로 이동합니다. 링크를 여는 것만으로 라이선스가 갱신되지는 않습니다.
예시 범위·주의: 진입 링크만 표시한 공식 예제입니다. Unlimited Licenses·소비 좌석·2024년 만료일은 예시이며 실제 사용 권한이나 현재 상태가 아닙니다.
L2 · License file 선택·업로드
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
기존 라이선스를 먼저 확인합니다. 신규 설치·갱신 승인 후 License file을 선택하고 발급받은 .ghl 파일을 지정한 다음 Upload합니다.
② 입력 / 대조할 값 · Input
승인된 GHES용 라이선스 파일만 사용합니다. 파일 내용·계약 식별자·키는 문서나 공유 화면에 복사하지 않습니다.
③ 확인할 결과 · Expected
업로드 후 적용된 좌석·유효기간을 다시 확인합니다. 파일 선택 화면이나 버튼만으로 적용 성공을 판단하지 않습니다.
예시 범위·주의: 공식 예제의 Running version 3.17.3, No seat restrictions, Clustering enabled, 2026년 만료일은 설치 권장값이 아닙니다. 출처는 GHES 3.21 문서이나 원 캡처의 UI는 다를 수 있습니다.
다음 단계로 넘어갈 조건: 실제 버전·유효 키·HTTPS·관리 접근·비상 복구가 확인됐습니다. PAYG 등 계약상 Connect 선행 조건이 있으면 STEP 08의 연결을 이 시점에 먼저 확인합니다.
기존 계정 전환 영향을 검토하고 Phase 4의 절차로 built-in scim-admin·Console·SSH 복구 접근을 확보합니다. 기존 SAML에서 필요한 setup 옵션은 선택만 하지 말고 승인된 Save settings와 적용 성공까지 확인합니다.
Entra의 대상 테넌트·앱 식별
Enterprise applications에서 신규 승인 시 GitHub Enterprise Server 갤러리 앱을 추가합니다. (Legacy)는 사용하지 않습니다. 기존 앱이면 새로 복제하지 말고 정확한 Object ID와 목적지를 확인합니다. GHES SAML과 SCIM에는 동일한 GHES 앱을 사용하고 Cloud EMU 앱은 별개로 유지합니다.
S1 · Entra ID → Enterprise applications
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
Entra 관리 센터에서 디렉터리를 확인한 뒤 Entra ID → Enterprise apps(Enterprise applications)를 엽니다.
② 입력 / 대조할 값 · Input
이번 GHES 인증·프로비저닝용 테넌트를 읽기 확인합니다. App registrations 목록과 구분합니다.
③ 확인할 결과 · Expected
대상 테넌트의 Enterprise application 목록으로 이동합니다.
예시 범위·주의: 메뉴 진입용 공식 캡처입니다. 신규 앱 생성이나 GHES 연결 완료를 보여주지 않습니다.
S2 · All applications에서 기존 GHES 앱 찾기
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
Search by application name or object ID에서 승인된 기존 GHES 앱을 검색합니다. 신규 구축 승인이 있을 때만 New application으로 별도 진행합니다.
예시 범위·주의: 목록·검색 위치 예시입니다. 화면의 앱명은 공식 fixture이며 운영 대상이 아닙니다. 조회 실패를 이유로 기존 앱을 복제하지 않습니다.
S3 · Overview: Application ID와 service principal Object ID
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
선택한 Enterprise application → Overview에서 ID를 읽습니다.
② 입력 / 대조할 값 · Input
Application ID는 client ID입니다. 이 화면의 Object ID는 해당 테넌트의 service principal ID이며 App registrations의 Object ID와 다릅니다.
③ 확인할 결과 · Expected
SAML·SCIM용 앱과 조회한 service principal이 같은 대상임을 확인합니다.
예시 범위·주의: Exchange 공식 문서의 Room Booking Tool(RoomBookingTool) 앱 예시입니다. ID 위치 설명용 구형 Azure AD 화면이며 GHES 앱 또는 현재 테넌트의 캡처가 아닙니다.
인증 전환 전 일반 파일럿 할당
Users and groups에서 승인된 일반 파일럿을 할당합니다. 기존 환경 전환이면 필요한 기존 사용자 범위도 검토합니다. 일반 사용자 생성 문제를 Owner 부여로 우회하지 않습니다.
F1 · Users and groups: 할당·Role 읽기
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
기존 Users and groups 목록을 먼저 읽습니다. 승인된 신규 할당만 Add user/group → 대상 선택 → Select → Select a role(제공될 때) → Assign으로 진행합니다.
② 입력 / 대조할 값 · Input
사용자/그룹 Object ID·직접 할당·그룹 직접 멤버·현재 Role을 대조합니다. Entra 앱 Owners와 GHES enterprise owner 앱 역할은 다릅니다.
③ 확인할 결과 · Expected
필요한 파일럿만 의도한 역할로 할당됩니다. 앱 할당만으로 GHES 사용자 생성이나 저장소 접근 완료를 선언하지 않습니다.
예시 범위·주의: Microsoft Entra SAML Toolkit 1 공식 fixture입니다. 할당 진입 화면만 보이며 사용자 선택창·확장된 Role 목록·최종 Assign 화면은 없습니다. 전원 Owner 부여나 임의 app role 생성은 하지 않습니다.
SP URL과 claim 입력
Single sign-on → SAML에서 아래 기본 URL·claim을 구성합니다. objectidentifier와 SCIM externalId는 같은 사용자 객체여야 하며 NameID와는 별도 필드입니다.
S4 · Basic SAML Configuration: GHES URL
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처 · GHES 3.21 SAML·SCIM 제품 기준
① 클릭할 위치 · Click
같은 GHES 앱 → Single sign-on → SAML에서 기존 값을 읽습니다. 신규 구축 또는 승인된 수정 때만 Basic SAML Configuration → Edit → Save합니다.
② 입력 / 대조할 값 · Input
Identifier (Entity ID): https://github.example.com | Reply URL (ACS): https://github.example.com/saml/consume | Sign on URL: https://github.example.com/sso. example.com은 설명용이며 실제 승인 호스트로 모두 일치시킵니다.
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처 · GHES 3.21 SAML·SCIM 제품 기준
① 클릭할 위치 · Click
Attributes & Claims → Edit에서 기존 매핑을 읽습니다. 변경·저장은 승인된 신규 구성 또는 수정일 때만 수행합니다.
② 입력 / 대조할 값 · Input
Unique User Identifier(NameID)·UPN과 별개로 http://schemas.microsoft.com/identity/claims/objectidentifier → Entra 사용자 Object ID → SCIM externalId의 일치를 대조합니다.
③ 확인할 결과 · Expected
같은 사용자 객체가 SAML과 SCIM에서 연결됩니다. 표시 이름·메일·NameID가 같다는 이유만으로 externalId가 맞다고 판단하지 않습니다.
예시 범위·주의: 기본 claim 일부만 표시한 공식 예시입니다. objectidentifier가 안 보인다고 없다고 단정하지 말고 상세 설정을 읽으세요. administrator=true 예제를 무조건 적용하거나 Owner를 강제 부여하지 않습니다.
IdP 인증서·URL을 GHES에 연결
Base64 공개 인증서, Login URL, Microsoft Entra Identifier를 수집해 GHES Management Console → Authentication → SAML의 Verification certificate·Single sign-on URL·Issuer에 연결합니다. 변경 승인 후 저장·적용 완료를 확인합니다. 아래 캡처는 Entra 값 위치이며 GHES 화면을 재구성한 것이 아닙니다.
S6 · SAML Signing Certificate: Base64 공개 인증서
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처 · GHES 3.21 SAML·SCIM 제품 기준
① 클릭할 위치 · Click
기존 활성 인증서·만료일을 읽고 SAML Signing Certificate → Certificate (Base64) → Download를 선택합니다.
② 입력 / 대조할 값 · Input
Thumbprint·유효기간·활성 서명키를 대조합니다. GHES SAML verification certificate용 공개 인증서이며 TLS 서버 인증서나 Federation Metadata XML과 다릅니다.
③ 확인할 결과 · Expected
승인된 구성에 사용할 공개 인증서를 준비합니다. 다운로드만으로 GHES 인증서가 교체되지는 않습니다.
예시 범위·주의: 인증서 다운로드 위치의 공식 예시입니다. 표시된 ID·만료일은 fixture입니다. 교체는 별도 승인 후 IdP 활성 키·GHES 신뢰·비상 접근을 함께 검증합니다.
S7 · IdP Login URL·Identifier → GHES SAML 설정
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처 · GHES 3.21 SAML·SCIM 제품 기준
① 클릭할 위치 · Click
SAML 하단 Set up [앱명]에서 기존 Login URL과 Microsoft Entra Identifier를 읽습니다. 승인된 구성 때만 해당 값을 GHES에 입력·저장합니다.
② 입력 / 대조할 값 · Input
Entra Login URL → GHES Single sign-on URL. Microsoft Entra Identifier → GHES Issuer. 이 IdP issuer는 https://github.example.com이라는 GHES Entity ID와 다릅니다.
③ 확인할 결과 · Expected
IdP URL·issuer·공개 인증서가 같은 테넌트/앱 설정과 맞습니다. 승인된 저장 후 SCIM 대상 사용자의 프로비저닝을 먼저 확인하고 별도 브라우저로 파일럿 SSO를 시험합니다.
예시 범위·주의: 공식 fixture의 tenant GUID·URL을 복사하지 않습니다. 이 캡처는 Entra 값 위치이며 GHES Save settings 또는 실제 SSO 성공 화면이 아닙니다.
다음 단계로 넘어갈 조건: SAML URL·issuer·인증서·파일럿 할당·복구 접근이 일치합니다. SCIM 활성 환경의 실제 SSO 완료는 STEP 06의 계정 생성 후 확인합니다.
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처 · GHES 3.21 SAML·SCIM 제품 기준
① 클릭할 위치 · Click
GHES 앱 → Provisioning에서 기존 configuration을 먼저 선택합니다. 신규 구축 승인 때만 New configuration을 사용합니다.
② 입력 / 대조할 값 · Input
앱·대상 URL·job 상태·마지막 주기와 Attribute mapping, Provisioning logs, Provision on demand 진입 위치를 확인합니다.
③ 확인할 결과 · Expected
SAML과 동일한 GHES 앱의 configuration을 식별합니다. 오류 진단을 위해 Start/Restart 또는 중복 configuration 생성을 하지 않습니다.
예시 범위·주의: 새 configuration 진입을 보여주는 Preview UI 예시입니다. 기존 job 실행 증거가 아닙니다. 구형 UI에서는 Automatic → Admin Credentials가 바로 보일 수 있습니다.
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처 · GHES 3.21 SAML·SCIM 제품 기준
① 클릭할 위치 · Click
기존 configuration → Admin Credentials를 읽습니다. 승인된 연결 시험만 Test Connection으로 실행하고, 신규/변경 승인 때만 Create 또는 Save합니다.
② 입력 / 대조할 값 · Input
Tenant URL: https://github.example.com/api/v3/scim/v2. Secret Token: •••••••• (마스킹 유지·복사 금지). 신규 입력은 승인된 GHES setup user의 classic PAT(scim:enterprise)를 보안 경로로 취급하며 문서에 붙여넣지 않습니다.
③ 확인할 결과 · Expected
연결 시험의 UTC·결과를 기록합니다. 성공은 연결/인증 확인이지 사용자 생성·역할 반영 성공이 아닙니다.
예시 범위·주의: 빈 입력란의 공식 예시이며 실제 토큰은 없습니다. GHES 3.21의 /api/v3/scim/v2를 기준으로 하며 Learn의 축약 표기 /api/v3/scim, Cloud api.github.com/scim/v2/enterprises/…, 8443 콘솔 URL과 혼동하지 않습니다.
연결 시험 후 파일럿 범위·매핑 저장
Test Connection 성공과 실제 GHES 수신 로그를 확인한 뒤 신규 구성의 Save/Create를 진행합니다. 사용자 externalId/userName/active/roles, 직접 할당·보안그룹 직접 멤버와 Scope를 확인하고 Sync only assigned users and groups 및 승인된 소규모 파일럿으로 제한합니다.
F3 · Properties: Scope·알림·삭제 방지
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처 · GHES 3.21 SAML·SCIM 제품 기준
① 클릭할 위치 · Click
기존 Properties/Settings와 Attribute mapping을 읽습니다. 신규 또는 승인된 수정 때만 편집·Apply/Save합니다.
② 입력 / 대조할 값 · Input
Provisioning scope: Sync only assigned users and groups. 알림·accidental deletion threshold를 승인 정책과 대조합니다. 별도 매핑 상세에서 externalId, userName, active, roles 및 필터를 확인합니다.
③ 확인할 결과 · Expected
의도한 소규모 파일럿만 범위에 포함되고 역할·활성 상태·삭제 방지 조건이 설명됩니다. Scope 전체 확대나 전체 Restart를 기본 해결책으로 사용하지 않습니다.
예시 범위·주의: 공식 예제의 threshold 500과 Preview 상태는 권장값이 아닙니다. roles/externalId 상세 매핑 화면은 없으므로 재구성하지 않았습니다. 실제 앱이 제공하는 매핑·역할을 별도로 읽습니다.
일반 파일럿 한 명 온디맨드
정확한 사용자 Object ID를 확인해 한 번 실행합니다. 계정 생성·수정·비활성화가 가능한 변경 작업입니다. 장기 bearer PAT 방식은 이를 위해 정상 자동 job을 Stop할 필요가 없습니다. 새 할당 전파에는 수 분 걸릴 수 있으며 통상 30초 미만 안내는 완료 SLA가 아닙니다.
F6 · Provision on demand: 승인된 파일럿 선택
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
기존 GHES 앱 → Provision on demand에서 대상 한 명을 검색하고 Object ID·할당·범위·예상 작업을 읽습니다. 승인 후에만 Provision을 실행합니다.
② 입력 / 대조할 값 · Input
동명이인을 피하기 위해 사용자 Object ID로 대조합니다. 변경 전 active·역할과 예상 Create/Update/Disable 등 작업을 확인합니다.
③ 확인할 결과 · Expected
승인된 한 명의 실제 작업 결과를 열어 확인할 수 있어야 합니다. 온디맨드는 읽기 시험이 아니라 실제 계정 변경입니다.
예시 범위·주의: AHCustom 공식 fixture의 그룹 멤버 2명 선택 예시입니다. 단일 사용자 생성 화면이 아니며 두 명을 그대로 선택하라는 지시도 아닙니다. 메뉴·선택 흐름만 참고합니다.
F7 · Perform action·View details: 실제 작업 판정
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
실제 파일럿의 온디맨드 결과에서 Perform action → View details를 읽습니다. 결과 확인만을 위해 다시 Provision하지 않습니다.
② 입력 / 대조할 값 · Input
Action·Status·Target ID·변경 속성·UTC를 대조하고 GHES SCIM identity, active, 역할을 별도로 확인합니다.
③ 확인할 결과 · Expected
실제 사용자 작업의 성공 후 파일럿 SAML 로그인·Org/저장소 권한을 따로 검증합니다. Skip이나 Test Connection 성공을 사용자 생성으로 해석하지 않습니다.
예시 범위·주의: AHCustom의 Group membership operations에서 두 멤버 추가를 보여주는 공식 fixture입니다. GHES 단일 사용자 생성 또는 Role 강제 반영 성공 캡처가 아닙니다.
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
Provisioning logs에서 실제 GHES 앱·사용자·할당 이후 시각으로 필터링하고 Status 전체를 읽습니다.
② 입력 / 대조할 값 · Input
사용자 Object ID·UTC·Create/Update/Disable/Delete/Skipped·오류 detail을 구분합니다. 성공만 필터링해 누락을 숨기지 않습니다.
③ 확인할 결과 · Expected
해당 사용자의 이벤트 유무와 작업 종류를 설명하고 같은 시각의 GHES 기록과 연결합니다. 로그가 없다고 재생성이나 Restart부터 하지 않습니다.
예시 범위·주의: Salesforce·Google 등 여러 앱의 공식 예제입니다. 보이는 이름·성공 건수는 fixture이며 실제 GHES 결과가 아닙니다.
F5 · Steps: 범위·매칭·대상 작업
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
대상 provisioning 이벤트를 열고 Steps와 세부 속성을 읽습니다.
② 입력 / 대조할 값 · Input
범위 판정·매칭·실패 단계·Target ID·변경 속성·오류 detail을 대조합니다. Change ID와 GHES request ID가 같다고 가정하지 않습니다.
③ 확인할 결과 · Expected
동일 사용자의 동일 UTC 작업으로 원인을 좁힙니다. 읽기 진단과 승인된 복구 변경을 분리합니다.
예시 범위·주의: Box 대상의 성공 Steps 공식 예시입니다. GHES 성공 증거 또는 현재 장애 원인 캡처가 아닙니다.
Owner·자동 동기화 검증 후 확대
운영 Owner가 필요하면 비상 접근을 유지한 채 Disable administrator demotion/promotion 제어·역할 매핑을 상세 절차대로 조정·적용합니다. 승인된 파일럿 범위로 Start provisioning하고 정기 동기화의 실제 roles·GHES Owner·로그인을 확인합니다. 온디맨드 성공만으로 역할 동기화 완료를 판단하지 않습니다. 이미 Running이면 전체 Restart하지 않습니다.
다음 단계로 넘어갈 조건: 파일럿의 계정 생성·활성·SSO, 필요한 운영 Owner와 비상 접근이 확인됐고 자동 job 상태·오류 분기가 기록됐습니다.
업무·보안 정책 경계에 맞춰 Organization을 정하고 base permission을 검토합니다. 프로젝트별 팀을 만들고 사용자 → SCIM 그룹 → 그룹 멤버 → GHES 팀 연결 순서로 확인합니다.
저장소 권한 부여
Organization → Teams → 팀의 Identity Provider Groups에서 승인 그룹을 연결하고, 저장소 Settings → Collaborators and teams에서 Read/Write/Maintain/Admin을 업무별로 부여합니다. 기존 팀 전환은 멤버 제거·접근 상실 영향 검토 후 진행합니다.
허용·거부를 일반 계정으로 시험
승인 사용자와 비허용 사용자를 분리해 Private 웹·Git 읽기를 확인합니다. Base permissions=None이 Internal 가시성까지 차단한다고 보지 않습니다. PR 승인·status check·CODEOWNERS 강제도 실제 실패 시험으로 확인합니다.
다음 단계로 넘어갈 조건: 일반 사용자의 허용·거부·그룹 회수 경로가 확인됐습니다. 관리자 공유 인증으로 대신 시험하지 않았습니다.
양쪽 enterprise 관리 권한·계약 자격·동일 사용자 매칭 방식을 확인합니다. GHES의 실제 egress·프록시·Cloud IP allowlist와 필요한 목적지 443을 검증합니다. 해당 계약에서 Connect를 요구하면 STEP 04 직후부터 이 조건을 충족시킵니다.
Connect 연결 후 필요한 기능만
GHES 프로필 → Enterprise settings → GitHub Connect → Enable GitHub Connect에서 올바른 Cloud enterprise와 연결합니다. 별도로 License sync → Enable을 선택합니다. 사용자 ID·이메일 등 데이터 전송 범위·수신지를 승인받습니다.
C1 · GitHub Connect: License sync → Enable
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
Enterprise settings → GitHub Connect에서 기존 연결 대상과 License sync 상태를 읽습니다. Connect 연결·변경 승인 후에만 Enable을 선택합니다.
② 입력 / 대조할 값 · Input
같은 계약의 GHES와 Cloud enterprise 연결을 대조합니다. 주간 자동 사용량 보고와 GHES .ghl 파일 적용은 별개입니다.
③ 확인할 결과 · Expected
활성화 후 주간 GHES → Cloud 라이선스 사용량 보고를 Cloud 측 보고서에서 확인합니다. 활성화 버튼만으로 보고 완료를 판단하지 않습니다.
예시 범위·주의: 공식 원본은 License sync의 Enable 버튼만 보여줍니다. Sync now는 이 그림에 없습니다. 주간 사용량 동기화는 라이선스 키 갱신·좌석 증설·사용자 프로비저닝이 아닙니다.
사용량 전송과 키 적용을 각각 확인
자동 사용량 전송은 주 1회입니다. 필요하면 Enterprise settings → Settings → License/Licensing → License sync → Sync now를 승인 후 실행합니다. Cloud Licensing의 해당 Server source·마지막 성공·중복 제거 결과를 확인합니다. 키의 한도·만료는 STEP 02/04와 별개입니다.
다음 단계로 넘어갈 조건: Enabled뿐 아니라 실제 사용량 전송·수신·중복 제거 증거가 있습니다. 미사용이면 계약·요구사항 확인 후 N/A로 기록합니다.
지원되는 Azure Blob 계정·실제 endpoint·네트워크 경로를 준비합니다. OIDC와 Credentials-based를 혼용하지 않습니다. Private Endpoint면 GHES와 Runner 각각 DNS·라우팅을 확인합니다. 기존 Shared Key 오류에 RBAC 역할 추가만으로 해결됐다고 판단하지 않습니다.
OIDC 선택 시 앱·federation 구성
Storage 인증용 Entra 앱을 등록해 client/tenant ID를 기록합니다. GHES 사용자 SAML/SCIM 앱과 목적을 구분하고 아래 값을 입력합니다.
A1 · Storage OIDC 앱: Client ID·Tenant ID
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
현재 Actions Storage 인증 방식부터 확인합니다. OIDC를 사용하는 경우 Storage용 App registrations → Overview의 기존 값을 읽습니다. 신규 앱 생성은 별도 승인입니다.
사용자 SAML/SCIM 앱과 별도의 Storage 인증 앱을 정확히 식별합니다. Shared Key 방식 오류에 OIDC 앱 설정을 무조건 적용하지 않습니다.
예시 범위·주의: GitHub 공식 Azure 앱 예시이며 이름·ID는 fixture입니다. Azure 구독/Billing과 인증 테넌트는 별도 확인 대상입니다. 이 화면은 Storage IAM 권한 부여 결과가 아닙니다.
Storage OIDC 입력
형식 / 조건
Issuer
https://github.example.com/_services/token
Subject
github.example.com — 프로토콜 없음
Audience
api://AzureADTokenExchange — 실제 클라우드·federation 조건과 대조
RBAC
Storage account scope의 해당 앱 service principal에 Storage Blob Data Owner
외부 검증 접근
https://github.example.com/_services/token/.well-known/openid-configuration https://github.example.com/_services/token/.well-known/jwks 두 주소 모두 외부 인증 서비스에서 도달 가능해야 함
A2 · Storage 앱: Federated credentials 진입
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
Storage 앱 → Certificates & secrets → Federated credentials에서 기존 신뢰를 읽습니다. 신규 또는 변경 승인 때만 Add credential을 사용합니다.
GHES appliance가 아닌 승인된 OS의 전용 호스트·계정을 사용합니다. GHES HTTPS·필요 Blob·공개 action/패키지 경로, 인증서 신뢰와 runner group의 허용 저장소를 준비합니다.
등록 범위·OS 선택
조직용은 Organization → Settings → Actions → Runners → New runner에서 OS·architecture를 선택합니다. 저장소용과 조직용 URL·권한을 혼동하지 않습니다. 아래는 공식 선택 화면 예시입니다.
R1 · Self-hosted runner 추가: OS·아키텍처 선택
공식 문서 원본 PNG · 확대 후 Esc로 축소
공식 공개 문서에 수록된 실제 UI 캡처 원본을 변형 없이 내장했습니다. 합성·재구성 UI가 아니며 현재 운영 대상에서 촬영한 화면도 아닙니다. 앱명·데모 사용자·tenant/앱 ID·호스트·날짜·상태는 공식 예제 fixture이며 고객 정보가 아닙니다. 원 캡처일은 미상이고 구형 Azure AD·Preview UI가 포함될 수 있습니다. 예제 식별자를 복사하지 마세요. 공식 원문 출처
① 클릭할 위치 · Click
기존 runner·group·허용 저장소를 먼저 읽습니다. 승인된 신규 등록은 조직 Settings → Actions → Runners → New runner로 진행합니다. 저장소 범위에서는 Repository Settings → Actions → Runners → New self-hosted runner입니다.
② 입력 / 대조할 값 · Input
실제 runner 머신의 OS·아키텍처와 조직/저장소 등록 범위를 선택합니다. 예시 호스트는 https://github.example.com입니다. 등록 토큰은 ••••••••로 취급하고 문서·로그에 복사하지 않습니다.
③ 확인할 결과 · Expected
실제 GHES 화면이 제공하는 명령을 승인된 runner 머신에서 실행한 뒤 Online/Idle·허용 저장소·파일럿 job 결과를 확인합니다. 선택 화면만으로 등록 성공을 판단하지 않습니다.
예시 범위·주의: 공식 문서가 조직·저장소·enterprise 절차에 공통으로 사용하는 OS/Architecture 원본 PNG입니다. New self-hosted runner/New runner 버튼 자체·등록 토큰·완료 상태는 이 그림에 없습니다. Linux/x64 선택은 예시이며 OS 지원 범위와 실제 머신을 별도 확인합니다.
화면이 생성한 설치 명령으로 등록
해당 GHES가 제공한 다운로드·검증·config 명령을 Runner 호스트에서 순서대로 실행합니다. 등록 토큰은 비밀이며 문서에 옮기지 않습니다. 정상 Listening/Idle을 확인하고 필요한 서비스 구성은 승인된 권한으로 수행합니다.
작은 워크플로로 왕복 검증
Phase 9의 합성 데이터 workflow를 승인된 시험 저장소에 적용합니다. checkout → artifact upload → download → 내용 비교를 확인합니다. GHES 호환 action ref를 사용하며 GitHub.com의 artifact v4+ 예제를 무조건 가져오지 않습니다.
다음 단계로 넘어갈 조건: Runner online만이 아니라 실제 job과 artifact 왕복이 성공했습니다. 미사용이면 STEP 09와 함께 N/A로 기록합니다.
담당: 아키텍트·서비스/가상화/보안 책임자선행: 업무·규제·연결 요구 수집산출물: 버전·플랫폼·사양·RPO/RTO·책임 승인서
적용 범위와 안전 원칙
공식 문서를 기준으로 일반 기업의 신규 배포·라이선스·네트워크 검증 절차를 설명한다. 실제 구성·계정·측정 결과는 승인된 환경에서 별도로 확인한다. 명령은 실행 예시일 뿐 이 문서 생성 과정에서 실행하지 않는다. github.example.com, examplerepo 및 대괄호 자리표시자는 승인된 값으로 교체한다. 기본 절차는 GHES 3.21의 VMware 단일 인스턴스이며, HA·인증·Actions는 각각 별도 승인 후 확장한다.
0-1. 제품과 운영 책임을 먼저 선택한다
선택
운영·인증 경계
결정 질문
GitHub Enterprise Server (GHES)
기업이 가상 어플라이언스, 네트워크, 업그레이드, 백업·복구를 운영한다. GHES용 SAML·SCIM 절차를 사용한다.
데이터 위치와 연결 제한을 직접 통제해야 하는가? 상시 운영 담당과 복구 예산이 있는가?
GitHub Enterprise Cloud (GHEC)
GitHub가 서비스 인프라를 운영한다. 일반 사용자 계정 기반 기업 또는 EMU 기업을 선택한다.
서버 운영 대신 클라우드 정책·IdP·사용량 관리에 집중할 수 있는가?
Enterprise Managed Users (EMU)
GHEC의 계정 관리 방식이다. IdP가 GitHub.com 또는 GHE.com의 관리형 계정을 프로비저닝한다.
계정 수명주기의 중앙 통제와 기업 외부 협업 제한이 요구사항에 맞는가?
EMU는 GHES에 설치하는 기능이 아니다
GHES의 SAML·SCIM 지원과 GHEC의 EMU는 서로 다른 제품별 구성이다. Cloud를 병용해도 계정·조직·정책이 자동 복제되지 않는다. EMU 선택 시 아래 공식 문서를 별도 절차로 이용하며, 이 가이드의 설치 선행조건으로 삼지 않는다.
위 값은 GHES 3.21 VMware 문서의 최소 권장 구성이지 성능 보증이 아니다. Actions는 기본 CPU·메모리에 각각 최소 25%, Code Security도 각각 최소 25%의 추가 자원을 계획한다. 두 기능을 모두 쓰면 두 증가 요인을 함께 반영한다. Actions 자체의 최소 조건인 8 vCPU / 64 GB도 동시에 충족해야 하므로 단순히 표에 25%만 더해 끝내지 않는다.
CPU 증설 시에는 16 vCPU까지 vCPU당 최소 6.5 GB 메모리 추가를 권장한다. 이는 증설 지침이며 위 표 전체를 대체하는 전역 최소 비율이 아니다. 예를 들어 12 vCPU / 80 GB는 검증을 시작할 계획안일 뿐, 사용자 50명 또는 특정 runner 수용량을 보증하지 않는다. runner 연결 수·동시 job·job 길이·artifact 크기·Git 부하는 서로 다른 지표이다. runner는 어플라이언스와 분리된 실행 호스트에 둔다.
부하 목록 수집
저장소 수·대형 저장소 크기·LFS 증가량·동시 clone/fetch·API/webhook 빈도·Code Security 분석·Actions job 및 artifact/cache 보존량을 적는다. 반복 polling은 줄이고 webhook 기반 연계를 검토한다.
스토리지 설계
SSD의 지연시간·지속 IOPS·동시 부하 여유를 확인한다. 기본 루트 디스크는 200 GB이므로 비클러스터 신규 배포는 400 GB로 사전 조정한다. 약 절반은 업그레이드·롤백용이어서 400 GB 전체가 루트 파일시스템에 표시되지 않는다.
데이터 볼륨 분리
루트와 별도로 새 빈 데이터 디스크를 전원 투입 전에 연결한다. 기존 데이터나 파티션이 있는 디스크를 재사용하지 않는다. VMware는 thick provisioning with lazy zeroing을 권장한다. 데이터 디스크 초기화·포맷 명령을 수동 실행하지 않는다.
파일럿으로 수정
업무를 대표하는 시험 저장소 examplerepo와 승인된 부하로 clone·push·API 지연, CPU·메모리 압박, 디스크 지연·여유, 백업 시간을 측정한다. 목표·경보 임계값을 사전에 합의하고 초과하면 확장 후 재시험한다. 좌석 수만으로 운영 승인하지 않는다.
업무 시간, RPO [허용 데이터 손실 시간], RTO [복구 완료 목표 시간], 보존 기간, 복구 우선순위
서비스 책임자가 승인하고 백업 담당자가 복구 시험으로 검증. HA는 백업을 대체하지 않는다.
인프라
VM 사양·데이터스토어·분리 데이터 디스크·확장 여유·장애 도메인
관제 담당은 조회, 가상화 담당은 승인된 변경 창에서만 변경.
DNS·NTP·TLS
FQDN, resolver, NTP, SAN, 인증서 체인·만료일·갱신 일정
네트워크·PKI 책임자를 각각 지정. 개인키 보관자와 업로드 수행자를 구분.
특권 접근
웹 enterprise owner, Console root/운영자, SSH 공개키 소유자, 비상 접근 경로
전담 운영 주·부 담당자 지정. 일반 관제 계정에 SSH 전체 권한을 주지 않고 자격증명은 비밀 저장소에 보관.
변경·지원
요청자, 승인자, 수행자, 검증자, 중단 조건, 지원 연락 경로
조회 기록과 변경 이력을 분리. 실패 시 설정 재저장·재부팅을 반복하지 않고 증거를 보존.
일반 Linux 서버가 아니다
GHES는 x86-64 가상 어플라이언스다. ARM VM, 임의 OS 위 apt/npm 설치, 내부 애플리케이션 파일 수정, 어플라이언스에 runner·백신 에이전트 등 임의 소프트웨어 추가를 기본 절차로 삼지 않는다. 공식 지원 범위 밖 작업은 GitHub Support에 사전 확인한다.
담당: 구매·Cloud billing·GHES 운영 담당선행: Phase 0 제품 선택산출물: 라이선스 파일·한도/사용량 대조표·갱신 책임
1-1. 계약 모델부터 판별한다
경로
발급·좌석 기준
선행조건 / 담당
독립형 유료·Volume/Subscription
Sales가 계약을 설정하고 구매 좌석·계약 기간에 맞는 서버 파일 제공. Cloud·Server 병용 권리를 포함한다.
구매·라이선스 담당이 계약과 파일 수령 경로 확인. 모든 경우에 Cloud 기업을 먼저 만들 필요는 없다.
GHES 평가판
승인된 trial 파일의 기간·제한을 확인한다. 운영용 계약과 혼동하지 않는다.
공식 Enterprise 사이트의 평가·다운로드 경로. Cloud 생성이 보편적인 필수조건은 아니다.
PAYG / Metered
Cloud-first. 사용자를 먼저 Cloud 조직에 할당하고, 키 생성 시점의 consumed Cloud licenses를 서버 좌석 기준으로 사용. 생성 키 유효기간은 1년.
Cloud 기업·조직·청구 권한 준비. 공식 병용 표는 GHES 3.13+ 및 GitHub Connect를 명시한다.
서버만 사용하는 PAYG 사용자의 처리
공식 문서는 Server-only 사용자가 이메일 중복 제거 후 metered 청구에 추가된다고 설명한다. 그러나 서버 키의 설치 한도는 생성 당시 Cloud 소비 좌석에 묶인다. 이 설명을 ‘서버 전용 인원만으로 원하는 키를 셀프서비스 발급할 수 있다’로 해석하지 않는다. Cloud 조직 할당 없이 서버 전용으로 시작하거나 한도가 부족한 계약은 Sales·Billing Support에 발급·청구 경로를 확인한다.
Cloud People > Members의 전체 수나 Total consumed 값을 키 좌석 산정에 대신 쓰지 않는다. Billing and licensing > Licensing의 consumed Cloud licenses를 확인한다. GHEC 계정·SCIM 계정 생성만으로 Enterprise 유료 좌석 소비가 확정되지 않는다. 조직에 속하지 않은 unaffiliated 사용자, Copilot만 배정된 인원 수도 GHE 소비 좌석 수와 같지 않다. 조직 소속·협업자 역할·구독 유형 등 공식 과금 조건을 확인하고 특히 Visual Studio 결합 라이선스의 예외도 별도 검토한다.
현재 값 기록
계약 모델, Cloud 소비 좌석, 설치된 GHES 키 한도, GHES 실제 사용 좌석, 만료일을 서로 다른 열로 적는다. PAYG 생성 전 조직 할당이 완료되고 Licensing 화면의 소비에 반영됐는지 확인한다.
좌석 확대
설치 한도 확대가 필요하면 PAYG는 Cloud 소비 증가를 확인한 뒤 새 서버 키를 생성·다운로드하고 GHES에 직접 업로드한다. Cloud 인원 증가만으로 기존 서버 키 한도가 자동 확대되지 않는다. Volume은 추가 구매 후 제공된 파일을 적용한다.
Connect의 경계 확인
라이선스 동기화는 GHES → Cloud 사용량 보고 및 이메일 기반 중복 제거다. 계정 프로비저닝이나 Cloud → GHES 키·quota 자동 갱신이 아니다. 자동 보고는 매주 실행되며 Sync now도 사용량만 전송한다. 한도·만료일을 바꾸는 작업과 분리한다.
만료 대응
만료일·내부 갱신 담당·알림 시점을 기록하고 갱신 파일 업로드 후 재검증한다. 키 만료 시 웹·Git 접근을 사용할 수 없으므로 정상 업무 중단 전에 처리한다. 회사명·키 원문·사용자 이메일이 담긴 출력은 공개 문서에 붙이지 않는다.
승인된 기업 소유자 권한으로 GitHub Enterprise Cloud에 접속한다. 프로필 → Enterprise 또는 Enterprises → 대상 기업 → Billing and licensing → Licensing으로 이동한다. consumed Cloud licenses 증가 또는 만료까지 30일 이하일 때 표시되는 노란 배너의 Generate new license를 선택한다. Enterprise Server licenses → Download로 파일을 받는다. 올바른 기업인지, 파일 생성일·수량이 요청과 일치하는지 대조한다.
독립형·평가 경로
Cloud 기업이 없는 경우, 평가판, GHE.com Volume 또는 경로가 불명확한 경우 공식 enterprise.github.com/download에서 계약 권한으로 확인한다. 파일이 없으면 구매·Sales에 문의한다. 단순히 Cloud 계정부터 새로 만드는 것으로 해결하지 않는다.
안전한 보관
파일의 계약·만료일·좌석을 확인하고 접근 제한 저장소에 보관한다. 다운로드 권한과 GHES 업로드 권한을 분리한다. 이메일 본문, 저장소, 실행 명령 인자에 라이선스 원문을 넣지 않는다.
신규 설치
Phase 3에서 격리된 최초 설정 화면에 파일을 업로드하고 root Management Console 암호를 설정한다. 아직 생성되지 않은 웹 사용자나 IdP 계정 암호를 입력하는 단계가 아니다.
기존 인스턴스 갱신
웹 site administrator로 로그인 → Enterprise settings → Settings → License → User licenses / Quick links → Update license. Console 인증이 요구되면 별도 Console 자격증명을 사용한다. License file 선택 → Upload. 백그라운드 반영에 몇 분 걸릴 수 있으므로 완료 후 한도·만료일을 다시 확인한다.
Console 사용자명을 혼동하지 않는다
Console의 Root site admin 경로는 최초 설정에서 정한 암호로 인증한다. 별도 Management Console user를 만든 경우 해당 Console 사용자명·자격증명을 쓴다. 웹 enterprise owner의 로그인명, SAML 로그인, SSH의 고정 사용자명 admin을 Console 사용자명으로 대입하지 않는다.
판정: info는 설치 키의 seats·unlimited_seating·expire_at 등을 보여준다. check는 유효한 키라면 License is valid.를 반환한다. 출력은 실제 값이며 예시 좌석 수를 정답으로 기대하지 않는다.
ghe-license info의 seats는 실제 사용 인원이 아니라 키 한도다. seats: 0이고 unlimited_seating: true이면 무제한 의미이지 사용자가 0명이라는 뜻이 아니다. 사용량은 License UI 또는 다음 REST 조회의 seats_used와 구분한다.
조회 · gh가 이미 설치되고 대상 GHES의 승인된 인증이 설정된 관리자 PC · bash
gh api --hostname github.example.com --method GET /enterprise/settings/license
판정: GHES REST API의 HTTP 200과 seats, seats_used, seats_available, kind, expire_at, days_until_expiration을 확인한다. 인증·권한 오류는 별도 해결하며 이 예시는 토큰 생성이나 scope 변경을 하지 않는다.
변경 승인 번호·수행자·검증자·변경 창과 현재 기업·Cloud 소비·설치 한도·사용량·만료일·조회 시각을 기록한다. 기존 .ghl은 접근 제한 저장소에 보존하고 덮어쓰지 않는다. 이전 키가 만료됐거나 현재 사용량을 수용하지 못하면 되돌리기도 안전하지 않으므로 복구 가능 여부와 Support 연락 기준을 먼저 승인받는다.
후보 파일만 조회
승인된 전달 경로로 관리 셸에서 읽을 수 있는 제한된 위치에 새 .ghl을 준비한 뒤 아래 명령을 사용한다. /APPROVED/PATH/new-license.ghl은 실제 승인 경로로 바꾼다. 생성일은 다운로드 기록과 함께 대조한다. 이 검사는 설치 키를 교체하지 않으며 check 성공만으로 올바른 기업·수량을 보증하지 않는다.
조회 · 승인된 GHES 관리 SSH 셸; 접근 제한된 후보 파일만 검사 · bash
GHE_LICENSE_FILE=/APPROVED/PATH/new-license.ghl ghe-license info
GHE_LICENSE_FILE=/APPROVED/PATH/new-license.ghl ghe-license check
판정: 후보 파일의 seats·unlimited_seating·expire_at과 유효성을 승인 요청에 대조한다. 환경변수는 각 조회 명령에만 적용된다. 회사명·파일 원문은 공개 기록에 남기지 않는다.
License 화면이 HTTP 500이면
오류 시각·대상 화면·요청 ID를 보존하고 승인된 관리망에서 https://github.example.com/setup으로 Management Console에 진입한다. 별도 Console 자격증명과 TCP 8443 접근을 확인하고 실제 Console UI의 라이선스 업로드 화면을 사용한다. Console까지 실패하면 반복 업로드·재부팅 대신 오류 증거를 가지고 Support에 문의한다.
승인된 업로드·반영 대기
1-3의 License file → Upload로 후보 파일을 올린다. 백그라운드 반영은 몇 분 걸릴 수 있으나 고정 SLA가 아니다. 완료 상태를 확인하고 중복 업로드를 피한다. 전체 OS 재부팅은 공식 업로드 절차의 필수 단계로 문서화되어 있지 않으며 개별 재부팅 경험을 일반 요구사항으로 삼지 않는다. CLI의 --apply는 영향을 받는 서비스를 재시작하므로 별도 변경 승인이 필요하다. 추측한 import 구문이나 구성 적용 명령을 기본 후속 작업으로 실행하지 않는다.
변경 후 비교·종료
1-4의 환경변수 없는 ghe-license info·ghe-license check로 설치 키를 다시 조회하고 License UI/REST의 한도·사용량·만료일, 웹·Git 서비스 복귀를 기록한다. 변경 전·후 값과 업로드 완료 시각을 한 표에 남긴다. 불일치·오류는 파일/적용/사용량을 분리해 조사하고 승인·유효성 확인 없이 이전 파일로 되돌리지 않는다. Connect 보고와 사용자 생성 성공은 별도 검증한다.
담당: 네트워크·PKI·IAM·GHES 운영 담당선행: FQDN·토폴로지·기능 선택산출물: 방화벽 행렬·DNS/TLS·Cloud 경로 증거
2-1. 연결을 시작하는 주체별로 방화벽을 설계한다
아래 포트는 모두 GHES 인바운드로 개방하는 목록이 아니다. 출발지·목적지·프로토콜·반환 트래픽·프록시 경로·업무 용도를 변경 요청서에 적는다. 실제 도입한 기능만 승인하고 관리망은 사용자망과 분리한다.
설명용 개념도. 경로별 통신 방향. 관리 PC 접속, 브라우저 SSO, Entra SCIM, Connect 및 Actions Storage 연결은 서로 다른 증거가 필요합니다.
시작 주체 → 목적지
포트 / 조건
허용 범위·검증
사용자 PC → GHES
TCP 443 / Git SSH는 TCP 22
웹·HTTPS Git과 SSH Git을 구분. 22는 관리 셸이 아니다. 80은 승인한 HTTP→HTTPS 전환 용도일 때만.
관리자·점프 호스트 → GHES
TCP 8443 / TCP 122
Console / 관리 SSH. 지정 운영망만 허용하고 일반 사용자·인터넷 전체에는 개방하지 않는다.
사용자 브라우저 ↔ GHES·IdP
각 HTTPS TCP 443
SAML 브라우저 리디렉션·응답 경로. PC의 SSO 성공은 IdP 서버의 SCIM 연결 성공을 의미하지 않는다.
Entra 프로비저닝 서비스 → GHES SCIM
TCP 443 / Cloud 직접 연결 구성일 때
외부에서 해석·도달 가능한 DNS, NAT 또는 LB/WAF 게시 경로, 신뢰 가능한 TLS 필요. 사설 IP에 443만 열어서는 부족.
GHES → GHEC / GitHub Connect
이 절차는 HTTPS TCP 443 사용; 공식 설명은 TLS 연결의 443 또는 80
GitHub.com 대상은 github.com, api.github.com, uploads.github.com 세 호스트를 승인한다. 평문 HTTP 허용으로 해석하지 않는다. GHE.com은 별도 공식 목적지를 확인하며 인바운드 관리 포트를 열지 않는다.
runner → GHES·API·Actions/artifact 호스트
TCP 443
실제 GHES FQDN·API 하위 도메인·반환된 다운로드 호스트를 확인. cache 및 직접 전달되는 artifact는 runner → Blob 경로도 필요.
GHES → Azure Blob / 인증 서비스
TCP 443 / Blob 선택 시
실제 승인된 Blob endpoint를 허용한다. login.microsoftonline.com은 저장소 OIDC 인증을 선택한 경우에 포함한다. 직접 연결·Private Endpoint별 DNS와 경로를 검증하며 GHES 성공만으로 runner 다운로드를 판정하지 않는다.
클라우드 OIDC 검증 서비스 → GHES
TCP 443 / OIDC 외부 저장소 인증 시
공개 discovery·JWKS URL에 접근 필요. Blob 데이터 트래픽 방향과 반대인 인증 경로를 별도 심사.
GHES → 지정 DNS / NTP
DNS UDP·TCP 53 / NTP UDP 123
승인 resolver·시각 서버만 목적지로 지정. 모든 클라이언트에서 GHES로 53·123을 여는 규칙이 아니다.
GHES → SMTP 릴레이
설정한 SMTP 포트·TLS 방식
메일 발송용 아웃바운드. 인바운드 메일 회신 기능의 TCP 25는 선택 기능으로 별도 검토.
HA 노드 상호 간
TCP 122 및 UDP 1194
HA 구성의 모든 노드 사이에 필요한 양방향 연결. 인터넷·전체 사내 대역으로 확장하지 않는다.
GHES 및 runner → GitHub.com (각 경로 별도)
TCP 443 / 공개 Actions 자동 접근을 켠 경우
양쪽 아웃바운드가 필요하다. runner의 github.com, api.github.com, codeload.github.com 등 공식 요구를 검토. Connect 세 호스트가 모든 workflow 의존성을 포함하지 않으며 작업별 외부 패키지·레지스트리는 별도 승인.
github.example.com과 내부·외부 DNS 응답, VIP/NAT, TTL, 갱신 담당을 승인한다. GHES 내부 resolver에서도 자신의 이름이 해석되어야 한다. 초기 설정 후 hostname 변경은 장애·보안키 무효화 가능성이 있으므로 단순 DNS 변경 작업으로 취급하지 않는다. 필요 시 공식 신규 인스턴스·복원 경로 및 Support를 검토한다.
하위 도메인 격리
*.github.example.com wildcard DNS 또는 공식 목록의 개별 레코드를 만든다. assets, avatars, codeload, raw, uploads, media, gist, pages 등 사용할 서비스가 같은 승인된 게시 경로로 해석되는지 확인한다. API·Actions에 필요한 이름도 해당 기능 문서와 함께 확인한다. 격리 후 이전 /raw/ 같은 경로의 404를 전체 서비스 장애로 오판하지 않는다.
TLS 준비
SAN에 github.example.com과 *.github.example.com을 포함한다. wildcard만으로 루트 FQDN은 보호되지 않는다. GHES 업로드용 인증서·중간 체인은 PEM, 개인키는 암호 없는 RSA PEM으로 준비하고 개인키 보관자를 지정한다. 내부 CA는 승인된 PC·runner의 신뢰 저장소에 배포하되 Cloud SCIM 클라이언트도 그 체인을 신뢰한다고 가정하지 않는다.
LB/WAF 확인
클라이언트 → LB에서 TLS를 종료해도 LB → GHES는 HTTPS를 유지한다. HTTP 다운그레이드는 지원되지 않는다. FQDN·SNI·인증서 검증·SCIM 경로·HTTP 메서드·Authorization 헤더가 정상 전달되는지 확인한다. WAF의 브라우저 인증 챌린지나 로그인 HTML 응답을 SCIM API 앞에 두지 않는다.
NTP·인증서 수명
승인 NTP primary·secondary를 지정하고 UDP 123 반환 경로를 확인한다. 하이퍼바이저 시각 강제 설정과 GHES NTP가 충돌하지 않게 한다. TLS 갱신은 발급→키 전달→업로드→변경 창→전체 체인·SAN 재검증으로 운영하고 만료 경보·주/부 담당을 둔다.
Entra 출발지 허용 목록은 최신 공식 값으로 관리
Microsoft Learn의 IP Ranges 절은 AzureActiveDirectory 서비스 태그를 안내한다. 사용 중인 Cloud에 맞는 최신 공식 IP 범위 파일/API, 검토 날짜, 갱신 책임자를 기록한다. 이 문서에 고정 IP를 복사하거나 모든 Azure·인터넷 IP를 일괄 허용하지 않는다. 일반 온프레미스 SCIM provisioning agent는 별도 애플리케이션 통합 방식이다. GHES 갤러리 앱에 에이전트를 붙이면 자동으로 동일 지원을 받는 대체 경로라고 가정하지 말고 양쪽 지원·매핑·인증 방식을 검증한다.
외부 저장소 OIDC를 선택하면 https://github.example.com/_services/token/.well-known/openid-configuration과 https://github.example.com/_services/token/.well-known/jwks의 공개 도달성을 별도 승인한다. 완전 사설망 정책과 양립하지 않으면 무작정 전체 사이트를 공개하지 말고 인증 방식과 배포 설계를 다시 결정한다.
판정: OpenSSL 3.x인지 확인 후 SNI·hostname·체인 검증 성공 및 Verify return code: 0을 확인한다. curl -q는 사용자 curl 설정을 읽지 않으며 리디렉션을 자동 추적하지 않는다. 200 또는 설계한 30x의 Location을 검토하고 TLS 오류·다른 호스트 이동이면 중단한다.
동일 검사를 assets 등 실제 사용하는 하위 도메인에도 반복한다. 내부 CA라면 승인된 CA 번들을 사용하도록 도구를 구성한다. -k로 검증을 끄거나 -L로 잘못된 리디렉션을 숨기지 않는다. 401/403은 HTTP 서버 도달의 단서일 뿐, 인증·권한·SCIM 동작 성공은 아니다.
증상
우선 분리할 원인
검증 증거
DNS는 되지만 TCP timeout
라우팅·NAT·보안 그룹·방화벽·LB health
같은 시각의 출발지와 경계 장비 허용/차단 로그.
TLS 이름·체인 오류
SAN·SNI·중간 인증서·프록시 TLS 검사·클라이언트 trust
검증한 이름, 만료일, 체인 결과. 개인키는 수집하지 않는다.
PC 성공 / Entra 실패
공개 DNS·Cloud 출발지·WAF 정책·Cloud가 신뢰하지 않는 CA
Entra Test Connection 시각·오류와 LB/GHES 요청 수신 로그 비교.
SCIM 401/403/404 또는 HTML
토큰·권한·SCIM 활성화·endpoint·리디렉션·WAF 챌린지
IAM 담당이 endpoint와 인증을 확인. 네트워크 전체 허용으로 해결하지 않는다.
등록된 runner에서 cache 실패
runner → Blob 직접 연결·DNS·프록시·스토리지 권한
GHES → Blob 성공과 별개로 runner의 실제 다운로드 endpoint·오류 확인.
설치 전 설계 게이트
방화벽 규칙과 DNS·TLS 발급·NTP·외부 게시 책임을 승인한다. 아직 기동하지 않은 GHES의 연결 성공을 요구하지 말고 Phase 3 이후 실행 검증 항목을 미완료로 남긴다.
네 가지 증거 수집
기동 후 ① 각 실제 호출 경로의 DNS 결과 ② FQDN·체인 포함 TLS 성공 ③ IAM 설정 후 Entra의 실제 Test Connection 결과 ④ 동일 시각의 LB/WAF 및 GHES 요청 수신·응답 상관관계를 모은다. 시각·경로·상태코드·요청 ID를 기록하고 토큰·개인정보는 가린다.
제한된 파일럿
네 가지 증거가 확보된 후 소수의 승인된 사용자로 SSO와 프로비저닝을 검증한다. Test Connection은 사용자 생성·수정·중지를 모두 시험하는 기능이 아니므로 실제 수명주기는 SCIM 단계에서 확인한다. 대기 시간이 0이거나 항상 40분 이내라는 SLA를 약속하지 않는다.
외부 연결 차단을 진단하려고 프록시 없이 넓은 아웃바운드를 임시 허용했더라도 운영 최종 상태로 승인된 것은 아니다. 프록시 전환·재시험이 남아 있으면 미완료로 기록한다. 이 절차는 새 광범위 허용을 권장하지 않는다.
현재 규칙 고정·승인
기존 규칙 ID·출발지·목적지·포트·직접/프록시 경로·만료 시각·담당자·승인자를 적고 네트워크 로그로 실제 외부 NAT IP를 확인한다. GHES 사설 IP나 관리자 PC 공인 IP로 대신하지 않는다. 변경 창·중단 기준·승인된 복구 경로를 정한다.
승인된 HTTP 프록시 구성
Management Console의 HTTP Proxy Server와 HTTP Proxy Exclusion에서 승인 URL·포트와 꼭 필요한 예외만 검토한다. GHES → 프록시 경로와 프록시 → 외부 목적지 경로를 따로 승인한다. Actions 사용 시 HTTP 프록시만 지원되며 HTTPS/SOCKS5 프록시는 지원되지 않는다. HTTP 프록시를 쓰더라도 목적지 HTTPS/TLS 검증은 유지한다. Privacy/Private mode 변경은 공개 범위에 영향을 주므로 별도 보안 검토 없이 해제하지 않는다. 승인된 설정 저장은 서비스 재시작·중단 가능성을 고려하고 구성 완료를 기다린다.
Connect 세 목적지·Cloud 허용 목록
github.com, api.github.com, uploads.github.com의 TCP 443을 프록시 경유로 허용한다. GHES 서비스가 실제 쓰는 경로와 프록시 예외를 확인하고 전환 후 외부 NAT IP를 기록한다. Cloud 기업에 IP allowlist가 있으면 이 실제 출구 IP/대역을 승인받아 반영한다. 임의 IP 확인 사이트로 조회하지 말고 경계 장비·프록시 로그를 사용한다.
경로 시험과 기능 시험 분리
2-5의 제한된 무인증 검사를 수행하고 서비스 요청의 같은 시각 로그로 프록시 통과를 대조한다. 이어 실제 GitHub Connect 사용량 동기화 결과·최근 성공 시각·Cloud 수신 값을 확인한다. 별도로 승인된 파일럿 사용자의 SCIM 생성·조직 할당·로그인을 확인한다. 동기화 성공은 계정 생성이나 설치 키 확대의 증거가 아니다.
임시 규칙 회수·재시험
승인된 프록시 경로의 성공 증거와 복구 계획을 검토한 뒤 변경 창에서 임시 광범위 규칙을 제거한다. 제거 후 같은 Connect·프로비저닝·필요한 Actions 검사를 다시 수행해 우회 경로 의존이 없음을 확인한다. 실패하면 증거를 보존하고 사전 승인된 복구 절차를 적용하며 무기한 전체 허용으로 돌아가지 않는다.
Blob은 실제 저장소 endpoint의 TCP 443, 저장소 OIDC를 선택한 경우에만 login.microsoftonline.com을 추가한다. 직접 연결 또는 Private Endpoint에 맞는 DNS 응답·라우팅·프록시 예외를 GHES와 runner 각각 확인한다. 지정 DNS의 UDP/TCP 53과 NTP의 UDP 123은 HTTPS 프록시와 별도 경로다. runner 프록시·출구 IP는 GHES와 같다고 가정하지 않으며 공개 Actions·패키지·레지스트리 의존성도 별도 시험한다.
승인된 GHES 관리 셸에서 서비스와 같은 프록시·DNS·CA 신뢰·예외 경로인지 먼저 확인한다. Console 설정이 셸 curl에 자동 반영된다고 가정하지 않는다. 불일치하면 네트워크 담당이 승인된 시험 경로를 준비한 뒤 실행한다. 토큰·Authorization·쿠키를 추가하지 않고 환경변수 전체나 프록시 자격증명을 덤프하지 않는다. PC에서 수집한 성공 로그만으로 GHES 서비스 경로를 입증할 수 없다.
담당: 가상화·GHES 운영 수행자와 검증자선행: Phase 0–2 승인·공식 이미지·키·관리망산출물: 검증된 기반 인스턴스·관리 접근·IAM 인계서
3-1. 공식 이미지와 변경 창을 준비한다
진입 조건 확인
Phase 0의 플랫폼·사양, Phase 1의 라이선스 파일, Phase 2의 FQDN·DNS·TLS·관리망을 준비한다. 수행자·검증자·중단 조건·지원 연락 경로를 정하고 초기 설정 동안 담당자가 자리를 비우지 않는다.
공식 OVA 확보
3.21 Release notes에서 설치일에 승인한 지원 패치를 선택 → Download GitHub Enterprise Server X.X.X → GitHub On-premises의 VMware ESXi/vSphere (OVA) → Download. 비공식 재패키징 이미지를 사용하지 않는다.
출처·무결성 확인
공식 다운로드 주소, 실제 파일명·버전·크기, vSphere가 표시하는 서명·발행자·인증서 검증 결과를 기록한다. 공식 checksum 또는 서명 검증 자료가 제공되면 그 값·방법과 대조한다. 임의 SHA 값을 만들어 기대값으로 쓰지 않는다. 서명·무결성 오류가 나면 우회하지 않고 재다운로드 또는 Support 확인 후 진행한다.
원본 OVA를 보존하고 비클러스터 400 GB 루트 권장을 적용한다. 공식 VMware 가이드의 배포 전 OVF disk attributes 조정 경로를 따른다. 원본 무결성 검사와 승인된 템플릿 변경 기록을 구분하고, 변경 후 manifest·서명 오류가 있으면 검증 우회 없이 배포 담당과 해결한다. 부팅 후 임의 파티션 편집으로 맞추지 않는다.
Deploy OVF Template
vSphere Client에서 승인 호스트·클러스터를 선택하고 Deploy OVF Template로 공식 이미지를 가져온다. VM 이름·대상·데이터스토어·네트워크 매핑을 대조한다. 디스크와 향후 확장 여유가 충분한 datastore, 권장 Thick Provision Lazy Zeroed를 선택한다.
자동 전원 투입 해제
Power on after deployment를 선택하지 않는다. 배포 후 Edit Settings에서 승인된 CPU·메모리·루트 용량·관리 경로를 다시 확인한다. 잘못된 네트워크 매핑은 최초 설정 화면을 외부에 노출할 수 있다.
새 데이터 디스크 연결
Add New Device → Hard Disk에서 별도 새 데이터 디스크를 만들고 Phase 0의 승인 용량을 지정한다. 루트 디스크를 데이터 디스크로 착각하지 않도록 장치·용량을 대조한다. 데이터가 있거나 비어 있는지 증명할 수 없는 디스크는 연결하지 않는다.
부팅·네트워크
검증자 확인 후 전원을 켠다. OS를 따로 설치하지 않는다. vSphere 콘솔에서 IP·gateway·DNS를 확인하고 필요 시 콘솔의 S 네트워크 설정에서 승인된 값을 입력한 뒤 D로 완료한다. 화면의 실제 옵션을 확인하며 원격 세션이 끊길 수 있는 변경을 무작정 반복하지 않는다.
최초 부팅 전부터 경계 방화벽으로 설치 담당자만 접근하게 한다. 초기 TLS는 자체 서명 상태일 수 있으므로 승인된 콘솔·호스트 확인 절차로 접속 대상을 확인한다. 자체 서명 경고를 영구 예외로 배포하지 않는다. 라이선스 업로드, root Console 암호 설정, 첫 웹 사용자 생성을 지연하면 다른 사람이 인스턴스를 선점할 수 있다.
라이선스·Console 암호
관리자 브라우저에서 https://github.example.com/setup으로 최초 설정에 진입한다. Management Console은 HTTPS 8443 경로를 사용하므로 해당 관리 포트를 허용한다. 공식 파일을 업로드하고 최초 root Management Console 암호를 설정·금고에 보관한다.
Hostname·DNS·Time
Console의 Hostname에 승인된 FQDN을 지정한다. DNS resolver는 VM 콘솔에서 확인한 값을 사용하고 자신과 필수 외부 이름의 해석을 확인한다. Time의 Primary NTP server와 필요 시 Secondary NTP server를 지정한다. 호스트 이름을 시험용 별칭으로 시작한 뒤 운영명으로 바꾸는 방식을 피한다.
격리·TLS
Hostname → Subdomain isolation (recommended)을 선택한다. TLS 설정에서 TLS only (recommended), 인증서/전체 체인, Unencrypted key를 지정한다. 버전별 TLS/Privacy 화면 배치를 확인하되 TLS 적용을 이유로 조직의 Private mode 정책을 임의로 해제하지 않는다. 기업 공개 범위 변경은 별도 승인 사항이다.
검토 후 Save settings
hostname·DNS·NTP·라이선스·TLS·인증 방식을 검증자와 대조한다. Actions는 외부 저장소·인증·runner 설계가 완료될 때까지 비활성 상태로 둔다. Save settings 후 구성 실행이 완료되고 최초 재시작이 끝날 때까지 기다린다. 일반 설정 저장도 서비스 재시작·사용자 중단을 유발하므로 변경 창을 적용한다.
첫 웹 사용자
Visit your instance로 이동해 첫 built-in 웹 관리자 계정을 즉시 만든다. 강한 암호와 복구 수단을 보관하고 제공되는 2FA를 설정한다. 첫 관리자 권한과 Enterprise settings 접근을 확인한 후 일반 사용자에게 서비스를 공개한다. 최초 Console 암호를 이 웹 계정 암호로 재사용하지 않는다.
후속 IAM 인계
SAML과 SCIM 단계는 별도 변경이다. SCIM에는 공식 절차의 built-in scim-admin enterprise owner가 필요하다. 첫 웹 관리자와 자동으로 같다고 가정하지 않는다. SAML 전환 전에 비상 로그인·승격·중복되지 않는 사용자명과 이메일을 검증한다. 여기서는 SCIM 토큰을 발급하지 않는다.
Root로 User Management → Create user에서 운영자 생성 가능. 운영자는 다른 Console 계정을 생성·삭제하지 못한다.
관리 SSH TCP 122
고정 사용자 admin + Console에 승인된 개인별 공개키
웹 Settings의 Git SSH 키와 별도. 개인키는 PC/승인 키 저장소에 남기며 서버나 문서에 복사하지 않는다.
공개키 등록
웹 Site admin → Management Console → SSH access → Add new SSH key에 운영자 공개키만 붙여넣고 Add key를 누른다. 소유자·지문·회수일을 기록한다. 이 변경은 즉시 적용되며 이를 위해 Save settings를 누를 필요가 없다.
호스트 지문 대조
최초 SSH 연결 전 서버 호스트 키 지문을 승인된 콘솔 또는 별도 신뢰 경로로 확보한다. 프롬프트의 지문과 대조한 뒤 승인한다. 호스트 키 확인을 끄거나 변경된 키를 무조건 삭제해 접속하지 않는다.
판정: 승인한 실제 버전·hostname·키 유효성을 대조한다. ghe-system-info는 JSON 시스템 정보다. df/free는 일반 읽기 전용 현황 조회이며 공식 사이징 검사나 부하 시험을 대체하지 않는다. root의 약 절반 예약과 별도 데이터 마운트를 확인한다.
출력에 포함된 시스템 식별자·네트워크 정보는 제한된 운영 기록에만 보관한다. root 여유가 예상보다 작다고 패키지 삭제·파티션 포맷·OS 업데이트를 실행하지 않는다. 설정값 전체 덤프 대신 필요한 hostname만 조회하고, 저장소·토큰·개인키가 포함될 수 있는 로그를 공개 공유하지 않는다.
완료 항목
남길 증거
실패 시 조치
버전·디스크
승인 패치와 실제 버전 일치, 루트/데이터 장치 및 용량
다르면 사용자 유입 전 중단. 데이터 디스크를 덮어쓰거나 강제 초기화하지 않는다.
DNS·TLS·NTP
FQDN과 하위 도메인 검사, 체인·SAN·만료, Time 상태·동기화 확인
Phase 2로 돌아가 원인을 수정. 연결 실패를 TLS 해제나 무조건 재저장으로 우회하지 않는다.
라이선스
키 check, 한도·만료일, 별도로 확인한 사용량
파일·계약·적용 시점 확인 후 구매 또는 Support에 문의.
관리·비상 접근
첫 웹 owner 접근, Console 운영자, 122 공개키 지문·소유자, 비상 자격증명 금고
역할별 로그인 성공을 개별 확인. 웹 로그인만으로 전체 관리 접근 성공 처리하지 않는다.
구성 실행
Save settings 완료 시각·오류 유무·서비스 복귀
오류 화면·시각·변경값을 보존하고 원인을 분리. 설정 적용 중 강제 재부팅·재배포 금지.
다음 단계로 넘어가는 범위
이 단계는 기반 설치 완료이지 운영 전체 승인이나 SCIM 검증 완료가 아니다. 다음은 SAML·SCIM의 제한된 파일럿이다. Actions는 외부 Blob·인증·네트워크·runner·용량이 준비된 별도 단계에서만 켠다. 운영 서비스 개시 전에는 RPO/RTO에 맞는 백업·복원 시험도 완료해야 한다.
GitHub와 Microsoft의 공식 문서를 기준으로 인증·프로비저닝·권한·라이선스 운영 절차를 설명하는 GHES 3.21 가이드다. 3.22 및 다른 패치의 UI·동작은 해당 버전에서 재검증한다. Cloud Enterprise Managed Users(EMU)의 초기 계정·OIDC·API 경로를 그대로 복사하지 않는다. 이 문서의 도메인과 계정은 예시이며, 명령은 승인된 환경에서 담당자가 실행하는 절차이지 실행 결과가 아니다.
SAML은 로그인, SCIM은 계정 수명주기, 조직 팀은 저장소 권한을 담당한다. 먼저 관리 복구 경로를 확보하고, 소수 파일럿으로 인증·프로비저닝·인가를 각각 검증한다.
설명용 개념도. 인증·프로비저닝·리소스 권한은 별개입니다. setup 계정과 SCIM 운영 Owner를 구분하고 한 명의 전체 접근을 먼저 검증합니다.
4.1 관리 계정은 네 종류로 구분한다
종류
인증·범위
운영 원칙
GitHub 웹 계정 / site administrator / enterprise owner
GHES 웹의 Enterprise settings, 사용자·조직 관리
웹 관리 권한과 Management Console 접근 자격을 혼동하지 않는다. 일반 사용자에게 Owner를 주지 않는다.
Management Console root site administrator / Console 사용자
인스턴스 설정용 별도 계정·암호, 일반적으로 HTTPS 8443
root 복구 암호와 개인별 Console 접근을 보호한다. 웹 계정 암호나 GitHub.com 계정과 같지 않다.
관리 SSH의 admin
등록된 관리 공개키, TCP 122
Git SSH의 git 사용자·키와 별도이다. 관리키를 개발자 공용키로 사용하지 않는다.
built-in SCIM setup 계정 scim-admin
운영자가 GHES에서 생성하는 로컬 웹 계정, enterprise owner
Cloud의 shortcode_admin이나 GitHub 환영 메일로 받는 setup 계정이 아니다. 별도 금고·담당자·복구 시험이 필요하다.
4.2 변경 전 입력표
입력
예시 / 수집 위치
승인·검사
서비스 URL / 버전
https://github.example.com / 설치된 3.21.x
TLS 체인·DNS·시각 동기화, 버전별 문서와 일치
Entra 관리 범위
example-ghes 앱의 Application Owner 또는 필요한 Application Administrator 역할
앱 생성·설정 권한과 그룹·Conditional Access 관리 권한을 분리하고 상시 Global Administrator 사용을 피한다.
복구 담당 / 로컬 계정
scim-admin / identity+admin@example.com
SCIM 대상과 username·email이 겹치지 않도록 한다.
파일럿
pilot.reader@example.com, pilot.owner@example.com
일반 계정과 Owner 승격용 계정을 분리한다.
기존 계정 대응표
기존 login ↔ 정규화된 UPN ↔ Entra 사용자 Object ID
충돌·이메일 덮어쓰기·계정 연결 대상을 변경 전에 검토
변경 창 / 복구
백업 완료 시각, 복원 검증, Console·SSH 담당
기존 LDAP/CAS 전환과 SCIM 활성화는 별도 이관 창을 잡는다.
기존 인스턴스에서는 인증 스위치만 바꾸지 않는다
SCIM 활성화 후 기존 SAML 사용자는 SCIM으로 프로비저닝되기 전까지 로그인할 수 없다. 기존 계정은 정규화된 userName과 기존 username 비교로 연결될 수 있고 이름·이메일 및 추가 이메일이 변경될 수 있다. LDAP/CAS와 SCIM을 혼용하지 않는다. 스테이징에서 계정 매칭과 복구를 검증하고 백업·중단 공지를 승인한다.
4.3 복구 계정 → Entra 앱 → GHES SAML
built-in 복구 경로 준비
Site admin → Management Console → Authentication에서 기존 SAML 사용 시 Allow creation of accounts with built-in authentication과 Disable administrator demotion/promotion을 선택한다. 후자는 설정 중 IdP 밖에서 관리자 권한을 부여하기 위한 임시 상태다. 승인된 변경 창에서 Save settings → 구성 적용 성공을 확인한 뒤 다음 계정 생성·승격으로 진행한다. 선택만 하고 저장하지 않은 상태로 넘어가지 않는다.
scim-admin 생성과 독립 로그인
Site admin → Invite user에서 예시 username·별도 이메일을 입력하고 Generate a password reset link를 사용한다. 새 비공개 창에서 초기 암호를 설정·금고 보관한다. 기존 관리자가 Enterprise settings → People → Administrators → Add owner에서 scim-admin을 검색해 Add로 enterprise owner를 부여한다. https://github.example.com/login의 built-in 로그인 경로로 재접속한다. 이 계정을 SAML에 연결하면 username/password 로그인 선택권을 잃을 수 있으므로 IdP 파일럿으로 사용하지 않는다. 독립 Console 복구 접근과 built-in 계정의 2FA·복구 코드도 확인한다.
동일 파트너 앱 생성
Entra ID → Enterprise apps → New application → 갤러리의 GitHub Enterprise Server를 추가한다. (Legacy) 앱은 제외한다. 같은 앱으로 SAML과 SCIM을 구성한다. 기존 Legacy/SAML 앱에서 옮길 때 GHES 3.21 가이드는 새 앱 구성을 요구하므로 할당·claims·SCIM 매핑을 검토해 이관한다. 최신 Entra 문서의 기존 앱 재사용 문구만 근거로 기존 앱을 즉시 전환하지 않는다.
인증 전환 전에 로그인 대상 할당
새 앱의 Users and groups → Add user/group에서 승인된 일반 SSO 파일럿을 먼저 할당한다. 기존 사용자 이관이면 변경 창에서 인증이 필요한 승인 대상도 전환 전에 할당·역할·접근 정책을 대조한다. 앱 할당이 필요한 구성에서 미할당 상태로 GHES 인증부터 바꾸지 않는다. 이때 SCIM 자동 프로비저닝은 아직 시작하지 않으며, 사용자 생성·Owner 검증은 Phase 5에서 별도 수행한다.
Entra SAML 기본값 입력
앱 → Single sign-on → SAML → Basic SAML Configuration → Edit에서 아래 표를 입력한다. SAML certificates의 Certificate (Base64)를 받고 Set up GitHub Enterprise Server의 Login URL, Microsoft Entra Identifier를 수집한다.
GHES에서 IdP 값 연결
Site admin → Management Console → Authentication → SAML에서 Single sign-on URL에 Login URL, Issuer에 Microsoft Entra Identifier, Verification certificate에 Base64 인증서를 넣는다. Signature Method·Digest Method는 IdP 서명 구성에 맞추고 Name Identifier Format도 실제 claim과 일치시킨다. User attributes를 검토하고 두 setup 옵션을 유지한다. IdP initiated SSO는 특별한 필요와 검증 없이 켜지 않는다.
변경 저장과 파일럿 인증
Management Console의 Save settings와 적용 진행 상태를 확인한다. 설정 적용은 서비스 재시작·중단 영향을 줄 수 있으므로 완료까지 변경 창과 복구 세션을 유지한다. 별도 브라우저에서 GHES 로그인 → Entra 인증 → GHES 복귀를 시험한다. Cloud의 Test SAML configuration 버튼이 GHES에도 있다고 가정하지 않는다. Entra의 Test this application은 별도 기능이다.
필드
입력 / 매칭
주의
Identifier (Entity ID)
https://github.example.com
GHES 호스트 기준, Cloud enterprise URL 아님
Reply URL (ACS)
https://github.example.com/saml/consume
대소문자·프로토콜·경로 확인
Sign on URL (SP initiated)
https://github.example.com/sso
Microsoft 공식 패턴. 해당 GHES의 로그인 흐름으로 검증
NameID / Username
안정적으로 관리할 UPN 등 실제 앱 claim과 GHES 사용자 속성
persistent URI 형식을 무조건 강제하지 않는다. UPN 변경·정규화 충돌 계획과 신원 키를 구분한다.
값이 정확히 같아야 한다. 앱의 Application(client) ID나 service principal Object ID가 아니다.
MFA·인증서 교체·복구
MFA와 Conditional Access는 Entra SAML 로그인에서 검증한다. GHES는 Cloud OIDC/CAP 네이티브 통합이 아니며 모든 PAT 요청마다 CAP가 평가된다고 약속하지 않는다. PAT·SSH·네트워크 접근 정책은 별도로 관리한다. 인증서 교체는 새 IdP 인증서와 GHES verification certificate를 조율해 갱신한다. SAML 비활성화로 해결하지 않는다. GHES가 인증서 만료를 강제하지 않아도 IdP 키 변경 후 불일치하면 digest mismatch가 발생한다.
판정: 신뢰할 수 있는 TLS와 HTTP 응답·리디렉션을 확인한다. 이것만으로 SAML 성공이나 Entra의 SCIM 도달성을 증명하지 않는다.
파일럿 증거: 로그인 시각, 앱 이름, 익명화한 사용자 Object ID, Entra sign-in 결과, GHES login을 대응시킨다. SCIM을 아직 켜지 않았다면 JIT 결과이며 Phase 5 후 다시 시험한다. SAML assertion 원문·암호·토큰은 공유 보고서에 붙이지 않는다.
담당: 신원·GHES 운영자선행: Phase 4·IdP의 API 도달성산출물: 할당·매핑·Owner·퇴사/복귀 증거
5.1 활성화 전 조건과 자격 증명
버전과 네트워크 경계
GHES SCIM은 3.14의 public beta를 거쳐 3.17에서 GA가 되었다. 아래 절차는 3.21 기준이다. Entra 프로비저닝 서비스가 GHES의 HTTPS 443 SCIM API에 도달해야 한다. 관리자 PC에서만 접속되는 VPN은 충분하지 않다. GitHub Connect의 outbound 연결이 SCIM inbound 경로를 대신하지 않는다.
항목
입력 / 설정
검증
토큰 소유자
built-in enterprise owner scim-admin
일상 사용자·퇴사 예정 계정 토큰 금지
PAT 종류·scope
personal access token (classic), scim:enterprise만
fine-grained PAT·GitHub App 토큰은 SCIM API에서 지원하지 않는다.
만료
No expiration (3.21 setup 문서 요구)
별도 비밀 금고·회전 담당·교체 시험. 일반 개발자 PAT 정책의 예외로 승인한다.
Tenant URL
https://github.example.com/api/v3/scim/v2
api.github.com 또는 enterprises/{slug} 경로를 사용하지 않는다.
Secret Token
setup 계정의 PAT를 금고에서 입력
표·명령줄·스크린샷·프로비저닝 로그에 값 표시 금지
할당 범위
Sync only assigned users and groups
일반 파일럿 1명과 Owner 후보 1명부터 시작
전용 classic PAT 발급
scim-admin으로 로그인 → Settings → Developer settings → Personal access tokens → Tokens (classic)에서 생성한다. 위 scope와 No expiration을 선택하고 값은 즉시 금고에 저장한다. 토큰은 자동 OIDC 교환 방식이 아니다.
GHES에서 SCIM 활성화
scim-admin → Enterprise settings → Settings → Authentication security → SCIM Configuration → Enable SCIM configuration을 선택한다. 감사 로그의 business.enable_open_scim과 기존 사용자 영향 범위를 확인한다. SAML은 계속 활성 상태로 유지한다.
Entra 연결 설정
같은 GitHub Enterprise Server 앱 → Provisioning → Get started → Automatic → Admin Credentials에서 Tenant URL·Secret Token 입력 → Test Connection → 성공 후 Save. 연결 시험 성공은 사용자 생성·역할·팀 권한의 성공을 의미하지 않는다.
매핑과 범위 고정
Mappings의 사용자·그룹 매핑을 검토한다. 기본 objectId → externalId, userPrincipalName → userName, email·active·이름 값을 확인한다. roles의 실제 갤러리 expression·출력 값을 보존하고 임의 상수로 바꾸지 않는다. Scope는 할당된 사용자·그룹만으로 설정·저장하고 알림 담당 및 대량 삭제 방지 설정을 검토한다.
일반 사용자와 Owner 직접 할당
Users and groups → Add user/group에서 일반 파일럿은 일반 역할, Owner 후보는 실제 제공되는 Enterprise Owner 역할로 직접 할당한다. 역할명이 다르면 앱·버전과 roles payload를 확인한다. Owner 그룹 상속만으로 승격을 추정하지 않는다. 그룹은 Security group만 사용하며 중첩 그룹과 Microsoft 365 그룹은 지원하지 않는다.
일반 파일럿의 계정 생성·매칭 확인
Provision on demand로 정확한 일반 파일럿 한 명을 선택해 실행한다. 이는 계정 상태를 쓰는 변경 작업이며 조회가 아니다. 대상 ID·externalId·active와 Steps의 실제 action·결과를 확인한 뒤 SAML 로그인도 별도로 시험한다. 이 성공을 Owner 역할 반영이나 조직·저장소 권한의 성공으로 해석하지 않는다.
Owner 제어 전환·적용
복구 세션을 유지한 승인 창에서 Management Console의 Disable administrator demotion/promotion을 해제한다. 선택 상태이면 SCIM으로 enterprise owner를 부여할 수 없다. Save settings → 구성 적용 성공과 비상 접근 유지를 확인한 뒤 다음 정기 동기화 단계로 진행한다. 기존 SAML administrator claim에 의한 승격·강등 영향도 조사한다. 적용 실패나 복구 접근 상실 시 진행하지 않는다.
승인된 파일럿 범위의 정기 동기화·Owner 검증
Overview → Start provisioning으로 승인된 파일럿 범위 전체의 처리를 시작한다. 이미 Running이면 재시작하지 않고 다음 정기 동기화의 대상별 결과를 확인한다. Off·Stopped이면 중지 사유와 누적 변경을, Quarantine이면 원인을 먼저 해결한다. 실제 roles 출력·GHES Owner 목록·새 브라우저 SSO를 모두 확인한다. GHES의 SCIM Owner 프로비저닝 지원과 Microsoft의 on-demand 역할 프로비저닝 미지원은 다른 범위의 설명이다. Owner 후보의 on-demand는 계정 생성·매칭 확인에 한정하며 성공만으로 Owner 반영을 판정하지 않는다. 초기 전체 평가와 이후 증분 주기를 구분한다. 약 40분은 앱별 주기 확인이 필요한 일반 안내이며 전체 앱의 SLA나 개별 사용자 완료 보장이 아니다.
검증 완료 후 대상 확대
일반 사용자와 운영 Owner의 계정·SSO·역할을 각각 검증하고 setup 계정의 권한·built-in 로그인·PAT가 유지되는지 확인한 후 일상 관리를 위임하고 승인된 대상을 확대한다. built-in 생성 허용 해제는 선택 사항이며 복구 경로 영향을 검증하기 전에는 끄지 않는다. reset·재생성으로 우회하지 않는다.
문서 간 차이는 버전 기준으로 처리
최신 Microsoft provisioning 안내에는 새 UI와 /api/v3/scim 경로가 보일 수 있다. 본 절차는 GHES 3.21 전용 Entra 가이드의 /api/v3/scim/v2, Test Connection → Save를 기준으로 한다. 실제 갤러리 앱이 다르면 버전·화면·응답을 확인한 뒤 진행하며 Cloud 경로로 대체하지 않는다.
5.2 Entra Provisioning logs부터 확인한다
정확한 앱과 할당 이후 시간으로 조회
Entra ID → Enterprise apps → 해당 GitHub Enterprise Server 앱 → Provisioning logs를 연다. Provisioning 화면에서 로그로 이동하는 UI라면 같은 앱·configuration인지 확인한다. Sign-in logs는 SAML 인증 기록이지 SCIM 생성 기록이 아니다. 앱의 service principal Object ID와 사용자 source Object ID를 먼저 대조하고, 시간 범위는 앱 할당 시각 이후로 잡는다. 화면의 시간대를 기록하여 UTC로 환산한다. 표시 이름·UPN만 같은 다른 앱이나 다른 사용자 로그를 섞지 않는다. F4 로그 목록을 참고한다.
행의 Action·Status와 Steps를 함께 읽기
사용자 행을 열어 Steps의 Import user → Determine scope → Match → Perform action을 확인한다. 실패 시 Test connection 단계도 확인한다. 매칭된 대상과 Modified properties의 externalId·userName·active·실제 roles를 대조한다. 실패 화면의 속성은 전송 시도 값일 수 있으므로 실제 반영으로 취급하지 않는다. F5 Steps와 F7 결과를 참고한다.
GHES와 같은 UTC 구간으로 상관 분석
앱 Object ID, source Object ID, Action·Status, UTC 시각, Target ID, Change ID, 표시되는 job ID·request ID와 오류 본문을 승인된 기록에 남긴다. Change ID는 Entra 이벤트·Steps·변경 속성 연결 키이며 GHES request ID와 같은 값이라고 가정하지 않는다. GHES 감사 로그·SCIM 조회의 externalId와 SCIM User ID를 같은 UTC 구간에 대조한다. Token·개인정보를 제거한 뒤 공유한다.
Action / 관찰
판정
다음 확인
Create + Success
대상 생성 성공 기록
정확한 Target ID·externalId·GHES 계정을 확인한다. 또 40분을 기다려야 생성되는 상태가 아니다.
Update + Success
기존 대상의 속성·상태 업데이트
새 계정 생성 증거가 아니다. 매칭 대상과 active·변경 속성을 확인한다.
Disable / Delete
접근 제거·수명주기 변경
생성 실패와 구분한다. 실제 요청·응답과 soft/hard 영향을 확인하며 재할당을 서두르지 않는다.
Skipped
평가되었으나 작업 생략
Steps의 scope·필터·역할·변경 없음 이유를 읽는다. 생성 성공과 같지 않다.
조회 결과 0건
선택한 필터·시간 범위에서 기록 미확인
실패·성공 어느 쪽도 증명하지 않는다. 앱·Object ID·시간·할당 전파·job 상태부터 확인한다.
생성·로그인·권한의 완료 증거는 별개
SCIM Success는 조직 가입이나 저장소 권한의 성공이 아니다. Create가 확인되면 SAML 로그인·조직 팀·Private 접근으로 검증을 이어간다. GHES UI 표시까지의 고정 완료 시각을 약속하지 않는다.
조회 전용 진단: 기존 승인 토큰만 사용
다음은 Bash subshell에서만 토큰을 유지하는 GET 예시다. gh가 설치된 신뢰할 수 있는 관리자 PC에서 실행한다. 토큰 자체는 쓰기 권한도 가지므로 조회 명령이라고 읽기 전용 자격 증명으로 착각하지 않는다. 세션 녹화·환경 수집도 금지한다.
Users는 대소문자를 구분한다. gh가 GHES의 /api/v3 접두어를 처리한다. 필요한 페이지에 한해 startIndex를 실제 반환 건수만큼 증가시키고 count·totalResults·itemsPerPage를 확인한다. 빈 페이지면 중단하며 gh --paginate로 일반 REST 페이지 규칙을 무조건 적용하지 않는다. scim/v2/Groups?startIndex=1&count=10도 같은 GET 방식으로 조회한다.
5.3 오류는 대상 사용자와 응답 본문으로 분류한다
관찰
읽기 전용 확인
다음 조치
로그에 대상 없음 / Skipped
정확한 UPN·Object ID·시각, 앱 할당, Scope·필터·소스 상태
성공한 다른 사용자 로그로 판정하지 않는다. 범위를 승인 후 수정한다.
400
SCIM detail, 필수 속성·정규화 충돌·User-Agent
실제 오류 속성과 갤러리 매핑을 비교한다.
401 / 403
토큰 유효성·소유자 상태·scim:enterprise, 네트워크 중간 장비 응답
인증 실패와 권한 거부를 분리한다. 광범위 scope 추가 금지
404 / 409
정확한 endpoint·대소문자·SCIM 활성화 / 기존 username·externalId
잘못된 URL과 충돌을 본문으로 구분하고 계정을 삭제하지 않는다.
라이선스 관련 오류 문구
오류 원문·request ID·GHES 패치·설치 라이선스·사용량
3.21 문서는 새 SCIM 계정 프로비저닝에 가용 라이선스가 필요 없다고 명시한다. 실제 out-of-seats라면 별도 증거로 Support에 확인한다.
429 / 재시도 / 격리
Entra Provisioning logs의 실패 단계·재시도·quarantine 및 GHES 감사 로그
초기 대량 작업과 증분을 분리하고 제공자 재시도 정책을 따른다. 재시작·전체 재프로비저닝을 반복하지 않는다.
생성 성공, 로그인 실패
objectidentifier = externalId, NameID/username 정규화, active 상태
SAML·SCIM 매칭을 수정한다. MFA 성공만으로 GHES 로그인 성공이라고 판정하지 않는다.
쓰기는 IdP 한 곳에서만
파트너 앱 사용 시 SCIM POST·PUT·PATCH·DELETE는 IdP만 수행한다. 임의 POST로 사용자·그룹을 고치면 후속 동기화가 깨질 수 있다. 토큰·개인정보를 제거한 오류 본문과 타임라인을 Support에 전달한다. 라이선스 오류를 알려진 버그라고 단정하거나 특정 패치의 해결을 약속하지 않는다.
5.4 퇴사·복귀와 좌석 검증
경로
GHES 3.21 영향
검증
Soft deprovision
Entra 비활성화·앱 할당 해제 등으로 정지, username 해시화, 연결 신원 유지
세션·private 접근 차단, 그룹 팀 제거를 확인한다. 수동 조직 멤버십은 정지 상태로 남을 수 있다.
같은 IdP 객체 복귀
같은 externalId·SCIM User ID로 재활성화 가능
동일 UPN의 새 Entra 객체는 복구가 아니다. 재할당 후 SSO·권한·자격 증명을 재확인한다.
Soft 복귀 시 자료
PAT·SSH 키·앱 승인 등이 복원될 수 있고 private/internal fork는 24시간 내 삭제, 90일 내 복귀 시 복원
보안 사고 계정은 이전 자격 증명까지 안전하다고 가정하지 않는다. 조직 복구의 90일 조건도 확인한다.
Hard deprovision
Entra 영구 삭제 등은 복원 불가. 신원 연결·토큰·키·앱 승인·개인 저장소 삭제, 댓글 등은 유지
Entra soft-deleted 객체의 30일 후 영구 삭제를 주의한다. 동일 이름 새 계정으로 원래 계정을 합칠 수 없다.
GHES 좌석
성공적으로 인증한 active 사용자와 dormant 사용자가 기준. 조직 가입은 필수 조건이 아니다.
정지 완료와 사용량 반영을 확인한다. 팀·조직에서만 제거했다고 좌석이 해제되지는 않는다.
setup 계정 예외
scim-admin은 생성 시 소비하다 SCIM 활성화 후 면제; 다른 이름은 계속 소비
초과 사용을 숨기려고 계정을 삭제·재생성하지 않는다. 라이선스 파일·실사용·계약을 대조한다.
5.5 초기 동기화가 끝난 뒤 신규 사용자 1명 추가
Entra 디렉터리에 사용자를 만들었다는 사실만으로 GHES 앱에 할당되지는 않는다. 먼저 5.2 로그를 확인하고 다음 순서로 누락 지점을 좁힌다. 기존 계정 삭제·임의 역할 승격·전체 Restart provisioning으로 진단하지 않는다.
GHES 앱과 사용자 신원을 정확히 고정
Enterprise apps의 예시 example-ghes 앱 Overview/Properties에서 service principal Object ID를 정확히 기록한다. Application (client) ID나 App registrations 객체 ID가 아니다. Admin Credentials의 Tenant URL은 https://github.example.com/api/v3/scim/v2, 일반형은 https://HOST/api/v3/scim/v2다. GHEC EMU의 https://api.github.com/scim/v2/enterprises/SLUG와 구분한다. 사용자 Overview의 Object ID를 source identity와 정확히 비교한다. 이것이 기본 매핑의 SCIM externalId이며 앱 Object ID와 다르다. 같은 UPN의 재생성 객체는 같은 사용자가 아니다.
유효한 직접 할당 또는 그룹의 직접 멤버인지 확인
앱 → Users and groups에서 사용자 직접 할당 또는 앱에 직접 할당된 Security group의 직접 멤버인지 확인한다. SecurityEnabled=true인 그룹을 사용한다. 중첩 그룹 멤버는 지원되지 않으며, 동적 그룹은 membership rule 평가·처리 완료를 먼저 확인한다. 그룹 평가 지연은 SCIM job 지연과 별개다. 빈 그룹이 있어도 별도로 유효한 사용자 직접 할당을 취소하지 않는다.F1 앱 할당을 참고한다.
app role·매핑·Scope를 분리해 점검
앱 Owners는 Entra 앱 관리 권한이고 Users and groups의 app role 할당이 아니다. 직접 할당과 그룹 할당의 중복·서로 다른 역할, Default Access, roles 매핑 expression·실제 출력을 검토한다. Default Access 처리 여부는 앱의 역할·scoping 조건으로 확인하며 무조건 성공 또는 실패라고 단정하지 않는다. 일반 사용자의 누락을 Enterprise Owner 부여로 우회하지 않는다. Provisioning → Overview → Properties(기존 UI의 Settings)에서 Sync only assigned users and groups와 사용자 scoping filter·소스 활성 상태를 확인한다. F3 Scope·Properties를 참고한다.
정상 실행 중이면 다음 증분 대상인지 확인
Provisioning mode가 Automatic, status가 On, job이 Running이고 할당·Scope 조건을 충족하면 신규 사용자는 다음 증분 평가 대상이다. 최초 전체 sync를 다시 시작할 필요가 없다. 앱의 실제 주기·last cycle·진행 상황과 해당 사용자 로그로 확인한다. 긴급한 승인 대상 1명은 5.7 on-demand 분기를 사용한다.
5.6 Automatic 설정과 실행 상태를 구분한다
관찰
의미
안전한 다음 단계
Automatic / On / Running
자동 모드로 job 실행 중
할당·Scope를 통과한 신규 사용자는 다음 증분 평가. 초기 sync 완료 여부와 대상별 로그 확인
Off
프로비저닝 상태가 꺼짐
설정만 저장해도 실행된다고 보지 않는다. 중지 사유·전체 구성 범위를 검토하고 승인 후 활성화
Stopped
job이 중지됨
중지 주체·사유·누적 변경을 확인한다. 승인 후 Start provisioning으로 구성 범위 전체 처리를 재개
Quarantine
지속 오류 때문에 처리·재시도 빈도가 감소한 격리 상태
자격 증명·네트워크·대상 오류를 먼저 해결하고 해제·다음 cycle 확인. Off나 정상 대기와 혼동 금지
F2 Provisioning Overview에서 상태와 마지막 실행을 읽는다. Start provisioning은 선택한 1명만 보내는 버튼이 아니다. 시작·재개 시 현재 구성된 전체 Scope의 생성·변경·비활성화 영향을 승인받는다. Restart provisioning은 watermark를 초기화하여 전체 소스 재평가를 유발하므로 신규 1명 추가나 로그 0건의 기본 해결책으로 사용하지 않는다.
5.7 Provision on demand: 승인된 1명의 실제 쓰기
실행 전 변경 대상과 상태 승인
정확한 GHES 앱·Tenant URL·source Object ID·할당·필터를 재확인한다. on-demand는 미리보기나 조회가 아니며 Create·Update·Disable을 수행할 수 있다. 앱에서 할당 해제된 사용자를 선택하면 비활성화할 수도 있다. Entra에서 비활성화·삭제되어 검색되지 않는 사용자를 같은 방식으로 처리할 수 있다고 가정하지 않는다. 새 할당은 on-demand에 전파되기까지 몇 분 걸릴 수 있다.
선택한 사용자 한 명 실행
앱 → Provisioning → Provision on demand에서 예시 pilot.reader@example.com을 검색하고 source Object ID로 확인한 한 명을 선택한 뒤 승인된 경우에만 Provision을 누른다. GHES의 long-lived bearer PAT 방식은 on-demand를 위해 자동 job을 Stop할 필요가 없다. OAuth 방식인 다른 앱의 정지 요구를 GHES에 적용하지 않는다. F6 사용자 선택를 참고한다.
결과를 판정하고 다음 검증으로 이동
View details / Steps에서 scope·match·action과 Target ID를 확인한다. Microsoft의 통상 30초 미만은 on-demand job 처리 안내이지 보장 시간이나 GHES 사용자 UI·조직·권한의 SLA가 아니다. 이미 정확한 대상의 Success + Create가 있으면 계정 생성 때문에 다시 40분을 기다리지 않는다. GHES의 같은 계정·active·SSO와 필요한 팀 권한을 확인한다. 할당 전파 전 Not assigned라면 몇 분 후 범위와 로그를 재확인하며 반복 실행으로 덮지 않는다. F7 결과를 참고한다.
역할 변경을 강제하는 기능이 아니다
Microsoft는 on-demand 역할 프로비저닝 미지원을 명시한다. 따라서 Owner 후보의 계정 생성·매칭 시험과 실제 Owner 역할 검증을 분리한다. GHES가 지원하는 SCIM Owner 반영은 5.1의 관리자 제어·앱 역할·roles 매핑 조건을 충족한 정기 동기화의 실제 출력과 GHES Owner 목록으로 확인한다. on-demand 재실행·Owner 우회 부여로 해결하지 않는다.
5.8 Cloud 한정: 해시 이름·Suspended 계정의 판정
GHES 사용자명 규칙으로 전용하지 않는다
아래는 GitHub.com의 GHEC EMU에서 무작위·해시처럼 보이는 이름을 조사할 때의 조건부 판단 기준이다. GHES 사용자명이나 shortcode 규칙으로 적용하지 않는다. 실제 계정에서 <hash>_SHORTCODE와 Suspended가 함께 확인되면 SCIM deprovision 흔적일 수 있으나 이름만으로 soft/hard 또는 실행 주체를 판정할 수 없다.
Cloud에서 확인할 것
해석
경계
Enterprise settings → People → Suspended members
정지된 managed user는 GitHub Enterprise 좌석을 소비하지 않음
목록에 남아 있어도 활성 계정·소비 좌석이라는 뜻이 아니다.
Active이나 unaffiliated인 사용자
어느 조직에도 속하지 않은 unaffiliated 사용자는 Enterprise 라이선스 비소비
연결된 Visual Studio 번들 라이선스의 별도 소비는 예외로 확인한다. 조직·저장소 접근과 실제 청구 기준을 대조한다.
Soft deprovision + 같은 Entra Object ID
externalId·SCIM User ID 연결이 남아 동일 소스 객체로 복구 가능
동일 UPN의 새 객체는 대체 불가. 원인 확인과 복귀 승인 후 IdP에서 처리하고 실제 접근을 재검증한다.
Hard deprovision
연결 신원이 제거되어 기존 계정 복원 불가
새 계정과 기존 기록을 합칠 수 없다. 진단 목적으로 삭제하거나 재생성하지 않는다.
목록 존재 ≠ 조직 멤버십 ≠ consumed Cloud licenses ≠ 설치된 GHES capacity다. Cloud 감사 로그의 user.rename·user.suspend·external_identity.deprovision을 같은 UTC 구간의 Cloud용 Entra Enterprise app Provisioning logs와 대조한다. GHES 앱 로그를 대신 사용하지 않는다. 앱 Object ID·Tenant URL·source Object ID·실제 요청 종류로 원천을 확인하기 전에는 계정 삭제·임의 이름 변경·앱 재할당을 하지 않는다. soft 복구 가능성이 곧 복귀 승인은 아니다.
담당: 조직 Owner·보안·개발 리드선행: 파일럿 SCIM 성공산출물: 조직 팀 매핑·샘플 저장소·권한 시험
6.1 조직·팀·저장소 권한 모델
대상 예시
설정
최소 권한 확인
example-org
Organization Owner 최소 인원, Settings → Member privileges → Base permissions: None
enterprise owner와 조직 Owner를 별도 관리한다. 일반 사용자로 private 접근을 시험한다.
example-developers
Entra Security group ↔ 조직 팀, 저장소 Write
앱 할당만으로 저장소 권한이 생기는 것은 아니다.
example-reviewers
표시 가능한 조직 팀, 저장소 Write, CODEOWNERS
검토자 팀도 명시적인 Write가 필요하다.
example-private-project
Private
팀 소속자만 업무 접근. 조직 Owner 등 관리 권한 예외를 별도 기록
example-shared-library
Internal
일반 enterprise member의 공유 영역. 특정 프로젝트 격리 용도가 아니다.
None은 Internal을 숨기지 않는다
Base permissions=None은 조직의 기본 권한을 줄이는 설정이다. 다른 조직 소속을 포함한 일반 enterprise member의 Internal 읽기 권한을 차단하지 않는다. 어떤 조직에도 속하지 않은 사용자·outside collaborator는 구분한다. 민감 프로젝트는 Private로 만들고 실제 비관리자 두 명으로 허용·거부를 시험한다.
사용자 → 그룹 → 팀 연결
Phase 5에서 사용자 생성, Security group 프로비저닝, 그룹 멤버 반영을 순서대로 확인한다. Enterprise settings → Identity provider에서 그룹을 읽어 확인한다. 조직 → Teams → New team에서 이름을 입력하고 Identity Provider Groups → Select Groups로 연결 후 Create team 한다. 사용자가 연결된 팀에 들어가면 조직 멤버가 자동 추가된다.
기존 팀 전환은 별도 승인
기존 팀 첫 연결 전 수동 추가 멤버를 제거해야 한다. 팀 이름·권한을 복제한 파일럿 팀으로 먼저 시험하고, 기존 멤버·저장소 권한을 기록한 후 영향 승인 창에서 전환한다. 사용자 계정 삭제가 아니다. 연결된 팀은 부모·자식 팀으로 중첩할 수 없고 팀 maintainer 지정에도 제약이 있다. 연결 해제 시 다른 가입 경로가 없으면 조직에서도 제거될 수 있다.
저장소 접근 부여
조직에 Private 샘플 저장소를 만들고 저장소 Settings → Collaborators and teams에서 조직 팀별 Read·Write·Maintain·Admin을 업무에 맞게 부여한다. IdP는 팀 멤버십을, GHES는 팀의 저장소 역할을 관리한다. 이 절차는 조직 팀 기준이다. Cloud Enterprise Teams의 UI·권한 모델을 GHES 3.21에 그대로 적용하지 않는다.
보호 규칙을 실제로 강제
저장소의 main 대상 ruleset 또는 branch protection에서 PR 승인, 필요한 status checks, Require review from Code Owners와 우회 권한을 명시한다. CI가 실제 보고하는 check 이름을 선택한다. CODEOWNERS 파일만 추가하면 리뷰 요청은 생겨도 병합 차단이 자동 보장되지는 않는다. 미승인·실패 check PR로 병합 거부를 검증한다.
앱·외부 인력·토큰 정책
조직 소유권 변경·외부 협업자 초대·저장소 생성 권한을 제한한다. 외부 인력은 회사의 IdP 객체·계약 종료·외부 식별자 정책에 따라 온보딩하고 GHES outside collaborator 동작을 확인한다. Cloud EMU의 일괄 외부 협업 제한을 전제하지 않는다. 일반 PAT 만료·최소 scope·SSO 연계 요구·앱 승인을 GHES 버전별로 확인한다. 내부 자동화는 지원되는 작업에 GitHub App의 선택 저장소·최소 permissions를 우선하고, SCIM classic PAT 예외와 분리한다.
6.2 개발자 온보딩 템플릿
README, 기여 절차, PR 템플릿, CI와 .github/CODEOWNERS를 샘플 저장소에 둔다. 아래 패턴은 base branch의 CODEOWNERS 내용 예시이며 팀은 visible·Write 조건을 만족해야 한다.
판정: clone은 로컬 파일을 생성한다. HTTPS 인증은 승인된 credential helper/보안 프롬프트를 사용하며 PAT를 URL에 넣지 않는다.
git config user.*는 커밋 표시 정보이지 로그인·SSO 설정이 아니다. Git용 SSH 공개키는 개인 GitHub 계정에 등록하며 관리 Console의 SSH 122 키와 분리한다. Cloud의 토큰 SSO 승인 UI가 동일하다고 가정하지 말고 GHES 문서·현재 사용자 설정을 확인한다.
조회 · 승인된 일반 파일럿 사용자 PC · bash
git ls-remote https://github.example.com/example-org/example-private-project.git HEAD
판정: 허용 사용자는 HEAD를 읽고, 미허용 사용자는 읽지 못한다. 관리자 토큰이나 공유 credential로 대신 시험하지 않는다.
6.3 권한 수용 시험
시험 주체
동작
완료 증거
팀 멤버 일반 계정
본인 SAML 로그인 → Private 웹 열람 → 본인 Git 인증으로 읽기
세 경로 각각의 실제 계정·성공 시각
다른 조직의 일반 계정
Private 거부 / Internal 읽기
기본 None과 Internal 가시성의 차이를 입증
검토 없는 작성자
미승인 PR·실패 check의 병합 시도
규칙이 차단하며 관리자 우회가 시험에 섞이지 않음
그룹에서 제거된 파일럿
동기화 후 팀·저장소 접근 확인
직접 collaborator·다른 팀·조직 기본권한 잔존 조사
복귀 파일럿
재할당 후 팀·조직·저장소 권한 확인
SCIM active만 보고 권한 복구를 단정하지 않음
감사 로그와 분기별 Owner·앱 설치·토큰·SSH 키 검토 책임자를 정한다. GHES에서 제공되는 보안 정책과 라이선스를 확인하며 Cloud 전용 AI Controls가 보편적으로 존재한다고 쓰지 않는다. AI 기능은 Copilot 범위에서 별도로 검토한다.
프록시·DNS·TLS 신뢰, Cloud IP allow list에 GHES 출구 IP 허용. SCIM 수신 경로와 분리
개인정보 승인
user ID·email 및 기능별 추가 데이터
전송 목적·수신 Cloud·보존·접근권한 검토
PAYG와 Connect 자격의 문서 차이
사용량 기반 과금 문서는 Cloud/Server 병용과 GitHub Connect를 설명하지만, 3.21 Connect 활성화 문서는 invoiced 요건과 trial·credit-card 제외를 별도로 명시한다. 모든 PAYG 계정이 가능하거나 불가능하다고 단정하지 말고 실제 enterprise의 자격을 GitHub Sales/Support에 확인한 뒤 연결한다.
브라우저 연결
GHES와 GitHub.com에 각각 로그인한다. GHES 프로필 → Enterprise settings → GitHub Connect → Enable GitHub Connect. Cloud 로그인·승인 흐름에서 대상 enterprise를 선택하고 해당 항목의 Connect를 누른다. Choose enterprise 화면의 대상 이름과 약관을 검토한다. Management Console에서 SCIM 토큰을 붙이는 절차가 아니다.
원하는 기능만 선택
GHES GitHub Connect 화면의 License sync → Enable을 별도로 선택한다. 필요할 때만 GitHub.com actions, Dependabot alerts, unified search/contributions 등 현재 버전에서 지원하는 기능을 승인한다. Actions 실행·runner와 보안 기능의 GHAS/Code Security/Secret Protection 자격은 별도이다. Connect 하나로 전부 활성화되지 않는다.
첫 동기화와 증거 수집
자동 사용자 라이선스 동기화는 GHES 사용량을 GHEC에 보내는 주 단위 작업이며 키 갱신이 아니다. 즉시 외부 데이터 전송을 승인했다면 GHES Enterprise settings → Settings → License(또는 Licensing) → License sync → Sync now를 사용한다. 이는 단순 조회가 아니라 데이터 전송이다. Cloud Billing and licensing → Licensing에서 해당 Server source·마지막 동기화 시각·상태를 읽어 확인한다.
불일치 분석
GHES active·suspended 사용자, GHES 기본 이메일, Cloud 신원·검증 이메일, 중복 제거 결과를 대조한다. Cloud 사용량 화면의 GitHub Connect server usage synced / never synced / Server usage uploaded 구분과 시각을 남긴다. 네트워크 실패·잘못된 연결 대상·이메일 불일치를 구분하고 무작정 재연결하지 않는다.
7.2 전송·중복 제거·비용은 별도 판정
구분
실제 의미
주의
데이터 흐름
GHES → Cloud로 사용자 ID·이메일 주소, 보안 제품 라이선스 소비 여부; 연결 메타데이터도 전송
익명 인원수만 보내는 기능이 아니다. 상세 Connect 데이터 표를 개인정보 검토 기준으로 삼는다.
전송하지 않는 항목
Connect 자체가 repository·issue·pull request를 Cloud로 자동 전송하지 않음
추가 Actions·앱·외부 서비스의 데이터 흐름까지 없다는 뜻은 아니다.
중복 제거
GHES 기본 이메일을 Cloud SAML/SCIM 신원 속성에 먼저 매칭, 미일치 시 검증된 Cloud 이메일 비교
username 동일만으로 보장하지 않는다. 이메일 변경·별칭·여러 Server source를 확인한다.
라이선스 수치
Billing and licensing → Licensing의 consumed Cloud licenses와 병용 총량을 구분
metered Server 라이선스 생성에는 Cloud 소비 수를 사용한다. People → Members의 결합 Total consumed를 그대로 넣지 않는다.
판정: TLS·HTTP 도달성의 일부 증거만 된다. 관리자 노트북의 성공만으로 appliance 연결·계약 자격·라이선스 sync 성공을 주장하지 않는다.
오프라인 대안과 Copilot 경계
자동 연결이 불가능하면 공식 절차의 GHES License → Export license usage와 Cloud Licensing → Add server usage를 승인된 별도 수동 전송으로 검토한다. 파일에도 사용자 데이터가 있으므로 일반 공유 폴더에 두지 않는다. Connect는 GHES 호스팅 저장소에서 Copilot cloud agent의 issue/PR 작업을 가능하게 만드는 스위치가 아니다. Cloud agent와 로컬 IDE 지원을 구분하고 Copilot 기능·호스팅 조건을 확인한다.
7.3 세 가지 동기화 시계와 라이선스 파일 적용을 구분한다
시계
주기·시간의 의미
완료 증거 / 잘못된 해석
① Entra 자동 프로비저닝: initial / incremental
처음에는 전체 구성 범위 평가, 이후 변경분 증분. 약 40분은 일반 안내로 앱별 문서·현재 job 주기를 확인
대상별 Action·Status·Target ID·GHES 상태로 판정한다. 모든 앱의 고정 주기나 사용자별 SLA가 아니다.
② Entra Provision on demand
승인된 사용자 한 명의 실제 쓰기. 통상 30초 미만이라는 Microsoft 안내
Steps·실제 action·대상 상태 확인. 새 할당 전파 수 분과 UI·조직 권한 반영은 별도이며 완료 시간을 보장하지 않는다.
③ GitHub Connect license usage sync
GHES → GHEC 사용량 자동 전송은 매주. 승인 후 Sync now로 별도 실행 가능
Cloud의 해당 Server source·마지막 성공 시각·상태 확인. SCIM 사용자 생성도 GHES 키 자동 갱신도 아니다.
별도 파일 적용 시간: 새 GHES 라이선스 키를 승인 후 Upload하면 백그라운드로 적용되며 화면 반영에 몇 분 걸릴 수 있다. 이는 위 세 동기화 주기와 다르다. 키 만료일도 별도로 추적한다. metered 방식의 생성 키는 문서상 1년 유효하며 현재 파일의 실제 만료일·갱신 알림을 확인한다. weekly sync나 사용자 증분이 만료를 연장하지 않는다.
7.4 주간 전송의 성공은 토글이 아니라 상태로 확인한다
License sync의 Enable은 설정 증거일 뿐 전송 성공 증거가 아니다. GHES Enterprise settings → Settings → License / Licensing → License sync → Sync now는 사용자 ID·이메일 등 사용량 데이터의 외부 전송이므로 목적·수신 enterprise·전송 범위 승인 후 실행한다. 실행 전후 Cloud Billing and licensing → Licensing의 해당 Server source, last sync, 성공·실패 또는 never synced 상태를 기록한다. 수동 실행 역시 GHES capacity를 늘리거나 라이선스 키를 재발급하지 않는다.
정각·첫 즉시 실행·사용자 cron을 약속하지 않는다
license sync 문서는 주간 자동 전송과 수동 Sync now를 설명하지만 고정 분 단위 실행 시각, Enable 직후 첫 실행의 즉시 완료, 사용자가 지정하는 cron을 보장하지 않는다. About GitHub Connect의 ‘활성화한 요일·대략적 시각부터 매주’ 문구는 연결 메타데이터 동기화 설명이다. 이를 license usage job의 신뢰할 수 있는 실행·완료 SLA로 전용하지 않는다.
7.5 신규 사용자와 키 재발급은 조건부로 연결한다
설치 capacity·만료·소비량을 먼저 읽기
신규 사용자 한 명마다 무조건 키를 재생성하지 않는다. 현재 GHES License 화면의 설치 좌석·사용량·만료, Cloud의 consumed Cloud licenses, 계약·과금 방식을 각각 대조한다. metered Server 키는 생성 시점의 consumed Cloud licenses를 기준으로 capacity가 정해지므로 Cloud 계정 목록 수나 결합 Total consumed를 대신 넣지 않는다.
부족·갱신 필요가 확인된 경우에만 파일 변경 승인
현재 설치 capacity가 필요한 사용량에 부족하거나 갱신이 필요한 경우, 자격·계약·다운로드 가능한 새 capacity를 확인한 뒤 승인받아 새 키 생성·다운로드·GHES 업로드를 수행한다. Cloud Licensing의 Generate new license 안내는 metered Cloud 소비 증가 또는 만료 30일 이내 등의 조건으로 나타난다. 업로드 뒤 백그라운드 반영과 실제 좌석·만료일을 다시 확인한다. Cloud에서 먼저 모든 사람을 만들어야만 GHES SCIM 생성이 된다는 보편적 순서로 바꾸지 않는다.
문서상 가용 좌석 불필요와 실제 오류의 차이는 Support 확인
2026-09-21 확인한 GHES 3.21 SCIM REST how-to는 ‘enterprise doesn’t require an available license to provision a new user account’라고 명시한다. 실제 요청에서 out-of-seats 오류가 발생하면 HTTP 상태와 응답 본문을 로그로 확인한다. 문서와 관측의 차이를 지우거나 확인된 제품 버그로 단정하지 않는다. 정확한 3.21 패치·endpoint·UTC·request ID·오류 본문·설치 라이선스 capacity/만료·실사용량·과금 방식으로 Support에 해당 요청의 제한 조건과 문서 적용 범위를 질문한다. SCIM 계정 생성, 로그인 시 좌석 소비, Cloud 소비, 설치 키의 수용량을 구분하며 계정 삭제·역할 승격·전체 재시작으로 우회하지 않는다.
7.6 운영자 인수인계 체크리스트
완료·실패·미확인 항목을 구분하고 각 증거 위치, 담당자, 승인된 다음 조치를 인계한다. 요약 상태만으로 계정·권한·연결의 종단 간 검증을 대신하지 않는다.
점검 항목
인계할 증거
완료·중단 기준
앱 할당·프로비저닝
정확한 앱·사용자 ID, 할당 이후 UTC 구간, job 상태와 대상별 Steps
로그 0건은 서버 미호출이나 실패의 증명이 아니다. 범위·보존·필터를 확인하며 전체 sync를 재시작하지 않는다.
계정·로그인·역할
Target ID·externalId·active, 일반 계정 SSO, 정기 동기화 roles와 실제 GHES Owner
on-demand Success만으로 역할을 판정하지 않는다. 복구 계정·PAT 유지와 조직·저장소 권한을 별도 검증한다.
Connect 사용량 전송
해당 Server source·마지막 성공 시각·상태·수신 Cloud와 이메일 매칭
주간 license sync는 사용량 전송이지 계정 생성이나 설치 키·quota 갱신이 아니다.
임시 광범위 outbound
승인 범위·기한·담당자, 최소 목적지·프록시 재시험·원복 계획
임시 성공은 운영 완료가 아니다. SCIM inbound와 구분하고 검증 후 임시 규칙을 회수한다.
설치 키와 사용량
설치 capacity·잔여 좌석·만료일·Cloud 소비·계약, 변경 시 전후 값
여유가 충분하면 사용자마다 재발급하지 않는다. 증설·갱신 필요가 확인된 경우만 승인 후 파일을 변경한다.
담당: GHES·Azure·Entra·보안 담당선행: TLS·DNS·라이선스·용량·백업산출물: 인증 선택표·경로표·쓰기 테스트·구성 적용 기록
범위·실행 원칙 · 2026-09-19 검토
기준은 GHES 3.21이다. 신규 3.22는 아래 차이 표시와 해당 버전 문서를 함께 확인한다. 이 문서는 공개 자료로 작성한 일반 절차이며 실제 환경에 접속하거나 검증한 결과가 아니다. github.example.com, storageexample, testorg는 예시다. 조회도 사전 권한이 필요하며, 변경·테스트·저장·비용 발생은 승인된 작업창에서만 수행한다. 고객 정보, 토큰, 키, 연결 문자열을 문서·채팅·로그에 넣지 않는다.
8.1 구성과 용량을 먼저 결정한다
설명용 개념도. Actions 서비스·자체 호스팅 Runner·외부 Storage의 역할과 인증 경계. OIDC와 credential 방식을 혼합해 진단하지 않습니다.
대상
설계·입력
확인 기준
GHES appliance
Actions 제어 서비스. runner나 Node.js 빌드 도구를 appliance에 설치하지 않는다.
GHES에서는 GitHub-hosted runner를 사용할 수 없다. 별도 self-hosted runner가 필요하다.
CPU·메모리
Actions 최소 8 vCPU / 64 GB. Azure 설치 문서의 사용자 규모별 기본 자원에서 CPU·메모리 각각 최소 25% 추가도 반영한다.
두 조건을 모두 충족하는 VM을 선정한다. 연결 runner 수는 작업 길이·artifact·저장소 부하에 따라 달라지며 보장 수치가 아니다. pilot의 queue·CPU·메모리·I/O로 조정한다.
외부 객체 저장소
Azure Blob 또는 Amazon S3 등 공식 지원 공급자 중 하나. 이 절차는 Azure Blob 기준.
로그·cache·artifact는 외부 저장소, workflow 소스·기타 메타데이터는 GHES에 남는다. 외부 저장소로 root/data 디스크 용량을 대체할 수 없다.
Azure 계정 종류
신규 권장 예: Standard / StorageV2(GPv2). 지원 대안: Premium / BlockBlobStorage.
Standard GPv1/GPv2와 Premium BlockBlobStorage를 구분한다. Premium general-purpose 계정은 Actions에 미지원이다. SKU만 보지 말고 kind도 확인한다.
운영 승인
저장소·네트워크·Entra·GHES 담당과 비밀 관리자 지정. 변경 전 백업·복구 및 키 회전 계획.
기존 account의 firewall, Private Endpoint(PE), DNS, 보존 정책을 읽고 공유 서비스 영향부터 확인한다.
8.2 인증 분기와 UI 입력값
모드·화면
입력
주의
Credentials-based
비밀 관리자가 승인된 경로로 전달한 Azure account connection string을 Management Console의 비밀 입력란에만 입력.
Client ID와 Tenant ID만으로 인증되지 않는다. account key 기반 연결 문자열에는 Shared Key 허용이 필요하다. 키 조회 명령·인라인 키·디버그 출력은 사용하지 않는다.
OIDC: App registrations → New registration
저장소 인증용 Entra 앱을 생성하고 Application (client) ID / Directory (tenant) ID 기록.
기존 SAML/SCIM 앱 재사용을 기본값으로 삼지 않는다. 앱 소유 tenant, storage subscription tenant, 청구/Billing tenant가 같은지 별도로 확인한다.
OIDC는 Entra ID tenant ID / client ID / Azure storage account name / Azure blob endpoint suffix 네 필드가 필요하다.
OIDC: account / suffix
storageexample / core.windows.net
suffix에 https://, account 이름, .blob 또는 전체 URL을 넣지 않는다. 국가별 Azure는 Storage → Endpoints의 실제 suffix를 사용한다.
OIDC의 공개 경로는 필수지만 GHES 전체 공개는 아니다
클라우드 인증 서비스가 아래 두 경로의 public DNS와 신뢰 가능한 TLS에 접근할 수 있어야 한다. 내부 PC에서 열리는 것만으로 충분하지 않다. 공개 허용은 보안 검토한 metadata/JWKS 경로로 제한하고 다른 경로를 무조건 개방하지 않는다. 이 조건이 금지되면 OIDC 구성을 중단하고 정책상 승인된 Shared Key/연결 문자열 대안을 검토한다. Shared Key 금지 정책을 임의로 해제하지 않는다.
판정: 두 URL의 외부 인증 서비스 접근·TLS 검증 가능 여부를 승인 기록으로 남긴다.
8.3 비밀을 출력하지 않는 사전 조회
아래 Azure CLI는 이미 인증된 승인 세션에서 실행한다. 계정 전환이 필요하면 현재 출력을 확인한 뒤 별도 승인으로 로그인한다. APP_TENANT_ID, STORAGE_TENANT_ID, SUBSCRIPTION_ID, APP_CLIENT_ID, STORAGE_SP_OBJECT_ID는 담당자가 확인한 값이며 비밀번호가 아니다. 연결 문자열은 이 변수 목록에 포함하지 않는다.
조회 · 승인된 관리자 PC · bash
az account show --query "{subscription:id,tenant:tenantId,state:state}" -o json
az storage account show --resource-group rg-ghes-storage --name storageexample --query "{id:id,kind:kind,sku:sku.name,location:location,httpsOnly:enableHttpsTrafficOnly,minTLS:minimumTlsVersion,sharedKey:allowSharedKeyAccess,publicNetwork:publicNetworkAccess,firewallDefault:networkRuleSet.defaultAction,blobEndpoint:primaryEndpoints.blob}" -o json
판정: 대상 subscription/tenant와 kind/SKU, Shared Key 및 네트워크 정책 확인. sharedKey=null은 false와 같다고 해석하지 않고 유효 기본 정책을 확인한다. 이 조회는 Blob 쓰기 권한 증명이 아니다.
로컬 세션·파일 · 승인된 관리자 PC · bash
az login --tenant "$APP_TENANT_ID" --allow-no-subscriptions --output none
판정: OIDC 앱 소유 tenant 조사에 한해 승인 후 로그인. 로컬 인증 캐시가 바뀐다. 범용 tenant 탐색을 하지 않는다.
OIDC를 선택한 경우에만 다음 앱/Federated credential 조회를 수행한다. 앱 소유 tenant에서 읽기 권한이 있어야 한다. Credentials-based의 403을 고친다고 무관한 앱에 RBAC를 추가하지 않는다.
조회 · 승인된 관리자 PC · bash
az ad app show --id "$APP_CLIENT_ID" --query "{clientId:appId,appObjectId:id,displayName:displayName}" -o json
APP_OBJECT_ID=$(az ad app show --id "$APP_CLIENT_ID" --query id -o tsv) &&
test -n "$APP_OBJECT_ID" &&
az ad app federated-credential list --id "$APP_OBJECT_ID" --query "[].{name:name,issuer:issuer,subject:subject,audiences:audiences}" -o json
판정: issuer/subject/audience를 대조한다. 앱 등록 object ID를 명시적으로 사용한다. 403/권한 거부는 항목 없음이 아니다. 앱 소유 tenant가 아니면 여기서 멈춘다.
로컬 세션·파일 · 승인된 관리자 PC · bash
az login --tenant "$STORAGE_TENANT_ID" --output none
az account set --subscription "$SUBSCRIPTION_ID"
판정: 저장소 tenant/구독 조회용 별도 승인. 앞의 앱 소유 tenant 세션과 혼동하지 않는다.
조회 · 승인된 관리자 PC · bash
az ad sp show --id "$APP_CLIENT_ID" --query "{clientId:appId,spObjectId:id,appOwnerTenant:appOwnerOrganizationId}" -o json
STORAGE_SCOPE=$(az storage account show -g rg-ghes-storage -n storageexample --query id -o tsv) &&
test -n "$STORAGE_SCOPE" &&
az role assignment list --scope "$STORAGE_SCOPE" --assignee-object-id "$STORAGE_SP_OBJECT_ID" --include-inherited --fill-principal-name false --query "[].{role:roleDefinitionName,scope:scope,principalId:principalId}" -o json
GHES → Blob, runner → GHES hostname/API 및 필요한 Blob 경로, Entra → OIDC metadata/JWKS를 별도 항목으로 검토한다. Entra SCIM → GHES의 inbound 성공은 Blob outbound 성공 증거가 아니다. PE의 private DNS zone·VNet 연결·실제 서비스의 DNS 응답·출구 NAT/firewall을 확인한다. HTTP proxy 제외 목록의 .localhost, 127.0.0.1, ::1과 내부 저장소 경로도 공식 문서에 맞춘다.
연결만 확인한다
승인된 GHES 관리 셸에서 아래 무인증 curl을 실행한다. PC의 같은 명령은 보조 자료일 뿐이다. 인증 없는 400/403은 HTTP 도달 가능성을 보여도 실제 GHES 서비스의 proxy 환경이나 읽기·쓰기 권한을 증명하지 않는다. TLS 오류를 -k로 우회하지 않는다.
Test storage settings — 변경 승인 필요
Management Console에서 승인된 테스트 범위에 대해 실행한다. create/upload/delete를 포함하는 쓰기 검증으로 취급한다. 읽기 전용 점검으로 분류하지 않는다. 테스트 시각과 성공/오류 코드만 기록하고 잔여 테스트 객체 및 정리 결과를 저장소 담당자가 확인한다.
Save settings — 서비스 재시작 가능
테스트 통과 후 공지된 작업창에서 저장한다. configuration run 종료까지 기다리고 진행 화면·구성 로그의 성공/실패 단계·시각을 기록한다. 진행 중 재저장하거나 ghe-config-apply를 중복 실행하지 않는다. 실패 시 원인 분석과 승인된 복구 절차로 돌아가며 저장소를 임의 교체하지 않는다.
판정: curl은 인증/권한 검증이 아니다. ghe-config는 이 단일 비밀 아닌 키만 조회한다. 전체 설정 목록, secrets 값, connection string, Authorization header는 출력하지 않는다.
구성 진행은 Management Console의 진행/로그 화면을 우선 사용한다. 추가 로그는 해당 버전의 관리 유틸리티 도움말과 공식 지원 절차로 범위를 좁혀 확인한다. 원본 전체 로그를 공유하지 말고 configuration run 단계·UTC 시각·마스킹된 오류만 전달한다.
8.5 403을 인증·권한·네트워크로 나누어 조사한다
오류/현상
먼저 볼 것
승인 후 조치
AuthenticationFailed
선택한 인증 모드, account 불일치, 키 회전·문자열 손상·시간 오차. OIDC이면 교환 오류와 issuer/subject/audience/TLS.
비밀 관리자가 일치 여부만 확인한다. 키를 로그에 복사하거나 --debug를 켜지 않는다. SAS를 임의 대체 인증으로 넣지 않는다.
KeyBasedAuthenticationNotPermitted
Credentials-based 요청인데 Shared Key가 정책상 금지되었는가?
Actions는 공개 metadata/JWKS 조건이 충족되면 OIDC 검토. Shared Key 변경은 보안 승인 필요. Client/Tenant 입력만 추가해 해결하려 하지 않는다.
AuthorizationPermissionMismatch
실제 OAuth SP·Data Owner·scope·전파 시간·필요한 write/delete 동작.
OIDC 선택 확인 후 정확한 SP에 공식 역할 적용. ARM Reader/Contributor와 Blob 데이터 역할은 다르다. 광범위 Owner로 우회하지 않는다.
StorageBlobLogs는 Blob 진단 설정이 Log Analytics로 수집 중일 때만 조회 가능하다. 진단 설정 활성화는 별도 변경·비용 승인이다. 아래는 실패 재현 직후 15분 범위 예시이며, URI/SAS/인증 hash는 출력하지 않는다. 필요한 식별자는 내부 제한 기록에서만 상관 분석한다.
조회 · 승인된 Log Analytics workspace · kusto
StorageBlobLogs
| where TimeGenerated > ago(15m)
| where AccountName == "storageexample"
| project TimeGenerated, OperationName, StatusCode, StatusText,
AuthenticationType = column_ifexists("AuthenticationType", ""),
CorrelationId = column_ifexists("CorrelationId", ""),
ClientRequestId = column_ifexists("ClientRequestId", "")
| order by TimeGenerated desc
| take 50
판정: 요청 시각·동작·인증 유형·상태로 분류한다. 존재를 가정한 RequestId 열을 사용하지 않는다. 결과 0건을 정상 판정으로 쓰지 않는다.
신규 3.22 차이 확인
공식 3.21/3.22 Azure Actions 문서 모두 OIDC와 connection string 두 방식을 안내한다. 3.22라는 이유로 필드·저장소 종류·공개 metadata 요구가 사라지지 않는다. 설치할 patch의 릴리스 노트, runner와 action runtime 호환성을 다시 승인한다.
VM의 전용 작업 디렉터리에서 UI 명령을 순서대로 복사한다. 일반 OS 계정으로 압축 해제·config를 실행한다. 등록 URL은 조직 URL이어야 한다. UI의 등록 token은 1시간 만료되는 비밀이며 PAT와 다르다. token을 문서에 전사하지 않고 로그·셸 추적을 끈 승인 세션에서 사용한다. 만료되면 UI에서 다시 발급한다.
그룹·레이블을 확인한다
등록 단계에서 pilot-linux 그룹과 ghes-pilot 레이블을 선택한다. 기본 self-hosted/Linux/X64 레이블도 확인한다. UI에서 Online/Idle을 확인한다. production secret, Docker socket, 운영망 접근을 시험 runner에 제공하지 않는다.
서비스로 전환한다 — OS별 승인
대화형 run 프로세스를 먼저 종료한다. 아래 Linux systemd 서비스 설치만 승인된 관리자 권한으로 실행한다. macOS는 공식 launchd 절차, Windows는 config의 서비스 설치 선택과 해당 서비스 계정을 따른다. 전체 workflow를 sudo/root로 실행하지 않는다.
승인 후 변경 · 등록을 마친 Linux systemd runner 설치 디렉터리 · bash
판정: runneruser는 준비한 비특권 계정으로 바꾼다. 서비스가 시작되고 UI Online/Idle이어야 한다.
조회 · 승인된 Linux runner 설치 디렉터리 · bash
sudo ./svc.sh status
판정: 상태만 조회한다. 프로세스 실행과 GHES 연결 성공을 별도로 확인한다.
ephemeral은 자동 확장 제품명이 아니다
3.21 runner 문서는 --ephemeral 등록을 지원한다. 실제 번들 runner의 옵션·버전 지원을 먼저 확인하고, 1 job 후 등록 해제와 VM/디스크 정리·외부 진단 로그 보존까지 별도 구현한다. Azure VMSS에 runner를 올리는 것만으로 자동 확장·보안 격리가 완성되지 않는다. pilot은 먼저 한 대로 검증한다.
9.2 읽기 조회와 ref 검증
이미 github.example.com에 인증된 gh를 사용한다. 조직 runner 목록의 classic PAT 기준 요구 scope는 admin:org이며 호출자는 조직 관리 권한이 있어야 한다. 여기서는 조회만 하지만 자격 증명 자체가 읽기 전용이라는 뜻은 아니다. 403은 runner 0대가 아니며 권한 담당자에게 전달한다. 토큰을 명령에 넣지 않는다.
조회 · 승인된 관리자 PC · bash
gh api --hostname github.example.com --paginate orgs/testorg/actions/runners --jq ".runners[] | {name,status,busy,labels:[.labels[].name]}"
gh api --hostname github.example.com repos/actions/checkout/git/ref/tags/v4 --jq .object.sha
gh api --hostname github.example.com repos/actions/upload-artifact/git/ref/tags/v3-node20 --jq .object.sha
gh api --hostname github.example.com repos/actions/download-artifact/git/ref/tags/v3-node20 --jq .object.sha
판정: 로컬 bundled/동기화 저장소 기준 ref 확인이다. 404이면 action 공급 경로·권한·tag/branch 유형을 조사한다. 원격 자동 접근 경로는 별도로 확인한다. 운영 적용 시 승인된 commit SHA 고정을 검토한다.
9.3 최소 workflow로 실행과 artifact 왕복을 증명한다
GHES artifact 버전
upload/download-artifact v4 이상은 현재 GHES에서 지원되지 않는다. 아래 v3-node20 두 ref의 action.yml에서 Node 20을 확인했다. upload-artifact의 현재 upstream 안내는 v3.2.2-node20도 제시하므로, 설치 시 최신 GHES 호환 보안 수정·승인 SHA를 확인한다. GitHub.com의 v3 폐기 공지만 보고 GHES를 v4로 교체하지 않는다.
승인된 private testorg/ghes-smoke 저장소 기본 branch에 .github/workflows/ghes-smoke.yml로 저장한다. 파일 생성·commit·push 또는 Contents API PUT은 모두 변경이다. 샘플은 Linux bash 전용이며 synthetic payload만 사용한다. 세션·운영 파일을 artifact로 올리지 않는다.
두 버전의 Azure Packages 공식 절차는 사전 생성한 container와 account connection string이다. SAS token/SAS URL은 연결 문자열로 지원되지 않으며, Actions의 OIDC 지원을 Packages에 그대로 적용하면 안 된다. Shared Key가 금지된 환경이면 정책 예외 또는 다른 공식 지원 구성을 승인받기 전 진행하지 않는다.
판정: 무인증 401 challenge는 registry 도달성 증거이며 push 권한 증명이 아니다. TLS 오류나 404는 endpoint/기능 설정부터 확인한다. -k를 사용하지 않는다.
10.3 인증 → 작은 private image push/pull
일반 GHES 사용자명 USER를 실제 pilot 로그인으로 바꾼다. SCIM 식별자나 임의의 '%' 접미사를 만들지 않는다. 개인 인증은 해당 GHES에서 발급한 PAT classic의 read:packages / write:packages와 실제 package·연결 저장소 권한이 필요하다. fine-grained PAT로 대체된다고 가정하지 않는다. 삭제 scope는 필요한 관리자에게만 부여한다. repo scope는 registry·private repository 요구를 확인해 최소화하며 무조건 선택하지 않는다.
아래는 승인 후 변경하는 선택적 synthetic 시험이다. bash에서 실행하고 Docker·전용 credential helper가 준비되어 있어야 한다. 토큰은 무표시 입력으로 받으며 credential helper 없이는 Docker 설정에 남을 수 있다. 승인한 private testorg namespace만 사용하고 public registry에 push하지 않는다. 외부 base image 없이 FROM scratch로 만든 데이터 전용 image이며 실행용 컨테이너가 아니다.
승인 후 변경 · 승인된 Linux Docker client의 전용 작업 디렉터리 · bash
판정: Login Succeeded·push digest를 기록한다. 원격 package는 자동 삭제하지 않는다. UI에서 연결 저장소/visibility를 확인하고 보존 만료·승인된 테스트 버전 삭제를 별도로 처리한다. 실패 시 작업 디렉터리와 로컬 image 잔여물을 지정 경로/태그에 한해 정리한다.
다운로드 증명은 캐시 없는 별도 승인 Docker daemon에서 수행한다. 같은 daemon의 pull은 로컬 레이어를 재사용하여 Blob 다운로드 장애를 놓칠 수 있다. 아래 PACKAGE_DIGEST에는 위 push가 반환한 전체 sha256 digest를 넣고, USER에는 read:packages와 실제 package 읽기 권한이 있는 일반 pilot을 사용한다. 별도 PC여도 동일 원격 Docker daemon을 사용하면 독립 검증이 아니다.
승인 후 변경 · 해당 image 레이어가 없는 승인된 별도 Docker daemon/client · bash
(
set -euo pipefail
set +x
: "${PACKAGE_DIGEST:?Set the approved push digest before this test}"
cleanup_auth() {
original_status=$?
unset CR_PAT
if ! docker logout containers.github.example.com; then
printf 'Credential cleanup failed; follow the approved cleanup procedure.\n' >&2
test "$original_status" -ne 0 || original_status=1
fi
exit "$original_status"
}
trap cleanup_auth EXIT
read -r -s -p 'Pilot read-only classic PAT: ' CR_PAT
printf '\n'
test -n "$CR_PAT"
printf '%s' "$CR_PAT" | docker login containers.github.example.com -u USER --password-stdin
unset CR_PAT
image="containers.github.example.com/testorg/ghes-smoke@$PACKAGE_DIGEST"
docker pull "$image"
docker image inspect "$image" --format '{{json .RepoDigests}}'
)
판정: 실제 레이어 다운로드 성공과 push/pull digest 일치를 모두 확인한다. registry는 읽지만 로컬 credential/image 캐시를 변경하며 저장소 요청·전송 비용이 발생할 수 있다.
10.4 Actions의 GITHUB_TOKEN 경로
workflow 저장소에 연결되어 있고 해당 저장소에 package 접근이 허용된 경우 아래 인증을 사용한다. workflow 수준의 permissions와 job steps에 각각 병합한다. Docker 준비는 runner에서만 한다. 기존 CLI-push package는 연결/Actions access 권한을 확인해야 하며, packages: write 선언만으로 다른 저장소 package 권한이 생기지 않는다. secrets.GITHUB_TOKEN을 별도 PAT로 생성해 저장하지 않는다.
승인 후 변경 · 승인된 테스트 workflow의 병합용 조각 · yaml
permissions:
contents: read
packages: write
# 기존 job의 steps에 병합할 단계
steps:
- name: Authenticate to this GHES registry
shell: bash
env:
PACKAGE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PACKAGE_USER: ${{ github.actor }}
run: |
set +x
printf '%s' "$PACKAGE_TOKEN" | docker login containers.github.example.com \
-u "$PACKAGE_USER" --password-stdin
# 승인된 synthetic image build/push 단계를 이 사이에 추가
- name: Logout
if: ${{ always() }}
run: docker logout containers.github.example.com
판정: 독립 실행 가능한 전체 workflow가 아니다. 실제 publish까지 승인한 경우에만 packages: write를 부여한다. OS credential store 접근도 runner 신뢰 경계에 포함한다.
10.5 장애·백업·완료 판정
확인 항목
조치/증거
401 / denied
GHES host·classic PAT scope·사용자 package 권한·저장소 연결·Actions access를 확인한다. SCIM 계정 생성 성공이 package 권한을 보장하지 않는다.
403 / storage 오류
Packages connection string·Shared Key 정책·container 존재·firewall을 먼저 본다. Actions OIDC의 SP 역할을 추가하는 방식으로 해결하지 않는다.
push 차단 / toggle 없음
Ecosystem Read-Only 상태·subdomain isolation·preview 승인 여부를 확인한다. 기존 private package를 public으로 바꾸어 우회하지 않는다.
백업·보존
GHES 설정·DB/메타데이터 백업과 외부 Blob 객체 보호를 분리해 설계한다. GHES 백업 완료가 모든 Blob 백업 완료를 뜻하지 않는다. 객체 lifecycle 자동 삭제가 GHES 참조를 깨지 않도록 retention·soft delete/versioning 호환성을 검토하고 함께 복원 시험한다.
신규 3.22 차이
Azure Packages 인증 절차는 동일하게 connection string이다. 3.22 신규 설치는 Backup Utilities 제거 계획을 반영해 내장 Backup Service 문서를 확인한다. DB와 Blob의 일관된 복구 시점·RPO/RTO는 별도 인수 항목이다.
최종 인수
비관리자 허용 pilot의 캐시 없는 private package 레이어 다운로드와 별도 미허용 pilot의 거부를 승인된 자원에서 확인한다. digest, 테스트 버전, 접근 결과, 정리 일정만 보관하고 PAT는 회수/회전한다.
진행 기준 / 완료 증거: 설정 적용 성공, synthetic push와 캐시 없는 pull의 digest 일치·실제 레이어 다운로드, 비관리자 allow/deny 확인, secret 정리, 외부 객체 포함 복구 책임자·보존 정책 승인. registry login만 성공한 상태는 미완료다.
담당: Cloud owner·구매·보안·GHES 관리자·pilot 개발자선행: 계약 경로·데이터 반출·클라이언트 승인산출물: 좌석/정책표·비관리자 pilot·지원 범위·회수 계획
3.21의 경계: GHES 저장소와 Copilot 서비스는 다르다
GHES는 GitHub Enterprise Cloud/EMU가 아니다. 3.21 appliance에 Copilot 모델·Cloud agent 서버를 설치하는 절차가 아니다. 일반적인 서비스 이용은 IDE/CLI의 Copilot 라이선스가 있는 github.com 또는 해당 GHE.com 계정 인증과 GHES의 Git/API 인증을 분리한다. 코드 저장소가 GHES에 있어도 선택된 prompt·코드 문맥이 모델 서비스로 전송될 수 있다.
신규 3.22의 중요한 예외 — Technical preview
3.22.0(2026-09-08) 공식 릴리스에는 GHES 관리자가 모델 공급자를 구성하고 사용자가 GHES 자격 증명으로 Copilot CLI를 사용하는 disconnected/air-gapped 구성이 추가되었다. 이를 3.21에 소급 적용하지 않는다. 이는 공식 CLI 연동 preview이며 GitHub-hosted 모델이나 Copilot cloud agent를 GHES에 설치하는 기능이 아니다. 외부 모델 endpoint를 선택하면 그 공급자로의 통신·문맥 전송은 여전히 필요하며, 완전 폐쇄망은 승인된 내부 호환 모델 endpoint와 도구 경계를 별도로 구성해야 한다. 운영 도입은 별도 검토한다.
GHES Git 인증과 Copilot 인증을 각각 기록한다. 같은 Entra IdP라고 사용자·토큰·tenant가 같다고 가정하지 않는다.
Copilot Business 전용 Cloud enterprise
일반 Cloud enterprise에 사용자를 직접 추가해 organization 비소속(unaffiliated)으로 관리하면 추가 GHEC 좌석을 소비하지 않는 구성이 가능하다.
Copilot Business는 과금된다. GHES 라이선스가 공짜가 되는 구조가 아니며 기존 조직 삭제로 비용을 회피하는 절차를 만들지 않는다.
PAYG Cloud + GHES license file
GHES 파일 좌석은 생성 시점의 consumed Cloud enterprise licenses 기준. 공식 문서의 Cloud organization 사용자 할당 등 조건을 충족해야 한다.
Billing & Licensing → Licensing의 소비 좌석을 확인한다. Copilot 좌석이나 People의 Total consumed로 대체하지 않는다. Server-only 사용자 청구/중복 제거와 GitHub Connect 요건도 확인한다.
Volume / subscription GHES 계약
구매 사용자 수와 계약 기간에 맞춘 GHES 권한. Cloud-only/Server-only/양쪽 사용 조건은 계약 확인.
Copilot-only enterprise 설명을 PAYG GHES 라이선스 우회 규칙으로 적용하지 않는다.
선택: EMU
Cloud 관리형 계정 운영이 필요한 경우에만 별도 Cloud/IdP 프로젝트로 진행.
GHES SCIM 또는 GHES 조직을 Cloud EMU로 간주하지 않는다. 이 단계에서 Cloud 조직·enterprise를 삭제하거나 마이그레이션하지 않는다.
11.2 Cloud 경로의 pilot UI와 실행 순서
책임자·승인표를 만든다
구매 담당은 상품/좌석/예산, Cloud enterprise owner는 AI controls, 보안 담당은 모델·클라이언트·MCP·데이터 반출, GHES 관리자는 코드 접근을 담당한다. 허용 IDE/CLI 버전, 모델, repository, tool별 read/write 범위와 폐기 일정을 작성한다.
좌석과 정책을 적용한다 — 변경
Cloud enterprise의 Copilot access 관리 화면에서 pilot을 할당한다. AI controls에서 모델·클라이언트·agent·MCP 관련 정책을 검토한다. 직접 할당 사용자는 Policies for enterprise-assigned users도 확인한다. GHES Management Console의 Actions/Packages 화면에서 설정하는 것이 아니다.
개발자 로그인과 출구를 분리 확인한다
IDE의 Copilot 로그인에서 라이선스 계정을 선택한다. CLI 일반 Cloud 로그인도 github.com 또는 GHE.com 경로를 사용한다. github.example.com을 Cloud Copilot 로그인 host로 무조건 넣지 않는다. 인증·모델 호출의 최신 공식 allowlist와 proxy CA를 승인하고 TLS 검증을 유지한다. GHES clone/push 인증은 별도로 준비한다.
synthetic 문맥으로 시험한다
승인된 private testorg 저장소의 무해한 예제 함수만 열고 ‘이 함수의 단위 테스트 초안을 제안하라’고 요청한다. 첫 시험은 제안 검토로 제한하고 파일/명령/MCP 쓰기 실행은 금지한다. 모델 응답·라이선스 인식·정책 차단·GHES read 접근 결과를 각각 기록한다.
비관리자와 차단 조건을 확인한다
pilot 일반 사용자로 재현하고, 승인된 비허용 모델/도구 또는 테스트 계정으로 차단을 확인한다. 광범위 토큰을 발급해 실패를 숨기지 않는다. 응답 원문보다 성공/거부, client·model 버전, 시각, 정책 식별자를 보관한다.
11.3 CLI/SDK BYOK·3.22 preview를 구분한다
선택
준비·입력
넘지 말아야 할 경계
3.21 + 로컬/외부 CLI·SDK BYOK
공식 BYOK 문서에 따라 승인한 외부 또는 로컬 모델과 secret store를 선택. GHES 접근 도구에 별도 자격 증명·DNS·TLS·최소 권한 제공.
사용자 정의 자동화이지 GHES 네이티브 cloud agent가 아니다. 로컬 BYOK는 GitHub 인증 없이 가능한 경로가 있으나 GHES API 작업의 인증까지 없어지지 않는다.
Enterprise BYOK
Cloud 측 사용자 정의 모델 정책·라이선스·인터넷 조건을 별도 검토.
로컬 BYOK와 동일한 과금·인증·오프라인 모델이라고 가정하지 않는다. 외부 모델이면 데이터는 외부 공급자로 전송된다.
3.22 preview 관리자
승인된 SSH 절차로 app.copilot-proxy의 enabled, endpoint-url, provider-type, provider-model-id 및 공급자 비밀을 구성. 공식 문서의 옵션/지원 공급자 확인.
비밀 값의 인라인 명령은 여기서 제공하지 않는다. 관리자 비밀 주입 절차와 ghe-config-apply 작업창 승인이 선행한다. appliance에 LLM을 설치하는 것으로 설명하지 않는다.
3.22 preview 사용자
COPILOT_PROVIDER_GHES_HOST=github.example.com, COPILOT_PROVIDER_GHES_TOKEN=승인된 비밀 주입, COPILOT_OFFLINE=true. gh의 GHES 인증 별도 확인.
호스트값 외에 토큰 실값은 표·로그·명령 history에 넣지 않는다. Cloud 연계 기능은 동일하게 동작한다고 보장하지 않는다. 지원 범위는 해당 preview 문서를 기준으로 한다.
3.22 preview가 승인·구성된 경우에만 아래 로컬 설정을 사용한다. 사전에 해당 GHES에 인증된 gh가 있어야 한다. 토큰은 stdout에 인쇄하지 않고 동적으로 받는다. API key 설정이나 preview 활성화를 이 명령이 대신하지 않는다.
로컬 세션·파일 · 3.22 preview 승인 pilot의 개발 PC · bash
set +x
COPILOT_PROVIDER_GHES_HOST=github.example.com
if COPILOT_PROVIDER_GHES_TOKEN="$(gh auth token --hostname "$COPILOT_PROVIDER_GHES_HOST")" &&
test -n "$COPILOT_PROVIDER_GHES_TOKEN"; then
export COPILOT_PROVIDER_GHES_HOST COPILOT_PROVIDER_GHES_TOKEN
export COPILOT_OFFLINE=true
printf 'Client environment prepared. Start only the approved CLI session.\n'
else
unset COPILOT_PROVIDER_GHES_TOKEN COPILOT_PROVIDER_GHES_HOST COPILOT_OFFLINE
printf 'STOP: no approved GHES token was retrieved.\n' >&2
fi
판정: 셸 환경만 구성한다. 토큰 조회 실패 시 성공으로 진행하지 않는다. 시작 전 client/provider 버전과 secret 취급을 확인한다. 종료 후 이 세 변수를 unset한다. 환경변수는 민감한 프로세스 데이터이므로 전용 세션에서만 사용하고 Cloud 모드와 섞지 않는다.
11.4 운영 정책·장애 분류와 인수
주제
운영 기준
데이터 문맥·content exclusion
현재 공식 문서는 CLI content exclusion 지원을 안내하지만 클라이언트·모드별 차이와 간접 semantic 정보·symlink/remote filesystem 한계가 있다. ‘모든 도구/모드에서 완전 차단’으로 보장하지 않는다. GHES 저장소에 실제 적용되는 정책 범위도 pilot에서 확인한다.
MCP·SDK·외부 도구
서버별 승인·도구 allowlist·토큰 scope·응답 데이터·명령/파일 쓰기 승인을 분리한다. content exclusion만으로 모든 MCP 응답과 사용자 정의 SDK 전달 데이터가 보호된다고 가정하지 않는다.
계정/좌석 오류
Copilot에 로그인한 Cloud 계정과 좌석·조직 정책부터 확인한다. GHES Git 로그인 성공을 Copilot 라이선스 증거로 삼지 않는다. 3.22 preview는 별도 provider/GHES token 경로를 점검한다.
네트워크/모델 오류
Cloud 또는 BYOK 공급자 endpoint·DNS·TLS·proxy·모델 허용·비용 제한을 구분한다. GHES REST 403과 모델 공급자 인증 실패는 서로 다른 원인이다.
Cloud agent 요청
3.21 GHES 저장소를 공식 Copilot cloud agent의 네이티브 대상으로 안내하지 않는다. 3.22 CLI preview도 cloud agent 설치가 아니다. 자동 PR 생성이 필요하면 별도 커스텀 통합으로 승인·감사·최소 권한을 설계한다.
중단/회수
pilot 좌석 회수, 승인 도구 중지, 토큰 폐기, 로컬 인증/환경 정리를 각 소유자가 수행한다. GHES 저장소 삭제 또는 Cloud 조직 삭제는 중단 절차가 아니다.
최종 검토일: 2026-09-19. Cloud/CLI 문서는 지속 변경된다. 위 날짜는 공개 문서 검토일이지 실제 고객 환경 인증일·지원 보증일이 아니다. rollout 전 해당 버전·계약·정책을 다시 확인한다.
진행 기준 / 완료 증거: 3.21 Cloud 경로 또는 별도 승인한 3.22 preview/BYOK 경로 명시, GHES와 AI 인증 분리, synthetic 응답 및 정책 차단 확인, 데이터 처리·MCP·비용·회수 책임자 승인. GHES 네이티브 cloud agent 설치로 인수하지 않는다.
공개 공식 문서를 기준으로 모니터링·로그 조사·운영 검증 절차를 설명합니다. 기본 절차는 GHES 3.21입니다. Phase 0의 입력표에 승인된 FQDN·환경 구분·실제 패치·토폴로지·관리 SSH 키·관리 콘솔 접근·증거 보관 폴더·담당자·알림 수신자·변경 번호를 기록합니다. 아래 HOSTNAME 등은 승인된 실제 값으로 바꾸는 자리표시자입니다. GHES site admin, Enterprise owner, Management Console 관리자, Cloud billing 담당 권한을 서로 같은 것으로 취급하지 않습니다.
12.1 매일 보는 화면과 정상·실패 분기
접속·시간·대상 확인
Site admin → Management Console → Monitor. HA/cluster는 노드 선택을 확인하고 같은 시간대의 정상 기준선과 비교합니다. 장애 시작·끝은 UTC로 기록합니다.
운영 상태에서 원인으로 이동
Operational Health에서 이상 구간을 찾고 System & Application Insights의 CPU·Memory·Storage·Application Health·Background jobs·Actions를 비교합니다. CPU만 보지 말고 I/O 지연, 디스크 포화, 요청 큐, 백그라운드 적체와 배포 시점을 함께 봅니다.
이상 시 변경보다 증거 확보
노드·UTC 구간·지표·영향 기능을 먼저 남깁니다. 인증 오류, 스토리지 지연, Runner 부족을 구분하고 담당자에게 전달합니다. 서비스 재시작·확장·에이전트 설치를 일상 조회 명령에 섞지 않습니다.
점검
정상 판정
실패 시 조치 / 증거
CPU·RAM
업무량 대비 건강한 기준선; Linux 캐시를 누수로 단정하지 않음
지속 상승과 응답 지연 동반 여부, VM 예약·경합·실행 중 백업을 확인
디스크·I/O
root와 /data/user를 따로 추적; 여유·증가율·지연 측정
공식 저장소 경고 60% / 위험 75%를 출발점으로 운영 임계값 승인; 삭제 대신 용량 계획
요청·작업 큐
큐가 해소되고 p90 응답 시간·오류율 안정
Queued requests의 No data는 대기 없음일 수 있음; 수집 장애와 구별
Actions
서비스 요청·MSSQL 지표와 실제 작업 성공 모두 확인
조직/저장소 Actions → Runners 및 대기 작업의 labels·runner group·외부 저장소를 별도 점검
알림·복구
승인된 시험 알림이 담당자에게 도착하고 최근 복구 시험 증거 존재
그래프·메일 설정 화면만으로 알림 설정 또는 복구 완료를 주장하지 않음
400 GB root가 200 GB로 보이는 이유
공식 구조 예시는 root 볼륨 400 GB 중 root filesystem 200 GB, 나머지 절반은 업그레이드·롤백용입니다. 3.14 이후 신규 설치에는 작은 BIOS/UEFI 파티션도 있으므로 실제 바이트 수는 따로 확인합니다. 사용자 데이터 볼륨 /data/user는 별개입니다. 예약 영역을 여유 데이터 디스크로 합산하거나 root 표시만 보고 디스크 누락으로 판단하지 않습니다.
판정: 예상 버전·서비스·라이선스 유효성 확인. 출력에는 내부 정보가 있으므로 원본은 제한 보관. 연결 실패 시 DNS·TCP 122·키 권한부터 확인.
12.2 제한된 로그 조사와 지원 자료
경로 / 선택자
용도
조회 원칙
/var/log/github/exceptions.log
애플리케이션 예외
장애 UTC 구간과 연관된 최근 행부터
/var/log/github/audit.log
사용자·저장소·시스템 이벤트
원본에는 신원·저장소 정보가 포함될 수 있음
/var/log/enterprise-manage/unicorn.log
관리 콘솔 UI/API HTTP 요청
SMTP 자격 증명·요청 본문을 공유하지 않음
/data/user/common/ghe-config.log
최근 설정 적용·업그레이드 진행
출력 중단은 실패일 수 있음; 완료로 오인 금지
journalctl -t github-unicorn
웹/API 요청 및 인증 관련 기록
UTC 시작·끝·최대 200행으로 제한
조회할 UTC 시작·끝을 먼저 지정: 승인된 관리 셸에서 START_UTC와 END_UTC를 실제 실패 구간의 YYYY-MM-DD HH:MM:SS UTC 값으로 설정합니다. 기본값은 없으며 미설정·빈 값이면 조회하지 않습니다. UTC 구간 지정을 참고합니다. ghe-config.log는 최근 설정 적용 조사용이며 SCIM 기본 조회 대상이 아닙니다.
조회 · 승인된 GHES 관리 셸 · bash
(
: "${START_UTC:?Set START_UTC to the actual start: YYYY-MM-DD HH:MM:SS UTC}"
: "${END_UTC:?Set END_UTC to the actual end: YYYY-MM-DD HH:MM:SS UTC}"
tail -n 200 /var/log/github/exceptions.log
tail -n 200 /data/user/common/ghe-config.log
journalctl -t github-unicorn --utc --since "$START_UTC" --until "$END_UTC" -n 200 --no-pager
)
판정: 실제 UTC 시작·끝을 사전 설정해야 조회. journalctl 시간·행 제한은 표준 옵션이며 GHES 문서는 tag를 확인해 줌. tail은 시간 필터가 아니므로 각 행의 시간을 확인.
필터링 ≠ 비식별화
선택적으로 grep으로 범위를 줄여도 전체 비밀·개인정보가 제거되지는 않습니다. 원본 로그·지원 번들은 접근 제한 보관하며, 공유본만 별도 검토·비식별화합니다. MIP/DLP 또는 조직 정책상 반출 불가한 실제 데이터는 외부 서비스·채팅에 첨부하지 않습니다. SMTP 비밀번호나 토큰을 로그에 출력하는 진단은 하지 않습니다.
판정: 서버 진단 생성·로컬 파일 쓰기 승인이 필요. 종료 코드 0과 비어 있지 않은 정상 압축 파일을 확인. 기존 파일 덮어쓰기는 차단하며 실패 시 부분 파일을 성공 자료로 사용하지 않음.
폴더·파일 이름은 승인된 실제 값으로 치환합니다. 호스트 키 검증을 끄지 않습니다. UI 대안은 Management Console → Support → Download support bundle입니다. geo-replication/cluster는 공식 절차의 ghe-cluster-support-bundle -p 2days -o 적용 여부를 확인합니다. -u·-t 자동 업로드 옵션은 사용하지 않으며 생성 후에도 반출 승인은 별개입니다.
12.2.1 기본 로그는 어디서 보는가
대상과 권한 고정
승인된 관리자 PC에서 위 ssh -p 122 admin@HOSTNAME으로 연결합니다. HOSTNAME은 실제 승인된 GHES 호스트로 치환합니다. 예시 https://github.example.com/api/v3/scim/v2는 승인된 실제 호스트로 바꿉니다. GHES용 Entra 앱·테넌트·실제 Tenant URL을 확인하고 Cloud용 앱과 구분합니다.
최근 일부만 조회
아래는 기본 애플리케이션 로그의 최근 100행입니다. 파일 전체나 최근 100분이 아닙니다. 행별 시각·시간대·노드와 실제 실패 구간을 대조합니다. 읽기 권한 오류는 기록 부재가 아니며 임의 권한 변경으로 우회하지 않습니다.
조회 · 승인된 GHES 관리 셸 · bash
tail -n 100 /var/log/github/production.log
판정: 최근 애플리케이션 기록 100행까지만 조회. 요청 경로·오류 문맥을 확인하되 HTTP 수신 증거와 별도로 대조.
조회 · 승인된 GHES 관리 셸; 필요한 경우만 짧게 관찰 · bash
tail -n 100 -F /var/log/github/production.log
판정: 최근 100행 다음에 새 기록을 계속 표시. 예: 1~2분 관찰 후 Ctrl+C로 조회기를 종료하며 서비스는 중지되지 않음.
판정: 실행 시점 기준 최근 20분 중 최대 200행. 장애가 더 이전이거나 요청량이 많으면 이 결과만으로 누락 여부를 판단하지 않음.
실제 UTC 시작·끝 입력 필수 — 기본값 없음
실패 이벤트의 날짜·시간대를 확인하고 같은 관리 셸에 START_UTC와 END_UTC를 YYYY-MM-DD HH:MM:SS UTC 형식으로 설정합니다. 시작이 끝보다 앞선 제한된 구간인지 확인합니다. KST(UTC+9)는 9시간을 빼 UTC로 환산합니다(예: 18:30 KST → 09:30 UTC). 자정을 넘으면 날짜도 조정합니다. 변수가 없거나 비어 있으면 아래 subshell만 중단하며 조회하지 않습니다.
조회 · 실제 장애 UTC 구간 확인 후 승인된 GHES 관리 셸 · bash
(
: "${START_UTC:?Set START_UTC to the actual start: YYYY-MM-DD HH:MM:SS UTC}"
: "${END_UTC:?Set END_UTC to the actual end: YYYY-MM-DD HH:MM:SS UTC}"
journalctl -t github-unicorn --utc --since "$START_UTC" --until "$END_UTC" --no-pager -n 200 -o short-iso
)
판정: 구간 내 최대 200행. 200행에 도달하면 창을 더 작게 나누어 확인하고 전체 구간을 다 봤다고 단정하지 않음.
12.2.3 SCIM: HTTP 수신부터 애플리케이션 오류까지
Entra의 사용자별 provisioning event에서 실패 단계·상세 응답을 먼저 확인합니다. 할당 직후 사용자가 없으면 자동 주기의 진행·대기와 Stopped 상태를 구분합니다. 승인된 단일 시험 사용자의 이벤트를 대조하며 전체 재프로비저닝으로 진단을 시작하지 않습니다.
판정: 최근 20분·최대 200행 안에서만 추가 검색. 결과가 없으면 필터 없는 기록·정확한 실패 창·HTTP 로그를 다시 대조.
메서드·경로·응답을 함께 읽기
원본 응답 / HTTP 상태
가능한 의미
다음 확인
GET 200
조회 성공; 사용자 생성 성공이 아님
Users 조회·연결 검사와 실제 생성 POST를 구분
POST 201
사용자 생성 요청 성공
반환된 대상 ID와 실제 GHES 사용자·감사 이벤트를 대조
PATCH 200 / 204
업데이트 요청 성공
active·roles 등 실제 변경 속성 확인; 신규 생성으로 집계하지 않음
400
응답 상세가 중요; out of seats 등
상세 문구가 좌석 부족이면 설치 키 한도·소비 확인. 모든 400을 좌석 부족으로 단정하지 않음
401 / 403
인증·인가 또는 경계 proxy/WAF 거부 가능
GHES 원본 응답인지 경계 장비 응답인지 확인 후 호스트·토큰·권한 대조
5xx
서버 또는 upstream 오류 가능
동일 UTC·노드·request ID의 exceptions 및 nginx error를 대조
LB/WAF의 상태와 GHES 원본(origin) 상태를 구분합니다. HTTP 200인 HTML 로그인 응답은 SCIM 성공이 아닙니다. 메서드·경로·UTC·source/target ID·request ID를 기록하고 실제 응답에서 확인된 값만 사용합니다. Entra Change ID는 자동으로 GHES request ID가 되지 않습니다. 일치가 확인되지 않으면 각 ID를 별도 필드로 보관하고 시간·대상·작업을 함께 대조합니다.
판정: 각 파일 최근 100행의 예외·upstream 오류를 production.log 및 HTTP 수신 기록과 대조. 단독 오류 문구로 원인을 확정하지 않음.
감사 이벤트는 HTTP 요청 로그의 대체물이 아닙니다. 실패한 생성은 사용자 생성 감사 이벤트를 남기지 않을 수 있습니다. GHEC에 무작위처럼 보이는 계정명이 있다는 사실만으로 새 신원 생성이나 GHES 계정과의 동일성을 확정하지 않습니다. 호스트·Entra 객체·externalId·대상 ID·생성 시각을 비교합니다.
12.2.5 라이선스 UI·설정 적용은 별도 분기
Management Console의 라이선스 업로드·갱신 UI/API 오류를 조사할 때만 콘솔 로그를 추가합니다. 일반 GHES License 화면 오류는 먼저 해당 요청의 production/journal/HTTP 기록을 확인합니다. SCIM 기본 조사에 콘솔·설정 로그를 무조건 섞지 않습니다.
조회 · Management Console 라이선스 UI·갱신 오류를 조사하는 승인된 GHES 관리 셸 · bash
판정: 콘솔 요청 시각·상태를 대조. 자격 증명·요청 본문 등 민감 필드가 있을 수 있으므로 원문 공유 금지.
조회 · 최근 설정 적용·업그레이드와 오류 시점의 관련성을 조사하는 승인된 GHES 관리 셸 · bash
tail -n 100 /data/user/common/ghe-config.log
판정: 설정 적용의 시작·완료·실패를 구분. 최근 적용이 없으면 SCIM 진단의 기본 출발점으로 사용하지 않음.
새 라이선스 키 업로드나 재시작 뒤 정상화가 관측되더라도 이는 변경 후 관측입니다. 키 한도·실패 상세·변경 전후 요청을 비교하지 않고 근본 원인이 입증됐다고 쓰지 않습니다. 라이선스와 Connect의 사용량 동기화는 분리하며 Sync/Enable만으로 설치 키의 좌석 한도가 늘어날 것으로 기대하지 않습니다.
12.2.6 내장 통합 로그 관찰 — 선택 사항
조회 · 승인된 GHES 관리 셸; 특정 로그로 좁히기 어려운 경우만 · bash
ghe-logs-tail
판정: GHES 내장 도구로 관련 로그를 함께 관찰하므로 출력량·민감 정보가 많을 수 있음. 1~2분 등 짧은 관찰 후 Ctrl+C로 종료.
이 통합 관찰과 tail -F는 총 출력 행 수가 제한되지 않습니다. 기본 선택은 위의 제한된 조회이며 Ctrl+C는 조회기만 종료하고 GHES 서비스는 중지하지 않습니다. 파일 전체 복사나 무기한 수집으로 대체하지 않습니다.
12.2.7 무출력·연결 오류·자료 취급 주의 조회표
관측 / 오해
안전한 확인 / 중단 기준
grep 무출력 = 서버 호출 없음?
아님. 실제 GHES 앱·Tenant URL(Cloud 아님), 요청 처리 노드·LB 경로, UTC/시간대, 보존·회전 파일, 마지막 N행·검색 필터를 확인. 기본 시스템 로그는 24시간마다 회전·회전 로그 7일 보존이며 실제 정책도 확인
Connect의 일반적인 cannot connect / cannot verify 메시지
NTP 장애 확정이 아님. DNS·TLS·아웃바운드·proxy와 실제 시간 오차를 각각 확인. NTP/disconnect는 원인 증거를 대신하지 않으며 Disable 후 재연결을 기본 처방으로 삼지 않음. Connect 참조
일시적으로 proxy 없이 넓은 outbound 허용 후 연결
운영 최종 구성 완료가 아님. 승인된 최소 목적지·포트와 proxy 경유 재시험, 임시 규칙 회수·담당·기한을 남김. 네트워크 참조
기본 로그에 정보가 부족함
debug 활성화·DB 콘솔·tcpdump·추가 패키지 설치·서비스 재시작을 기본 진단에 포함하지 않음. 제한된 증거와 미확인 사항을 정리해 승인된 지원 절차로 이관
읽기 전용이면 공유해도 됨?
아님. 신원·이메일·내부 경로·요청 본문·토큰·SAML assertion·쿠키·자격 증명이 포함될 수 있음. 원문은 접근 제한 보관, 공유본은 별도 비식별화·승인. grep은 비식별화 도구가 아님
외부 목적지 사전 승인. 활성화 이후 데이터, at-least-once 전달이므로 중복 처리·수신 지연 시험
SMTP 알림
Management Console → Settings → Email; 승인 후 Test email settings / Send test email
송신 relay의 승인 포트 사용: 587/STARTTLS 예시와 25를 구별. 회신 수신은 GHES inbound 25·MX 별도 설계
만료·갱신
TLS·IdP 서명 인증서·PAT·App 자격 증명·GHES 라이선스 만료 목록
각 소유자·대체 담당·갱신 창·사전 알림 일정·시험 수신 증거 기록; 이 문서가 알림을 설정한 것은 아님
조회 · 해당 GHES에 사전 인증·인가된 관리자 PC의 GitHub CLI · bash
gh api --hostname HOSTNAME --method GET /enterprise/settings/license
판정: seats / seats_used / seats_available / expire_at / days_until_expiration 비교. 401·403은 호스트·인증·인가 확인; 문서에 없는 토큰 scope를 추정하거나 확대하지 않음.
UI는 Enterprise settings → Settings → License입니다. ghe-license info와 ghe-license check만 일상 조회에 사용하며 --used는 포함하지 않습니다. Code Security·Secret Protection 또는 기존 Advanced Security 계약은 활성 저장소의 최근 90일 내 push된 커밋의 고유 active committer를 기준으로 검토합니다. 저장소별 수를 단순 합산하거나 사용자별 좌석 체크박스로 수동 배정하는 모델로 설명하지 않습니다. GHEC 청구·Copilot 구독/정책은 별도이며 확인하지 않은 Cloud 화면을 GHES 경로로 만들지 않습니다.
운영 시험
승인된 목표 / 관측
합격·실패 처리
가용성 SLO
업무 시간·성공 요청 비율·측정 창·제외 조건 합의
실제 측정치와 목표 비교; 임의 가용성 보장 금지
RPO / RTO
13장의 마지막 복구 가능 시점·복구 완료 시간
목표 초과 시 주기·용량·복구 절차 수정 후 재시험
퇴사 soft 차단
승인된 시험 사용자로 IdP 차단과 GHES 계정 정지·자격 증명 정책 확인
웹·Git·API 접근 거부와 조직/자산 보존 확인; IdP 차단만으로 모든 PAT 차단을 가정하지 않음
13.1 Backup Utilities와 Backup Service: 확인된 사실과 미확인 사항
3.21 Utilities 문서는 Service를 권장하고 Utilities를 “scheduled for removal in … version 3.22”라고 명시합니다. 3.22.0 GA 릴리스 노트(2026-09-08)에서는 Utilities의 실제 제거·deprecated 항목을 확인하지 못했습니다. 제거 예정과 제거 완료는 다릅니다. 3.22 Utilities 문서 URL이 Service 설명으로 이동하는 사실도 실행 파일 제거의 증명은 아닙니다. 따라서 ‘3.22에서 제거 완료’ 또는 ‘3.22에서도 계속 지원’ 어느 쪽도 단정하지 않고 전환·지원 여부를 업그레이드 차단 조건으로 둡니다.
방식
실제 구조
운영 선택
기존 Backup Utilities / 3.21
별도 Linux backup host에 설치, SSH로 GHES에서 수집; backup.config의 GHE_DATA_DIR에 저장
운영 중인 원격 호스트의 버전·키·일정·복구 시험을 먼저 기록. appliance에 무작정 설치하지 않음
Backup Service / 3.21·3.22
GHES 내장·관리 콘솔 관리; 별도 백업 소프트웨어 호스트 불필요, 전용 볼륨 /data/backup
조회한 두 버전 문서는 NFS mount를 피하도록 안내. NFS 서버/경로 입력 UI를 만들어 넣지 않음
독립 보관
같은 장애 영역의 연결 디스크 하나는 사이트 DR을 충족하지 못함
암호화·접근 분리·별도 사이트 보관·복원 가능한 사본·retention/immutability는 별도 스토리지 정책으로 검증
HA
active/passive 비동기 복제; 손상·삭제도 전파 가능
HA ≠ 백업. 수동 승격·DNS/LB 전환·split-brain 방지가 필요
13.2 백업 입력표 → 초기 설정 → 첫 성공
저장소 승인
Phase 0의 입력표에 백업 방식·소스 버전·전용 디스크 ID·용량·마운트·복구 대상·UTC 일정·보존 개수·RPO/RTO·담당자를 기록합니다. Service는 primary 데이터 디스크 사용량의 최소 5배, 대소문자 구분 및 hard/symbolic link 지원을 확인합니다. Utilities 문서의 primary 할당량 5배 권고와 혼동하지 않습니다.
Service 저장소 준비 — 파괴 작업 분리
하이퍼바이저에서 승인된 전용 디스크를 연결하고 아래 조회로 식별합니다. 신규 빈 디스크에 한해서 공식 ghe-storage-init-backup 초기화 절차를 2인 확인 후 수행합니다. 초기화는 해당 장치를 포맷·삭제하므로 복사 가능한 포맷 명령은 제공하지 않습니다. 기존 초기화 디스크는 재포맷하지 말고 공식 재사용 절차로 mount service를 활성화합니다. root·data 디스크와 불명확하면 중단합니다.
Service 화면 입력
/data/backup 마운트 후 Management Console의 Backup 영역 / Backup Service가 나타납니다. Settings → Backup에서 승인 일정(Daily 또는 custom cron)과 Number of snapshots를 설정하고 Save settings합니다. 기본 10개는 10일이 아닙니다. Include Pages·Skip search indices·복구 시 감사/관리 암호 옵션을 승인 범위와 대조합니다. Save settings는 서비스 재시작 가능성이 있는 변경이므로 적용 완료까지 확인합니다.
최초 백업
변경 창의 I/O·비용·잔여 용량 승인 후 Backups → Backup Now를 선택합니다. 첫 실행은 full, 이후 증분 판단은 서비스가 수행합니다. CLI 대안은 아래와 같으며 UI와 동시에 실행하지 않습니다. Backup Service → Backup History에서 시작·종료·성공·snapshot ID·지속 시간을 기록합니다.
기존 Utilities 경로
별도 호스트에서 호환 release archive·backup.config·GHE_HOSTNAME·GHE_DATA_DIR·일정을 검토합니다. GHES 관리 키 등록과 TCP 122를 승인한 다음 아래 host check와 백업을 수행합니다. Service로 이전할 때 설정 재입력 또는 공식 migration 절차를 사용하고 새 복구 시험 전 기존 사본을 폐기하지 않습니다.
조회 · 승인된 GHES 관리 셸 · bash
lsblk
findmnt /data/backup
df -h /data/backup
판정: 전용 장치·실제 mount·용량을 대조. mount 없음이나 화면 미노출은 초기화 완료가 아님.
승인 후 변경 · Backup Service가 구성된 GHES 관리 셸 · bash
ghe-backup
판정: 백업 쓰기·CPU/I/O 비용 발생. 성공 종료와 이력·snapshot·복구 가능성을 따로 확인.
승인 후 변경 · 기존 3.21 전용 Backup Utilities 호스트의 설치 디렉터리 · bash
./bin/ghe-host-check && ./bin/ghe-backup
판정: 연결 실패 시 키·호스트·TCP 122·지원 버전 해결 전 백업 실행 금지.
13.3 백업 상태 판정과 보관 범위
조회 · Backup Service 사용 GHES 관리 셸 · bash
tail -n 200 /var/log/github-backup/backup-verbose-YYYYMMDD.log
ls -l /data/user/common/backup_utils_in_progress
판정: 로그 파일명은 backup-verbose- 뒤 날짜 앞 하이픈 포함. YYYYMMDD는 해당 서버 로그 날짜로 치환. marker 존재는 진행 중 신호; 부재는 성공 증거가 아님.
실패/중첩이면 이전 작업의 진행·스토리지 접근·여유·지연·버전을 확인하고 중복 실행을 멈춥니다. marker를 지우거나 retention을 줄여 즉시 재실행하지 않습니다. 성공 후 자동 prune이 일어나므로 보존 변경도 승인 대상입니다. 매일 마지막 성공의 나이·지속 시간·누락 일정·잔여 용량을 확인하고 복구 시험을 주기적으로 재수행합니다.
데이터
보호 범위 / 별도 정책
복구 순서·판정
Git·DB·설정·Pages·검색
snapshot 내용과 Include Pages / Skip search indices 실제 값 확인
설정·메타데이터·저장소 검증; 검색 재색인 지연은 데이터 누락과 구분
Actions
외부 logs·artifacts·blob은 GHES snapshot에 포함되지 않음
외부 저장소를 준비·접근 검증 → Actions 설정 → GHES restore → 설정 적용 → Runner 재등록
Packages
GHES snapshot만으로 외부 blob 보호를 충족하지 않음; 저장소 사업자 백업·보존·복구 정책 필요
복원한 blob과 GHES 메타데이터 시점 일치 확인 후 시험 package 다운로드/게시
네트워크·비밀
대상 네트워크는 별도 준비; storage 인증·TLS·license·관리 암호 복원 영향 검토
비밀은 vault/승인 채널 사용. 운영 설정 복원으로 시험 환경에서 운영 연결이 열리지 않도록 차단
설명용 개념도. HA, 시점 백업, 외부 객체 보호, 격리 복원은 다른 목적입니다. 복원 성공과 실측 복구 시간으로 운영 준비를 판단합니다.
13.4 격리 STAGING 복구 훈련
복구 선언·버전 선택
사고 기준 T0, 선택 snapshot의 복구 가능 시점 T1, 복구 시작 T2를 UTC로 기록합니다. 같은 feature 또는 최대 두 feature 앞 대상까지 지원하며 최신→구버전 복원은 금지입니다. 예: 3.21 snapshot은 3.21/3.22 대상 가능, 3.22→3.21은 불가. 처음에는 같은 패치로 연습합니다.
격리 먼저
새 STAGING 대상의 DNS·방화벽·관리 접근을 분리합니다. 운영 IdP/SCIM·webhook·SMTP·Runner·Actions/Packages 쓰기를 차단하고 시험용 목적지만 허용합니다. 서비스 시작 전에 차단을 적용합니다. snapshot 및 외부 저장소 사본을 준비하며 운영 storage 자격 증명을 시험에 그대로 복제하지 않습니다.
Actions 호환성 게이트
공식 Actions 복구는 원래 provider/credentials를 사전 구성하도록 안내합니다. 격리 복제 저장소의 주소·인증으로 메타데이터 호환성을 보장할 수 없으면 전체 Actions 복구 시험을 중단하고 지원팀과 격리 설계를 확인합니다. 운영 연결로 우회하거나 부분 시험을 전체 성공으로 보고하지 않습니다.
maintenance·복원
대상 maintenance를 켜고 백업 읽기 접근을 확인합니다. HA 구성 대상은 replication stop만으로 부족하며 공식 teardown 절차가 필요하므로 훈련은 새 standalone으로 시작합니다. 아래 선택 snapshot만 복원합니다. -c는 설정·인증서·license 덮어쓰기 옵션이지 DB 복원 여부가 아니므로 기본 예제에서 제외합니다.
승인 후 변경 · 운영과 격리된 STAGING Backup Service 복구 대상 관리 셸만 · bash
ghe-restore -s SNAPSHOT_TIMESTAMP
판정: 전체 대상 데이터 덮어쓰기. 대상·snapshot·버전·네트워크 격리·승인 2인 확인 없으면 실행 금지.
승인 후 변경 · 기존 3.21 Backup Utilities 호스트; 위 Service 명령 대신 사용하는 경로 · bash
판정: 대상은 승인된 격리 STAGING만. 대상 관리 키·버전·maintenance 확인 후 대화형 승인; -c 생략.
설정 검토·시작
Management Console에서 네트워크·인증·TLS·storage·관리 암호 복원 영향을 확인 후 Save settings합니다. 네트워크 격리를 유지한 채 승인된 시험 IP exception list로 제한 접근을 열어 Git·issue·LFS·Pages·API·감사·검색·시험 Actions/Packages를 검증하고 Runner를 재등록합니다. 실패 시 restore-verbose-[timestamp].log를 제한 조회하며 HA 재구성은 standalone 성공 뒤에만 진행합니다.
측정·종료
검증 완료 T3을 기록합니다. 관측 데이터 손실 구간은 T0−T1, 기술 복구 시간은 T3−T2, 사고 기준 서비스 회복 시간은 T3−T0입니다. 외부 blob의 일관된 복구 시점까지 포함해 승인 RPO/RTO와 비교합니다. 훈련 종료는 운영 트래픽 전환 승인이 아니며 결과·미복구 항목·후속 조치·사본 보존을 서명합니다.
13.5 HA 장애 전환은 별도 변경
replica는 hot standby이며 일반 사용자용 독립 읽기 전용 서버가 아닙니다. 일반 HA에서 replica 관리 콘솔은 replication mode를 표시하고 Git 요청은 primary로 전달될 수 있습니다. 노드 간 TCP 122·UDP 1194는 공식 포트 기준으로 범위 승인합니다. 연결·복제 상태를 확인하고 장애 선언 → 기존 primary fencing/maintenance → 미복제 손실 승인 → 수동 승격 → DNS/LB 전환 → 기능 검증 순서를 별도 실행계획으로 승인합니다. 여기에는 복사 가능한 운영 승격 명령을 넣지 않습니다. 되돌릴 때 양쪽 쓰기 허용 금지·재복제 계획이 필요합니다. 3.22는 cluster topology의 HA replication을 retired로 명시하며 일반 standalone HA와 다릅니다.
담당: 변경 관리자·GHES·서비스 담당선행: 지원 경로·용량·STAGING·복구 게이트산출물: 버전/서명·검증·변경 종료 증거
14.1 기준일·지원 버전·변경 영향
feature
GA
지원 종료 / closing down
운영 기준
3.21
2026-06-11
2027-06-11
이 문서의 기본 운영 절차; 실행 시 최신 보안 patch·known issues 재검토
3.22
2026-09-08
2027-09-08
2026-09-19 현재 GA; 과거 9월 1일 RC 안내를 적용하지 않음
릴리스 선택 게이트
실행 당일 all-releases·해당 release notes·Security fixes/CVE·공식 다운로드를 재조회합니다. 특정 patch를 영구 최신으로 고정하지 않습니다. 3.21→3.22는 feature upgrade이며 대상은 소스보다 최대 두 feature 앞까지입니다(중간 feature 하나 생략 가능). Upgrade assistant에서 실제 source patch·target patch·플랫폼 경로를 확인하고 이전 migration/background jobs 완료를 검증합니다.
3.22 차이
3.21 대비 필요한 조치
Backup Utilities
3.21 문서의 3.22 제거 예정과 GA 노트의 확인 부재를 구분. Service 전환·복구 시험·지원 확인 전 진행 금지
복제·복원
새 replication controller 및 controller 활성 시 ghe-restore storage 미복원 known issue 확인; 복구 검증 없는 승격 금지
Cluster HA
3.22에서 해당 topology의 HA replication retired. 일반 HA 절차로 대체하지 말고 구조 전환 승인
업그레이드 단계
3.22 노트에 phased execution 소개. 문서는 3.21+ 실행 가능 안내; 실제 source의 help로 지원 확인
연동·보안
/repos 경로 충돌, pre-receive hook networking 기본 차단, 제거된 API 필드·Security 설정 API 점검
Actions·Dependabot
voting storage의 번들 Actions 설치 및 기존 Dependabot 일정 중단 known issues를 회귀 시험에 포함
관측성
Collectd는 3.22와 이전 지원 창에서 지원; 제거 예고는 3.23. 3.22에서 이미 제거됐다고 쓰지 않음
설명용 개념도. 버전·경로 확인부터 백업·staging·승인·변경 후 검증까지. 실패 시 무조건 이전 버전으로 덮어쓰는 방식이 아닙니다.
14.2 준비·다운로드·검증
영향·복구 승인
변경 창·사용자 공지·서비스 중단 허용·담당·중단 시각·복구 승인자를 확정합니다. STAGING에서 SAML/LDAP·SCIM·GitHub Apps/OAuth·webhook·Runner·Actions·Packages·Code Security/Secret Protection·GEI 등 실제 사용 기능을 시험합니다. Cloud EMU 화면을 GHES로 대체하지 않습니다.
용량·백업 게이트
공식 capacity 점검: CPU/메모리 통상 70% 미만, 디스크 비포화, 요청 큐 지속 200 미만, Aqueduct 적체 1~2시간 미만 및 data disk 최소 15% 여유를 확인합니다. 최근 백업·외부 storage·복구 시험과 feature 변경 직전 일관된 VM/디스크 snapshot 계획을 모두 준비합니다. 미충족이면 일정 연기합니다.
패키지 선택
공식 releases → 대상 버전 Download → Upgrading → 실제 플랫폼의 .pkg를 선택합니다. URL·파일 크기·공식 SHA256(제공되는 artifact)·서명 검증 결과를 기록합니다. 게시되지 않은 hash를 만들지 않습니다. 3.21→3.22에 .hpkg나 Management Console의 patch 설치 화면을 사용하지 않습니다.
조회 · 업그레이드 전 source GHES 관리 셸 · bash
ghe-version
ghe-upgrade -h
판정: source patch/platform과 실제 지원 옵션 확인. --check / -c는 공개 문서로 의미 미확인: 사용하지 않음.
승인 후 변경 · 여유 공간·출력 파일명·다운로드가 승인된 source GHES 관리 셸 · bash
cd /home/admin && test ! -e APPROVED-UPGRADE.pkg &&
curl --fail --location --output APPROVED-UPGRADE.pkg 'OFFICIAL-PKG-URL' &&
sha256sum APPROVED-UPGRADE.pkg
판정: 기존 파일이 있으면 중단. 출력 SHA256을 해당 artifact의 공식 값과 직접 비교. 크기·hash 불일치 또는 다운로드 실패면 중단; 실패 시 남은 부분 파일은 재사용하지 않음.
판정: 공개 hash가 없는 artifact는 공식 서명 검증 경로를 승인받아 진행. --verify는 공식 검증이지만 무쓰기 조회로 보장하지 않음. 서명 실패는 중단하며 설치로 우회하지 않음.
14.3 standalone feature upgrade 실행
maintenance와 snapshot
Management Console → Maintenance → Enable maintenance mode → now → Save. 진행 중 쓰기·작업 종료를 기다린 뒤 승인한 일관된 VM/디스크 snapshot을 생성·식별합니다. 전원이 켜진 VM의 임의 snapshot만으로 정합성을 가정하지 않습니다. maintenance 설정은 실제 서비스 변경입니다.
설치·재시작
아래 명령의 패키지 경로와 표시된 target·서명을 다시 확인한 뒤 대화형 설치를 승인합니다. 새 root 영역 쓰기 및 자동 재시작을 예상하고 콘솔 접근을 유지합니다. 자동 yes 옵션은 넣지 않습니다. phased pre-upgrade는 준비 쓰기 작업이며 실제 지원 확인·별도 승인 시 표준 설치 대신 공식 절차를 택합니다.
승인 후 변경 · 모든 게이트가 통과된 standalone GHES 관리 셸; 먼저 STAGING · bash
ghe-upgrade /home/admin/APPROVED-UPGRADE.pkg
판정: 승인된 버전 설치·재시작. SSH 단절은 예상되지만 시간 초과 시 강제 재실행하지 않고 콘솔·로그 확인.
판정: 목표 버전 및 자동 config apply 성공 확인. SSH 접속만으로 완료 아님; 자동 설정 실패 시 maintenance 유지, 근거 수집.
검증 후 개방
migration·background jobs 상태와 custom firewall 규칙 재적용을 확인합니다. 자동 config apply를 이유 없이 재실행하지 않습니다. 제한된 시험 접근으로 로그인·clone/fetch/push·API·webhook·Actions/Packages·Security·백업 일정 및 첫 후속 백업을 확인합니다. IP exception list는 제한 접근 상태로 maintenance를 해제하는 기능이므로 별도 승인합니다.
정상화
성공 증거·담당 서명 후 IP exception list를 사용했다면 해당 목록 기능을 비활성화·저장합니다. 사용하지 않았다면 Maintenance의 Enable maintenance mode를 해제·저장합니다. 시험 허용 목록 밖의 일반 사용자 접근도 재검증합니다. CPU/I/O·큐·오류율을 이전 기준선과 비교하며 관찰 창 종료 뒤 변경을 닫습니다. 실패하면 접근을 제한한 채 복구 분기로 갑니다.
14.4 patch·HA·cluster 분기와 실패 복구
분기
절차 / 중단 기준
동일 feature hotpatch
대상 patch의 자격을 확인. standalone은 automatic update checks 후 Updates → Install package 사용 가능. 일부 서비스 중단/재시작 가능하므로 모든 patch가 무중단이라고 약속하지 않음
일반 HA의 .pkg
복제 정상 → primary maintenance → replica 복제 정지 → primary 업그레이드·config 성공 → replica 업그레이드 → 복제 시작·동기화 → 검증 후 개방. hotpatch는 별도 순서; 무조건 복제 정지하지 않음
cluster의 .pkg
3.22 cluster HA retirement 해결이 선행. 공식 cluster 절차는 primary MySQL 이외 노드 먼저, primary MySQL 마지막 → cluster config apply/status → 정상 시 개방. 일반 HA의 primary-first와 혼용 금지
patch 롤백
공식 --allow-patch-rollback은 이전 patch의 .pkg·재시작 등 조건이 있는 별도 변경. .hpkg나 feature downgrade 수단이 아니며 지원 문서·승인 없이 실행하지 않음
feature 실패
3.22 DB를 3.21에 그대로 붙이는 downgrade 금지. 공식 rollback은 변경 전 일관된 snapshot 복구. 디스크 snapshot은 같은 release의 새 인스턴스에 복원; 대안은 변경 전 백업으로 호환 새 대상 복구
복구 실행 순서
장애 선언·기존 primary 격리 → 승인된 snapshot/변경 전 백업 선택 → 외부 storage 시점 정합 → 격리 대상 복구·검증 → 손실 범위 승인 → DNS/LB 단일 쓰기 대상 전환. 실패 후 쓰기 손실은 별도 기록
미확인 사항을 남긴 채 통과시키지 않기
Backup Utilities 실제 제거/지원 상태, source 패치의 phased 옵션, 선택 artifact의 공개 checksum, 격리 Actions 복원 호환성, 3.22 replication-controller 복원 known issue 해결 여부는 실행 전 재확인 항목입니다. 조회한 문서는 업데이트될 수 있습니다. HA 자동화 문서의 순서와 package 절차가 다르면 임의 혼합하지 말고 선택한 토폴로지·버전의 공식 절차 및 지원 확인으로 변경계획을 확정합니다.
실제 GHES 버전, 정확한 대상 API/화면 경로, UTC와 시간대, 변경 전후·마지막 정상 시각, 영향 사용자 수와 정상/실패 차이, request/job/event ID, 비밀값을 뺀 응답, 이미 실행한 승인 변경. HAR·SAML assertion·토큰·쿠키·라이선스 파일은 일반 채팅이나 공개 티켓에 붙이지 않습니다.
Check item:
Target / installed version:
Operator / approver / UTC:
Expected result:
Observed result / event or request ID:
PASS / FAIL / NOT TESTED / N/A with reason:
Evidence location (restricted):
Approved change and recovery decision:
Owner / support case / next checkpoint:
판정: 비밀값은 제외하고 각 완료 조건의 실제 근거를 연결합니다.
부록 D. 공식 문서·이미지 출처
2026-09-19 기본 절차에 2026-09-21 운영상 주의점의 공식 근거를 보강한 참조 목록입니다.
기존 모든 기능을 새로 감사했다는 뜻은 아닙니다. 명령·UI는 해당 버전·권한에 맞춰 현장에서 검증해야 합니다.
개념도·공식 예제 화면은 실제 환경의 구성·성공 결과를 증명하지 않습니다.
공식 원문 출처https://docs.github.com/en/enterprise-server@3.21/billing/how-tos/manage-server-licenses/upload-new-license
공식 원문 출처https://learn.microsoft.com/en-us/entra/identity/saas-apps/github-enterprise-server-provisioning-tutorial
공식 원문 출처https://learn.microsoft.com/en-us/exchange/permissions-exo/application-rbac#new-service-principal
공식 원문 출처https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/assign-user-or-group-access-portal
공식 원문 출처https://learn.microsoft.com/en-us/entra/identity/saas-apps/github-enterprise-server-tutorial
GHES 3.21 SAML·SCIM 제품 기준https://docs.github.com/en/enterprise-server@3.21/admin/managing-iam/provisioning-user-accounts-with-scim/configuring-authentication-and-provisioning-with-entra-id
공식 원문 출처https://learn.microsoft.com/en-us/entra/identity/app-provisioning/provision-on-demand
공식 원문 출처https://learn.microsoft.com/en-us/entra/identity/monitoring-health/concept-provisioning-logs
공식 원문 출처https://docs.github.com/en/enterprise-server@3.21/admin/configuring-settings/configuring-github-connect/enabling-automatic-user-license-sync-for-your-enterprise
공식 원문 출처https://docs.github.com/en/enterprise-server@3.21/admin/managing-github-actions-for-your-enterprise/enabling-github-actions-for-github-enterprise-server/enabling-github-actions-with-azure-blob-storage
공식 원문 출처https://docs.github.com/en/enterprise-server@3.21/actions/how-tos/manage-runners/self-hosted-runners/add-runners
GHES 시스템 구조https://docs.github.com/en/enterprise-server@3.21/admin/overview/system-overview
Actions 최소 자원·외부 저장소https://docs.github.com/en/enterprise-server@3.21/admin/managing-github-actions-for-your-enterprise/getting-started-with-github-actions-for-your-enterprise/getting-started-with-github-actions-for-github-enterprise-server
관리 셸 지원 범위https://docs.github.com/en/enterprise-server@3.21/admin/administering-your-instance/administering-your-instance-from-the-command-line/accessing-the-administrative-shell-ssh
라이선스 파일https://docs.github.com/en/enterprise-server@3.21/billing/concepts/enterprise-billing/ghes-license-files
ghe-license info / checkhttps://docs.github.com/en/enterprise-server@3.21/admin/administering-your-instance/administering-your-instance-from-the-command-line/command-line-utilities#ghe-license
라이선스 GET APIhttps://docs.github.com/en/enterprise-server@3.21/rest/enterprise-admin/licensing#get-license-information
파일·PAYG 좌석 기준https://docs.github.com/en/billing/concepts/enterprise-billing/ghes-license-files
hostname 변경 경고https://docs.github.com/en/enterprise-server@3.21/admin/configuring-settings/configuring-network-settings/configuring-the-hostname-for-your-instance
DNS resolverhttps://docs.github.com/en/enterprise-server@3.21/admin/configuring-settings/configuring-network-settings/configuring-dns-nameservers
하위 도메인·SANhttps://docs.github.com/en/enterprise-server@3.21/admin/configuring-settings/hardening-security-for-your-enterprise/enabling-subdomain-isolation
Entra IP Rangeshttps://learn.microsoft.com/en-us/entra/identity/app-provisioning/use-scim-to-provision-users-and-groups#ip-ranges
Entra Test Connection·주기·온디맨드https://learn.microsoft.com/en-us/entra/identity/app-provisioning/use-scim-to-provision-users-and-groups#integrate-your-scim-endpoint-with-the-microsoft-entra-provisioning-service
Connect의 세 호스트·Cloud IP allowlisthttps://docs.github.com/en/enterprise-server@3.21/admin/configuring-settings/configuring-github-connect/enabling-github-connect-for-githubcom
3.21 기존 사용자 매칭https://docs.github.com/en/enterprise-server@3.21/admin/managing-iam/provisioning-user-accounts-with-scim/user-provisioning-with-scim-on-ghes
3.21 단일 쓰기 원천·가용 좌석https://docs.github.com/en/enterprise-server@3.21/admin/managing-iam/provisioning-user-accounts-with-scim/provisioning-users-and-groups-with-scim-using-the-rest-api
3.21 IdP 그룹과 조직 팀https://docs.github.com/en/enterprise-server@3.21/admin/managing-iam/provisioning-user-accounts-with-scim/managing-team-memberships-with-identity-provider-groups
3.21 CODEOWNERS 강제 조건https://docs.github.com/en/enterprise-server@3.21/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
3.21 보호 브랜치https://docs.github.com/en/enterprise-server@3.21/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches
3.21 연결 메타데이터의 주간 시각https://docs.github.com/en/enterprise-server@3.21/admin/configuring-settings/configuring-github-connect/about-github-connect#data-transmitted-when-github-connect-is-enabled
조직 감사 180일https://docs.github.com/en/enterprise-server@3.21/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/reviewing-the-audit-log-for-your-organization
Actions 외부 저장소https://docs.github.com/en/enterprise-server@3.21/admin/backing-up-and-restoring-your-instance/restoring-with-github-actions-enabled
HA 구조·트래픽https://docs.github.com/en/enterprise-server@3.21/admin/monitoring-and-managing-your-instance/configuring-high-availability/about-high-availability-configuration