오프라인 Self-Managed GitLab 인스턴스 설치

Tier: Free, Premium, Ultimate Offering: Self-Managed

이 가이드는 완전히 오프라인에서 Self-Managed GitLab을 설치, 구성 및 사용하는 데 도움이 되는 단계별 안내서입니다.

설치

note
이 가이드는 서버가 Ubuntu 20.04를 사용하고 있으며 Omnibus 설치 방법을 사용하고 있으며 GitLab Enterprise Edition이 실행 중이라고 가정합니다. 다른 서버에 대한 지침은 다를 수 있습니다. 또한, 이 가이드는 서버 호스트가 my-host.internal로 해결되고 영구 전송 레이어로 전달해야 할 패키지 파일을 다운로드할 수 있는 다른 서버에 대한 액세스가 있는 것으로 가정합니다.

이 프로세스의 비디오 설명은 오프라인 GitLab 설치: 다운로드 및 설치를 참조하세요.

GitLab 패키지 다운로드

당신은 로컬 네트워크 액세스가 없는 오프라인 환경인 경우 동일한 운영 체제 유형의 서버를 사용하여 수동으로 GitLab 패키지를 다운로드하고 관련 종속성을 다운로드해야 합니다.

Ubuntu에서는 다음 명령어를 사용하여 인터넷 액세스가 있는 서버에서 이를 수행할 수 있습니다.

# 리포지토리 준비를 위한 bash 스크립트 다운로드
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh" | sudo bash

# gitlab-ee 패키지 및 종속성 다운로드 /var/cache/apt/archives로
sudo apt-get install --download-only gitlab-ee

