정적 객체의 외부 리포지터리

등급: Free, Premium, Ultimate 제공: Self-managed

GitLab을 구성하여 아카이브 또는 원시 블롭과 같은 리포지터리 정적 객체를 외부 리포지터리(콘텐츠 전달 네트워크, CDN 같은)에서 제공하도록 설정합니다.

외부 리포지터리 구성

정적 객체를 위한 외부 리포지터리를 구성하려면 다음 단계를 따릅니다:

  1. 왼쪽 사이드바에서 맨 아래에서 관리 영역(Admin Area)를 선택합니다.
  2. 설정 > 리포지터리를 선택합니다.
  3. 리포지터리 정적 객체의 외부 리포지터리를 확장합니다.
  4. 기본 URL과 임의의 토큰을 입력합니다. 외부 리포지터리를 설정할 때, 이 두 값을 ORIGIN_HOSTNAMESTORAGE_TOKEN으로 설정하는 스크립트를 사용합니다.
  5. 변경 사항 저장을 선택합니다.

사용자가 외부 리포지터리를 우회하고 애플리케이션에 직접 액세스하지 못하도록 하기 위해 토큰이 필요하며, GitLab은 외부 리포지터리에서의 요청에서 이 토큰이 X-Gitlab-External-Storage-Token 헤더에 설정되어 있기를 기대합니다.

개인 정적 객체 제공

GitLab은 개인 프로젝트에 속하는 정적 객체 URL에 대해 사용자별 토큰을 추가하여, 외부 리포지터리가 사용자를 대신하여 인증될 수 있도록 합니다.

외부 리포지터리에서 시작된 요청을 처리할 때, GitLab은 사용자가 요청한 객체에 액세스할 수 있는지를 확인하기 위해 다음을 확인합니다:

  • token 쿼리 매개변수
  • X-Gitlab-Static-Object-Token 헤더

요청 흐름 예제

다음 예시는 다음 간의 요청 및 응답의 일련의 순서를 보여줍니다:

  • 사용자
  • GitLab
  • 콘텐츠 전달 네트워크
sequenceDiagram 사용자->>GitLab: GET /project/-/archive/master.zip GitLab->>사용자: 302 Found Note over 사용자, GitLab: 위치: https://cdn.com/project/-/archive/master.zip?token=secure-user-token 사용자->>CDN: GET /project/-/archive/master.zip?token=secure-user-token alt 캐시에 객체 없음 CDN->>GitLab: GET /project/-/archive/master.zip Note over CDN, GitLab: X-Gitlab-External-Storage-Token: secure-cdn-token<br/>X-Gitlab-Static-Object-Token: secure-user-token GitLab->>CDN: 200 OK CDN->>사용자: master.zip else 캐시에 객체 있음 CDN->>GitLab: GET /project/-/archive/master.zip Note over CDN, GitLab: X-Gitlab-External-Storage-Token: secure-cdn-token<br/>X-Gitlab-Static-Object-Token: secure-user-token<br/>If-None-Match: etag-value GitLab->>CDN: 304 Not Modified CDN->>사용자: master.zip end

외부 리포지터리 설정

이 절차는 외부 리포지터리로 Cloudflare Workers를 사용하지만, 다른 CDN 또는 함수 서비스(FaaS) 시스템도 동일한 원칙을 사용하여 작동할 수 있습니다.

  1. 아직 진행하지 않은 경우 Cloudflare Worker 도메인을 선택합니다.
  2. 다음 스크립트에서 첫 번째 두 상수에 대한 다음 값을 설정합니다:

    • ORIGIN_HOSTNAME: GitLab 설치의 호스트 이름.
    • STORAGE_TOKEN: 임의의 안전한 토큰. UNIX 기반 시스템에서 pwgen -cn1 64를 실행하여 토큰을 얻을 수 있습니다. 이 토큰은 정적 객체용 외부 리포지터리를 구성하는 방법에 설명된 대로 Admin 영역에 저장합니다.

      const ORIGIN_HOSTNAME = 'gitlab.installation.com' // FIXME: 올바른 값으로 설정
      const STORAGE_TOKEN = 'very-secure-token' // FIXME: 올바른 값으로 설정
      const CACHE_PRIVATE_OBJECTS = false
           
      const CORS_HEADERS = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
        'Access-Control-Allow-Headers': 'X-Csrf-Token, X-Requested-With',
      }
           
      self.addEventListener('fetch', event => event.respondWith(handle(event)))
           
      async function handle(event) {
        try {
          let response = await verifyAndHandle(event);
               
          // 캐시에서 반환된 응답은 불변이므로 CORS 헤더를 설정하기 위해 다시 생성합니다
          response = new Response(response.body, response)
          response.headers.set('Access-Control-Allow-Origin', '*')
               
          return response
        } catch (e) {
          return new Response('An error occurred!', {status: e.statusCode || 500})
        }
      }
      ...
      
  3. 이 스크립트로 새 워커를 만듭니다.
  4. ORIGIN_HOSTNAMESTORAGE_TOKEN의 값을 복사합니다. 이 값을 정적 객체용 외부 리포지터리를 구성하는 데 사용합니다.