# apt 다운로드 폴더의 내용을 마운트된 미디어 장치로 복사
sudo cp /var/cache/apt/archives/*.deb /path/to/mount

GitLab 패키지 설치

선행 조건:

  • 오프라인 환경에 GitLab 패키지를 설치하기 전에 필요한 모든 종속성이 설치되었는지 확인하세요.

Ubuntu를 사용하는 경우에는 복사한 .deb 패키지를 dpkg를 사용하여 설치할 수 있습니다. 그러나 아직 GitLab 패키지를 설치하지 마십시오.

# 물리적 미디어 장치로 이동
sudo cd /path/to/mount

# 종속성 패키지 설치
sudo dpkg -i <package_name>.deb

패키지를 설치하는데 사용할 운영 체제에 따른 명령어를 사용하되, EXTERNAL_URL 설치 단계에 http URL을 지정해야 합니다. 한번 설치되면 SSL을 수동으로 구성할 수 있습니다.

서버의 IP 주소에 바인딩하는 대신 IP 해상도를 위한 도메인을 설정하는 것이 권장됩니다. 이렇게 함으로써 우리의 인증서 CN에 안정적인 대상을 확실하게 하고 장기적인 해상도를 더 간단하게 만들 수 있습니다.

다음 예시는 Ubuntu를 위한 EXTERNAL_URL을 HTTP를 사용하여 지정하고 GitLab 패키지를 설치합니다.

sudo EXTERNAL_URL="http://my-host.internal" dpkg -i <gitlab_package_name>.deb

SSL 활성화

당신의 새로운 인스턴스에 대해 SSL을 활성화하려면 다음 단계를 따르세요. 이러한 단계는 Omnibus의 NGINX 구성에서 SSL을 수동으로 구성하는 것을 반영합니다:

  1. /etc/gitlab/gitlab.rb를 다음과 같이 변경하세요:

    # external_url을 "http" 대신 "https"로 업데이트
    external_url "https://my-host.internal"
    
    # Let's Encrypt를 false로 설정
    letsencrypt['enable'] = false
    
  2. 자체 서명 인증서를 생성하기 위해 적절한 권한으로 다음 디렉토리를 생성하세요:

    sudo mkdir -p /etc/gitlab/ssl
    sudo chmod 755 /etc/gitlab/ssl
    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/gitlab/ssl/my-host.internal.key -out /etc/gitlab/ssl/my-host.internal.crt
    
  3. 변경 사항을 적용하기 위해 인스턴스를 다시 구성하세요:

    sudo gitlab-ctl reconfigure
    

GitLab 컨테이너 레지스트리 활성화

컨테이너 레지스트리를 활성화하려면 다음 단계를 따르세요. 이러한 단계는 기존 도메인에 컨테이너 레지스트리를 구성하는 것을 반영합니다:

  1. /etc/gitlab/gitlab.rb를 다음과 같이 변경하세요:

    # external_registry_url을 external_url과 일치하도록 변경하되 포트 4567을 추가하세요
    external_url "https://gitlab.example.com"
    registry_external_url "https://gitlab.example.com:4567"
    
  2. 변경 사항을 적용하기 위해 인스턴스를 다시 구성하세요:

    sudo gitlab-ctl reconfigure
    

Docker 데몬이 레지스트리와 GitLab Runner를 신뢰하도록 허용

도커 데몬에 여러분의 인증서를 제공하여 여러분의 레지스트리에 신뢰할 수 있는 인증서를 사용해야하는 단계를 따르세요 도커 레지스트리에 신뢰할 수 있는 인증서 사용에 대한 단계를 따르세요:

sudo mkdir -p /etc/docker/certs.d/my-host.internal:5000

sudo cp /etc/gitlab/ssl/my-host.internal.crt /etc/docker/certs.d/my-host.internal:5000/ca.crt

GitLab Runner에 여러분의 인증서를 제공하여 신뢰할 수 있는 인증서를 사용하여 GitLab Runner를 설치하는 단계를 따르세요:

sudo mkdir -p /etc/gitlab-runner/certs

sudo cp /etc/gitlab/ssl/my-host.internal.crt /etc/gitlab-runner/certs/ca.crt

GitLab Runner 활성화

우리의 GitLab Runner를 도커 서비스로 설치하는 단계를 따르면서, 먼저 우리의 러너를 등록해야합니다:

$ sudo docker run --rm -it -v /etc/gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner register
CA 인증서 업데이트 중...
런타임 플랫폼                                    arch=amd64 os=linux pid=7 revision=1b659122 version=12.8.0
시스템 모드에서 실행 중.

GitLab 인스턴스 URL을 입력하세요 (예: https://gitlab.com/):
https://my-host.internal
등록 토큰을 입력하세요:
XXXXXXXXXXX
러너에 대한 설명을 입력하세요:
[eb18856e13c0]:
러너에 태그를 입력하세요 (쉼표로 구분):
러너에 대한 선택적 유지 관리 노트를 입력하세요:

러너 등록 중... 성공                     runner=FSMwkvLZ
실행자(Executor)를 입력하세요: custom, docker, virtualbox, kubernetes, docker+machine, docker-ssh+machine, docker-ssh, parallels, shell, ssh:
docker
기본 Docker 이미지를 입력하세요 (예: ruby:2.6):
ruby:2.6
러너가 성공적으로 등록되었습니다. 이미 실행 중이라면 설정이 자동으로 다시 로드될 것입니다!

이제 우리는 러너에 몇 가지 추가적인 구성을 추가해야합니다:

/etc/gitlab-runner/config.toml를 다음과 같이 변경하세요:

  • 볼륨에 Docker 소켓 추가 volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
  • 실행자 구성에 pull_policy = "if-not-present" 추가

이제 러너를 시작할 수 있습니다:

sudo docker run -d --restart always --name gitlab-runner -v /etc/gitlab-runner:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
90646b6587127906a4ee3f2e51454c6e1f10f26fc7a0b03d9928d8d0d5897b64

호스트 OS에 대한 레지스트리 인증

Docker 레지스트리 인증 문서에 언급된 대로, 특정 버전의 Docker는 OS 수준에서 인증서 체인을 신뢰해야 합니다.

Ubuntu의 경우, 다음과 같이 update-ca-certificates를 사용해야 합니다:

sudo cp /etc/docker/certs.d/my-host.internal\:5000/ca.crt /usr/local/share/ca-certificates/my-host.internal.crt

sudo update-ca-certificates

모든 것이 잘 되면, 다음과 같은 것을 볼 수 있을 것입니다:

1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

버전 확인 및 서비스 핑 비활성화

버전 확인과 서비스 핑은 GitLab 사용자 경험을 향상시키고 사용자가 GitLab의 최신 인스턴스를 사용하도록 보장합니다. 이 두 서비스는 오프라인 환경에서 GitLab 서비스에 연결을 시도하고 실패하지 않도록 끌 수 있습니다.

자세한 정보는 서비스 핑을 활성화 또는 비활성화를 참조하세요.

러너 버전 관리 비활성화

러너 버전 관리는 GitLab에서 최신 러너 버전을 가져와 환경 내의 구식인 러너를 확인하기 위해 러너 버전 관리를 비활성화해야 합니다. 오프라인 환경에서는 러너 버전 관리를 비활성화해야 합니다.

NTP 구성

GitLab 15.4 및 15.5에서 Gitaly Cluster는 pool.ntp.org에 접근 가능하다고 가정합니다. pool.ntp.org에 접근할 수 없는 경우, Gitaly의 시간 서버 설정을 사용자 정의하여 Gitaly 및 Praefect 서버에서 접근 가능한 NTP 서버를 사용하도록 설정해야 합니다.

오프라인 인스턴스에서는 GitLab Geo 체크 Rake 작업이 항상 pool.ntp.org를 사용하므로 실패합니다. 이 오류를 무시할 수 있지만, 이를 해결하는 방법에 대해 더 읽을 수 있습니다.

패키지 메타데이터 데이터베이스 활성화

패키지 메타데이터 데이터베이스를 활성화하면 Continuous Vulnerability ScanningCycloneDX 파일의 라이선스 검사를 활성화하는 데 필요합니다. 이 프로세스에는 패키지 메타데이터 데이터베이스라는 총칭 내에서 라이선스 및/또는 고문 데이터 사용이 필요합니다. 이는 EE License에 따라 라이선스가 부여됩니다. 패키지 메타데이터 데이터베이스 사용과 관련된 다음 사항을 참고하세요:

  • 우리는 패키지 메타데이터 데이터베이스의 전부 또는 일부를 사전 통지 없이 언제든지 임의로 변경하거나 중단할 수 있습니다.
  • 패키지 메타데이터 데이터베이스에는 타사 웹사이트 또는 리소스로의 링크가 포함될 수 있습니다. 이러한 링크를 편의상만 제공하며 해당 웹사이트 또는 리소스에서 제공되는 타사 데이터, 콘텐츠, 제품 또는 서비스에 대해 책임지지 않습니다.
  • 패키지 메타데이터 데이터베이스는 일부 정보가 타사에 의해 제공된 정보를 기반으로 하며, GitLab은 제공된 콘텐츠의 정확성이나 완전성에 대한 책임이 없습니다.

패키지 메타데이터는 다음 Google Cloud Provider (GCP) 버킷에 저장됩니다:

  • 라이선스 스캔 - prod-export-license-bucket-1a6c642fc4de57d4
  • 의존성 스캔 - prod-export-advisory-bucket-1a6c642fc4de57d4

gsutil 도구를 사용하여 패키지 메타데이터 내보내기 다운로드

  1. gsutil 도구를 설치합니다.
  2. GitLab 레일즈 디렉토리의 루트를 찾습니다.

    export GITLAB_RAILS_ROOT_DIR="$(gitlab-rails runner 'puts Rails.root.to_s')"
    echo $GITLAB_RAILS_ROOT_DIR
    
  3. 동기화할 데이터 유형을 설정합니다.

    # 라이선스 스캔인 경우
    export PKG_METADATA_BUCKET=prod-export-license-bucket-1a6c642fc4de57d4
    export DATA_DIR="licenses"
    
    # 의존성 스캔인 경우
    export PKG_METADATA_BUCKET=prod-export-advisory-bucket-1a6c642fc4de57d4
    export DATA_DIR="advisories"
    
  4. 패키지 메타데이터 내보내기를 다운로드합니다.

    # 패키지 메타데이터 내보내기를 다운로드하려면 Google Cloud Storage 버킷으로의 아웃바운드 연결이 허용되어야 합니다.
    # -y "^v1\/"를 사용하여 v1 객체만 건너뛰어 v2 객체만 다운로드합니다. v1 데이터는 더 이상 사용되지 않으며 16.3부터 사용이 중지되었습니다.
    mkdir -p "$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/$DATA_DIR"
    gsutil -m rsync -r -d -y "^v1\/" gs://$PKG_METADATA_BUCKET "$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/$DATA_DIR"
    
    # 또는, GitLab 인스턴스가 Google Cloud Storage 버킷에 연결할 수 없는 경우, 패키지 메타데이터
    # 내보내기를 허용된 액세스를 가진 머신을 사용하여 다운로드한 다음, GitLab 레일즈 디렉토리의 루트로 복사할 수 있습니다.
    rsync rsync://example_username@gitlab.example.com/package_metadata/$DATA_DIR "$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/$DATA_DIR"
    

Google Cloud Storage REST API를 사용하여 패키지 메타데이터 내보내기 다운로드

패키지 메타데이터 내보내기는 Google Cloud Storage API를 사용하여 다운로드할 수도 있습니다. 콘텐츠는 https://storage.googleapis.com/storage/v1/b/prod-export-license-bucket-1a6c642fc4de57d4/ohttps://storage.googleapis.com/storage/v1/b/prod-export-advisory-bucket-1a6c642fc4de57d4/o에서 사용할 수 있습니다. 다음은 이를 cURLjq를 사용하여 다운로드하는 예제입니다.

#!/bin/bash

set -euo pipefail

DATA_TYPE=$1

GITLAB_RAILS_ROOT_DIR="$(gitlab-rails runner 'puts Rails.root.to_s')"

if [ "$DATA_TYPE" == "license" ]; then
  PKG_METADATA_DIR="$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/licenses"
elif [ "$DATA_TYPE" == "advisory" ]; then
  PKG_METADATA_DIR="$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/advisories"
else
  echo "사용법: import_script.sh [license|advisory]"
  exit 1
fi

PKG_METADATA_BUCKET="prod-export-$DATA_TYPE-bucket-1a6c642fc4de57d4"
PKG_METADATA_DOWNLOADS_OUTPUT_FILE="/tmp/package_metadata_${DATA_TYPE}_object_links.tsv"

# 버킷 콘텐츠 다운로드
# v2 객체만 다운로드하기 위해 `prefix=v2`를 사용하여 결과를 필터링합니다. v1 데이터는 더 이상 사용되지 않으며 16.3부터 사용이 중지되었습니다.
# 스크립트는 모든 객체를 다운로드하고 JSON 형식의 파일당 최대 1000개의 객체를 가진 파일을 생성합니다.

MAX_RESULTS=1000
TEMP_FILE="out.json"

curl --silent --show-error --request GET "https://storage.googleapis.com/storage/v1/b/$PKG_METADATA_BUCKET/o?maxResults=$MAX_RESULTS&prefix=v2%2f" >"$TEMP_FILE"
NEXT_PAGE_TOKEN="$(jq -r '.nextPageToken' $TEMP_FILE)"
jq -r '.items[] | [.name, .mediaLink] | @tsv' "$TEMP_FILE" >"$PKG_METADATA_DOWNLOADS_OUTPUT_FILE"

while [ "$NEXT_PAGE_TOKEN" != "null" ]; do
  curl --silent --show-error --request GET "https://storage.googleapis.com/storage/v1/b/$PKG_METADATA_BUCKET/o?maxResults=$MAX_RESULTS&pageToken=$NEXT_PAGE_TOKEN&prefix=v2%2f" >"$TEMP_FILE"
  NEXT_PAGE_TOKEN="$(jq -r '.nextPageToken' $TEMP_FILE)"
  jq -r '.items[] | [.name, .mediaLink] | @tsv' "$TEMP_FILE" >>"$PKG_METADATA_DOWNLOADS_OUTPUT_FILE"
  #API 속도 제한용
  sleep 1
done

trap 'rm -f "$TEMP_FILE"' EXIT

echo "$DATA_TYPE 내보내기 매니페스트 가져옴"

# 버킷 객체의 링크 및 이름을 추출하여 tsv 파일로 출력합니다.

echo -e "$PKG_METADATA_DIR에 패키지 메타데이터 내보내기 저장 중\n"

# 다운로드할 객체 수를 추적합니다
INDEX=1
TOTAL_OBJECT_COUNT="$(wc -l "$PKG_METADATA_DOWNLOADS_OUTPUT_FILE" | awk '{print $1}')"

# 객체 다운로드
while IFS= read -r line; do
  FILE="$(echo -n "$line" | awk '{print $1}')"
  URL="$(echo -n "$line" | awk '{print $2}')"
  OUTPUT_PATH="$PKG_METADATA_DIR/$FILE"

  echo "$FILE 다운로드 중"

  if [ ! -f "$OUTPUT_PATH" ]; then
    curl --progress-bar --create-dirs --output "$OUTPUT_PATH" --request "GET" "$URL"
  else
    echo "기존 파일이 발견되었습니다"
  fi

  echo -e "$INDEX$TOTAL_OBJECT_COUNT 객체 다운로드 완료\n"

  INDEX=$((INDEX + 1))
done <"$PKG_METADATA_DOWNLOADS_OUTPUT_FILE"

echo "모든 객체 $PKG_METADATA_DIR에 저장됨"

자동 동기화

귀하의 GitLab 인스턴스는 package_metadata 디렉터리의 내용과 정기적으로 동기화됩니다. 상위 변경 사항과 자동으로 동기화하려면 cron 작업을 추가하여 새로운 내보내기를 주기적으로 다운로드할 수 있습니다. 예를 들어, 매 30분마다 실행되는 cron 작업을 설정하기 위해 다음과 같은 크론탭을 추가할 수 있습니다.

라이선스 스캔에 대한 명령:

*/30 * * * * gsutil -m rsync -r -d -y "^v1\/" gs://prod-export-license-bucket-1a6c642fc4de57d4 $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/licenses

의존성 스캔에 대한 명령:

*/30 * * * * gsutil -m rsync -r -d gs://prod-export-advisory-bucket-1a6c642fc4de57d4 $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/advisories

변경 사항

16.2 버전의 릴리스로 인해 패키지 메타데이터 디렉터리가 vendor/package_metadata_db에서 vendor/package_metadata/licenses로 변경되었습니다. 이 디렉터리가 이미 인스턴스에 존재하고, 의존성 스캔을 추가해야 하는 경우 다음 단계를 수행해야 합니다.

  1. 라이선스 디렉터리의 이름 변경: mv vendor/package_metadata_db vendor/package_metadata/licenses.
  2. vendor/package_metadata_dbvendor/package_metadata/licenses로 변경하는 자동화 스크립트 또는 명령을 업데이트합니다.
  3. vendor/package_metadata_dbvendor/package_metadata/licenses로 변경하는 크론 항목을 업데이트합니다.

    sed -i '.bckup' -e 's#vendor/package_metadata_db#vendor/package_metadata/licenses#g' [FILE ...]
    

문제 해결

누락된 데이터베이스 데이터

라이선스 또는 지원 데이터가 의존성 목록 또는 MR 페이지에서 누락된 경우, 이는 데이터베이스가 내보낸 데이터와 동기화되지 않은 경우의 하나의 가능한 원인입니다.

package_metadata 동기화는 크론 작업을 사용하여 트리거되며(지원 데이터 동기화라이선스 동기화) 관리자 설정에서 활성화된 패키지 레지스트리 유형 만 가져옵니다(관리 설정).

vendor/package_metadata의 파일 구조는 위에서 활성화된 패키지 레지스트리 유형과 일치해야 합니다. 예를 들어, maven 라이선스 또는 지원 데이터를 동기화하려면 Rails 디렉터리 하위의 패키지 메타데이터 디렉토리는 다음 구조를 가져야 합니다:

  • 라이선스에 대해서:$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/licenses/v2/maven/**/*.ndjson.
  • 지원에 대해서:$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/advisories/v2/maven/**/*.ndjson.

성공적인 실행 후, 데이터베이스의 pm_ 테이블 아래의 데이터가 채워져 있어야 합니다 (Rails console을 사용하여 확인):

  • 라이선스에 대해: sudo gitlab-rails runner "puts \"패키지 모델에 #{PackageMetadata::Package.where(purl_type: 'maven').size}개의 패키지가 있습니다\""
  • 지원에 대해: sudo gitlab-rails runner "puts \"지원 모델에 #{PackageMetadata::AffectedPackage.where(purl_type: 'maven').size}개의 패키지가 있습니다\""

또한, 동기화 작업이 끝난 후 특정 패키지 레지스트리에 대해 체크포인트 데이터가 있어야 합니다. 예를 들어, Maven의 경우, 성공적인 동기화 실행 후 체크포인트가 생성되어 있어야 합니다:

  • 라이선스에 대해: sudo gitlab-rails runner "puts \"maven 데이터가 #{PackageMetadata::Checkpoint.where(data_type: 'licenses', purl_type: 'maven')} 까지 동기화되었습니다\""
  • 지원에 대해: sudo gitlab-rails runner "puts \"maven 데이터가 #{PackageMetadata::Checkpoint.where(data_type: 'advisories', purl_type: 'maven')} 까지 동기화되었습니다\""

마지막으로, application_json.log 로그를 확인하여 동기화 작업이 오류 없이 실행되었는지 PackageMetadata::SyncService 클래스가 DEBUG 메시지를 통해 검색할 수 있습니다. 예: {"severity":"DEBUG","time":"2023-06-22T16:41:00.825Z","correlation_id":"a6e80150836b4bb317313a3fe6d0bbd6","class":"PackageMetadata::SyncService","message":"라이선스:gcp/prod-export-license-bucket-1a6c642fc4de57d4/v2/pypi/1694703741/0.ndjson"}.