InfoGrab Docs

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

요약

이것은 GitLab Self-Managed 인스턴스를 완전히 오프라인으로 설치, 구성 및 사용하는 데 도움이 되는 단계별 가이드입니다. 이 가이드는 서버가 Linux 패키지 설치 방법을 사용하는 Ubuntu 20.04이고 GitLab Enterprise Edition을 실행한다고 가정합니다.

이것은 GitLab Self-Managed 인스턴스를 완전히 오프라인으로 설치, 구성 및 사용하는 데 도움이 되는 단계별 가이드입니다.

설치#

Note

이 가이드는 서버가 Linux 패키지 설치 방법을 사용하는 Ubuntu 20.04이고 GitLab Enterprise Edition을 실행한다고 가정합니다. 다른 서버의 경우 지침이 다를 수 있습니다. 이 가이드는 또한 서버 호스트가 my-host.internal로 해석된다고 가정합니다. 이를 서버의 FQDN으로 교체하고, 필요한 패키지 파일을 다운로드하기 위해 인터넷에 액세스할 수 있는 다른 서버에 액세스할 수 있다고 가정합니다.

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

GitLab 패키지 다운로드#

인터넷에 접근할 수 있는 동일한 운영 체제 유형의 서버를 사용하여 GitLab 패키지와 관련 의존성을 다운로드해야 합니다.

오프라인 환경에 로컬 네트워크 액세스가 없는 경우 USB 드라이브와 같은 물리적 미디어를 통해 관련 패키지를 수동으로 전송해야 합니다.

Ubuntu에서 이 작업은 인터넷에 접근할 수 있는 서버에서 다음 명령을 사용하여 수행할 수 있습니다:

# Download the bash script to prepare the repository
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh" | sudo bash

# Download the gitlab-ee package and dependencies to /var/cache/apt/archives
sudo apt-get install --download-only gitlab-ee

# Copy the contents of the apt download folder to a mounted media device
sudo cp /var/cache/apt/archives/*.deb /path/to/mount

GitLab 패키지 설치#

필수 조건:

  • 오프라인 환경에 GitLab 패키지를 설치하기 전에 먼저 필요한 모든 의존성을 설치했는지 확인합니다.

Ubuntu를 사용하는 경우 복사한 의존성 .deb 패키지를 dpkg로 설치할 수 있습니다. 아직 GitLab 패키지를 설치하지 마세요.

# Go to the physical media device
sudo cd /path/to/mount

# Install the dependency packages
sudo dpkg -i <package_name>.deb

운영 체제에 맞는 관련 명령을 사용하여 패키지를 설치하되 EXTERNAL_URL 설치 단계에 http URL을 지정해야 합니다. 설치 후 수동으로 SSL을 구성할 수 있습니다.

서버의 IP 주소에 바인딩하는 것보다 IP 확인을 위한 도메인을 설정해야 합니다. 도메인은 인증서의 CN(Common Name)을 위한 안정적인 대상을 제공하고 장기적인 확인을 단순화합니다.

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

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

SSL 활성화#

새 인스턴스에 SSL을 활성화하려면 다음 단계를 따르세요. 이 단계는 NGINX 구성에서 수동으로 SSL을 구성하는 단계를 반영합니다:

  1. /etc/gitlab/gitlab.rb를 다음과 같이 변경합니다:

    # Update external_url from "http" to "https"
    external_url "https://my-host.internal"
    
    # Set Let's Encrypt to 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를 다음과 같이 변경합니다:

    # Change external_registry_url to match external_url, but append the port 4567
    external_url "https://gitlab.example.com"
    registry_external_url "https://gitlab.example.com:4567"
    
  2. 변경 사항을 적용하기 위해 인스턴스를 재구성합니다:

    sudo gitlab-ctl reconfigure
    

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

레지스트리와 함께 신뢰할 수 있는 인증서를 사용하는 단계에 따라 Docker 데몬에 인증서를 제공합니다:

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

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를 Docker 서비스로 설치하는 단계와 유사한 프로세스에 따라 먼저 Runner를 등록해야 합니다:

$ sudo docker run --rm -it -v /etc/gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner register
Updating CA certificates...
Runtime platform                                    arch=amd64 os=linux pid=7 revision=1b659122 version=12.8.0
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://my-host.internal
Enter the registration token:
XXXXXXXXXXX
Enter a description for the runner:
[eb18856e13c0]:
Enter tags for the runner (comma-separated):
Enter optional maintenance note for the runner:

Registering runner... succeeded                     runner=FSMwkvLZ
Please enter the executor: custom, docker, virtualbox, kubernetes, docker+machine, docker-ssh+machine, docker-ssh, parallels, shell, ssh:
docker
Please enter the default Docker image (for example, ruby:2.6):
ruby:2.6
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

다음으로 Runner에 몇 가지 추가 구성을 추가해야 합니다.

/etc/gitlab-runner/config.toml을 다음과 같이 변경합니다:

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

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

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 서비스에 연결을 시도하고 실패하지 않도록 비활성화할 수 있습니다.

자세한 내용은 서비스 핑 활성화 또는 비활성화를 참조하세요.

Runner 버전 관리 비활성화#

Runner 버전 관리는 GitLab에서 최신 Runner 버전을 가져와 환경의 어떤 Runner가 오래되었는지 확인합니다. 오프라인 환경에서는 Runner 버전 관리를 비활성화해야 합니다.

NTP 구성#

Gitaly 클러스터(Praefect)는 pool.ntp.org에 액세스할 수 있다고 가정합니다. pool.ntp.org에 액세스할 수 없는 경우 Gitaly 및 Praefect 서버에서 시간 서버 설정을 커스터마이즈하여 액세스 가능한 NTP 서버를 사용할 수 있습니다.

오프라인 인스턴스에서 GitLab Geo 확인 Rake 작업pool.ntp.org를 사용하기 때문에 항상 실패합니다. 이 오류는 무시할 수 있지만 해결 방법에 대해 자세히 알아볼 수 있습니다.

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

패키지 메타데이터 데이터베이스를 활성화하면 지속적 취약성 스캔CycloneDX 파일의 라이선스 스캔을 활성화할 수 있습니다. 이 프로세스에는 패키지 메타데이터 데이터베이스라고 통칭하는 라이선스 및/또는 어드바이저리 데이터의 사용이 필요하며, EE 라이선스에 따라 라이선스가 부여됩니다. 패키지 메타데이터 데이터베이스 사용과 관련하여 다음 사항에 유의하세요:

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

패키지 메타데이터는 GitLab이 유지 관리하고 소유한 다음 Google Cloud Provider(GCP) 버킷에 저장됩니다:

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

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

  1. gsutil 도구를 설치합니다.

  2. GitLab Rails 디렉토리의 루트를 찾습니다.

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

    # For License Scanning
    export PKG_METADATA_BUCKET=prod-export-license-bucket-1a6c642fc4de57d4
    export DATA_DIR="licenses"
    
    # For dependency scanning
    export PKG_METADATA_BUCKET=prod-export-advisory-bucket-1a6c642fc4de57d4
    export DATA_DIR="advisories"
    
  4. 패키지 메타데이터 내보내기를 다운로드합니다.

    # To download the package metadata exports, an outbound connection to Google Cloud Storage bucket must be allowed.
    mkdir -p "$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/$DATA_DIR"
    gsutil -m rsync -r -d gs://$PKG_METADATA_BUCKET "$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/$DATA_DIR"
    
    # Alternatively, if the GitLab instance is not allowed to connect to the Google Cloud Storage bucket, the package metadata
    # exports can be downloaded using a machine with the allowed access, and then copied to the root of the GitLab Rails directory.
    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 "Usage: 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"

# Download the contents of the bucket
# The script downloads all the objects and creates files with a maximum 1000 objects per file in JSON format.

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" >"$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" >"$TEMP_FILE"
  NEXT_PAGE_TOKEN="$(jq -r '.nextPageToken' $TEMP_FILE)"
  jq -r '.items[] | [.name, .mediaLink] | @tsv' "$TEMP_FILE" >>"$PKG_METADATA_DOWNLOADS_OUTPUT_FILE"
  #use for API rate-limiting
  sleep 1
done

trap 'rm -f "$TEMP_FILE"' EXIT

echo "Fetched $DATA_TYPE export manifest"

# Parse the links and names for the bucket objects and output them into a tsv file

echo -e "Saving package metadata exports to $PKG_METADATA_DIR\n"

# Track how many objects will be downloaded
INDEX=1
TOTAL_OBJECT_COUNT="$(wc -l "$PKG_METADATA_DOWNLOADS_OUTPUT_FILE" | awk '{print $1}')"

# Download the objects
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 "Downloading $FILE"

  if [ ! -f "$OUTPUT_PATH" ]; then
    curl --progress-bar --create-dirs --output "$OUTPUT_PATH" --request "GET" "$URL"
  else
    echo "Existing file found"
  fi

  echo -e "$INDEX of $TOTAL_OBJECT_COUNT objects downloaded\n"

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

echo "All objects saved to $PKG_METADATA_DIR"

자동 동기화#

GitLab 인스턴스는 package_metadata 디렉토리의 내용과 정기적으로 동기화됩니다. 업스트림 변경 사항으로 로컬 복사본을 자동으로 업데이트하려면 새 내보내기를 주기적으로 다운로드하도록 cron 작업을 추가할 수 있습니다. 예를 들어 다음 crontab을 추가하여 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. cron 항목을 업데이트하여 vendor/package_metadata_dbvendor/package_metadata/licenses로 변경합니다.

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

트러블슈팅#

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

라이선스 또는 어드바이저리 데이터가 의존성 목록, 취약성 보고서 또는 머지 리퀘스트 페이지에서 누락된 경우 데이터베이스가 내보내기 데이터와 동기화되지 않았을 수 있습니다.

활성화된 패키지 레지스트리 유형 확인#

package_metadata 동기화는 cron 작업(어드바이저리 동기화라이선스 동기화)을 사용하여 트리거됩니다. 관리자 설정에서 활성화된 패키지 레지스트리 유형만 가져옵니다.

예를 들어, maven이 선택되었지만 golang이 선택되지 않은 경우 Maven에 대한 어드바이저리 및 라이선스 정보만 볼 수 있습니다.

올바른 파일 구조 확인#

vendor/package_metadata의 파일 구조는 이전에 활성화된 패키지 레지스트리 유형과 일치해야 합니다. 예를 들어 maven 라이선스 또는 어드바이저리 데이터를 동기화하려면 Rails 디렉토리 아래의 패키지 메타데이터 디렉토리는 $GITLAB_RAILS_ROOT_DIRgitlab-rails runner 'puts Rails.root.to_s' 명령의 출력과 일치하는 다음 구조를 가져야 합니다:

  • 라이선스의 경우: $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/licenses/v2/maven/**/*.ndjson.
  • 어드바이저리의 경우: $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/advisories/v2/maven/**/*.ndjson.

Rails 콘솔에서 GitLab이 파일 경로를 인식하는지 확인할 수 있습니다:

  • 라이선스의 경우: sudo gitlab-rails runner "puts File.exist?(PackageMetadata::SyncConfiguration::Location::LICENSES_PATH)"
  • 어드바이저리의 경우: sudo gitlab-rails runner "puts File.exist?(PackageMetadata::SyncConfiguration::Location::ADVISORIES_PATH)"

위 명령이 false를 반환하면 GitLab이 예상 패키지 경로를 찾을 수 없습니다. 경로의 모든 폴더와 파일에는 755 권한이 있어야 합니다. 권한을 업데이트하려면:

sudo chmod -R 755 $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/

데이터 확인#

동기화 작업이 성공적으로 실행된 후 데이터베이스의 pm_ 테이블 아래에 데이터가 채워져야 합니다.

Rails 콘솔을 사용하여 공급업체별로 존재하는 패키지 수를 확인할 수 있습니다. 예를 들어 Maven 라이선스 및 어드바이저리 데이터가 로드되었는지 확인하려면 다음을 실행합니다:

  • 라이선스의 경우: sudo gitlab-rails runner "puts \"Package model has #{PackageMetadata::Package.where(purl_type: 'maven').size} packages\""
  • 어드바이저리의 경우: sudo gitlab-rails runner "puts \"Advisory model has #{PackageMetadata::AffectedPackage.where(purl_type: 'maven').size} packages\""

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

  • 라이선스의 경우: sudo gitlab-rails runner "puts \"maven data has been synced up to #{PackageMetadata::Checkpoint.where(data_type: 'licenses', purl_type: 'maven')}\""
  • 어드바이저리의 경우: sudo gitlab-rails runner "puts \"maven data has been synced up to #{PackageMetadata::Checkpoint.where(data_type: 'advisories', purl_type: 'maven')}\""
로그#

application_json.log 파일은 동기화 작업이 실행되었고 오류가 없는지 확인하는 데 도움이 됩니다. 동기화와 관련된 이벤트의 심각도는 DEBUG이고 클래스는 PackageMetadata::SyncService입니다. 예시: {"severity":"DEBUG","time":"2026-01-07T02:15:49.618Z","meta.caller_id":"PackageMetadata::AdvisoriesSyncWorker","correlation_id":"43008e30dd708eadbe1ab16ad7fa953f","meta.root_caller_id":"Cronjob","meta.feature_category":"software_composition_analysis","meta.client_id":"ip/","class":"PackageMetadata::SyncService","message":"Evaluating data for advisories:offline//opt/gitlab/embedded/service/gitlab-rails/vendor/package_metadata/advisories/v2/maven/1761761049/0.ndjson"}

sidekiq 로그는 동기화 작업 중에 오류가 발생했는지 표시합니다. 동기화에 대해 기록된 이벤트는 관련 클래스를 언급합니다:

  • 라이선스의 경우: PackageMetadata::LicensesSyncWorker
  • 어드바이저리의 경우: PackageMetadata::AdvisoriesSyncWorker

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

Tier: Free, Premium, Ultimate
Offering: GitLab Self-Managed
원문 보기
요약

이것은 GitLab Self-Managed 인스턴스를 완전히 오프라인으로 설치, 구성 및 사용하는 데 도움이 되는 단계별 가이드입니다. 이 가이드는 서버가 Linux 패키지 설치 방법을 사용하는 Ubuntu 20.04이고 GitLab Enterprise Edition을 실행한다고 가정합니다.

이것은 GitLab Self-Managed 인스턴스를 완전히 오프라인으로 설치, 구성 및 사용하는 데 도움이 되는 단계별 가이드입니다.

설치#

Note

이 가이드는 서버가 Linux 패키지 설치 방법을 사용하는 Ubuntu 20.04이고 GitLab Enterprise Edition을 실행한다고 가정합니다. 다른 서버의 경우 지침이 다를 수 있습니다. 이 가이드는 또한 서버 호스트가 my-host.internal로 해석된다고 가정합니다. 이를 서버의 FQDN으로 교체하고, 필요한 패키지 파일을 다운로드하기 위해 인터넷에 액세스할 수 있는 다른 서버에 액세스할 수 있다고 가정합니다.

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

GitLab 패키지 다운로드#

인터넷에 접근할 수 있는 동일한 운영 체제 유형의 서버를 사용하여 GitLab 패키지와 관련 의존성을 다운로드해야 합니다.

오프라인 환경에 로컬 네트워크 액세스가 없는 경우 USB 드라이브와 같은 물리적 미디어를 통해 관련 패키지를 수동으로 전송해야 합니다.

Ubuntu에서 이 작업은 인터넷에 접근할 수 있는 서버에서 다음 명령을 사용하여 수행할 수 있습니다:

# Download the bash script to prepare the repository
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh" | sudo bash

# Download the gitlab-ee package and dependencies to /var/cache/apt/archives
sudo apt-get install --download-only gitlab-ee

# Copy the contents of the apt download folder to a mounted media device
sudo cp /var/cache/apt/archives/*.deb /path/to/mount

GitLab 패키지 설치#

필수 조건:

  • 오프라인 환경에 GitLab 패키지를 설치하기 전에 먼저 필요한 모든 의존성을 설치했는지 확인합니다.

Ubuntu를 사용하는 경우 복사한 의존성 .deb 패키지를 dpkg로 설치할 수 있습니다. 아직 GitLab 패키지를 설치하지 마세요.

# Go to the physical media device
sudo cd /path/to/mount

# Install the dependency packages
sudo dpkg -i <package_name>.deb

운영 체제에 맞는 관련 명령을 사용하여 패키지를 설치하되 EXTERNAL_URL 설치 단계에 http URL을 지정해야 합니다. 설치 후 수동으로 SSL을 구성할 수 있습니다.

서버의 IP 주소에 바인딩하는 것보다 IP 확인을 위한 도메인을 설정해야 합니다. 도메인은 인증서의 CN(Common Name)을 위한 안정적인 대상을 제공하고 장기적인 확인을 단순화합니다.

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

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

SSL 활성화#

새 인스턴스에 SSL을 활성화하려면 다음 단계를 따르세요. 이 단계는 NGINX 구성에서 수동으로 SSL을 구성하는 단계를 반영합니다:

  1. /etc/gitlab/gitlab.rb를 다음과 같이 변경합니다:

    # Update external_url from "http" to "https"
    external_url "https://my-host.internal"
    
    # Set Let's Encrypt to 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를 다음과 같이 변경합니다:

    # Change external_registry_url to match external_url, but append the port 4567
    external_url "https://gitlab.example.com"
    registry_external_url "https://gitlab.example.com:4567"
    
  2. 변경 사항을 적용하기 위해 인스턴스를 재구성합니다:

    sudo gitlab-ctl reconfigure
    

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

레지스트리와 함께 신뢰할 수 있는 인증서를 사용하는 단계에 따라 Docker 데몬에 인증서를 제공합니다:

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

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를 Docker 서비스로 설치하는 단계와 유사한 프로세스에 따라 먼저 Runner를 등록해야 합니다:

$ sudo docker run --rm -it -v /etc/gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner register
Updating CA certificates...
Runtime platform                                    arch=amd64 os=linux pid=7 revision=1b659122 version=12.8.0
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://my-host.internal
Enter the registration token:
XXXXXXXXXXX
Enter a description for the runner:
[eb18856e13c0]:
Enter tags for the runner (comma-separated):
Enter optional maintenance note for the runner:

Registering runner... succeeded                     runner=FSMwkvLZ
Please enter the executor: custom, docker, virtualbox, kubernetes, docker+machine, docker-ssh+machine, docker-ssh, parallels, shell, ssh:
docker
Please enter the default Docker image (for example, ruby:2.6):
ruby:2.6
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

다음으로 Runner에 몇 가지 추가 구성을 추가해야 합니다.

/etc/gitlab-runner/config.toml을 다음과 같이 변경합니다:

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

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

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 서비스에 연결을 시도하고 실패하지 않도록 비활성화할 수 있습니다.

자세한 내용은 서비스 핑 활성화 또는 비활성화를 참조하세요.

Runner 버전 관리 비활성화#

Runner 버전 관리는 GitLab에서 최신 Runner 버전을 가져와 환경의 어떤 Runner가 오래되었는지 확인합니다. 오프라인 환경에서는 Runner 버전 관리를 비활성화해야 합니다.

NTP 구성#

Gitaly 클러스터(Praefect)는 pool.ntp.org에 액세스할 수 있다고 가정합니다. pool.ntp.org에 액세스할 수 없는 경우 Gitaly 및 Praefect 서버에서 시간 서버 설정을 커스터마이즈하여 액세스 가능한 NTP 서버를 사용할 수 있습니다.

오프라인 인스턴스에서 GitLab Geo 확인 Rake 작업pool.ntp.org를 사용하기 때문에 항상 실패합니다. 이 오류는 무시할 수 있지만 해결 방법에 대해 자세히 알아볼 수 있습니다.

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

패키지 메타데이터 데이터베이스를 활성화하면 지속적 취약성 스캔CycloneDX 파일의 라이선스 스캔을 활성화할 수 있습니다. 이 프로세스에는 패키지 메타데이터 데이터베이스라고 통칭하는 라이선스 및/또는 어드바이저리 데이터의 사용이 필요하며, EE 라이선스에 따라 라이선스가 부여됩니다. 패키지 메타데이터 데이터베이스 사용과 관련하여 다음 사항에 유의하세요:

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

패키지 메타데이터는 GitLab이 유지 관리하고 소유한 다음 Google Cloud Provider(GCP) 버킷에 저장됩니다:

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

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

  1. gsutil 도구를 설치합니다.

  2. GitLab Rails 디렉토리의 루트를 찾습니다.

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

    # For License Scanning
    export PKG_METADATA_BUCKET=prod-export-license-bucket-1a6c642fc4de57d4
    export DATA_DIR="licenses"
    
    # For dependency scanning
    export PKG_METADATA_BUCKET=prod-export-advisory-bucket-1a6c642fc4de57d4
    export DATA_DIR="advisories"
    
  4. 패키지 메타데이터 내보내기를 다운로드합니다.

    # To download the package metadata exports, an outbound connection to Google Cloud Storage bucket must be allowed.
    mkdir -p "$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/$DATA_DIR"
    gsutil -m rsync -r -d gs://$PKG_METADATA_BUCKET "$GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/$DATA_DIR"
    
    # Alternatively, if the GitLab instance is not allowed to connect to the Google Cloud Storage bucket, the package metadata
    # exports can be downloaded using a machine with the allowed access, and then copied to the root of the GitLab Rails directory.
    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 "Usage: 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"

# Download the contents of the bucket
# The script downloads all the objects and creates files with a maximum 1000 objects per file in JSON format.

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" >"$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" >"$TEMP_FILE"
  NEXT_PAGE_TOKEN="$(jq -r '.nextPageToken' $TEMP_FILE)"
  jq -r '.items[] | [.name, .mediaLink] | @tsv' "$TEMP_FILE" >>"$PKG_METADATA_DOWNLOADS_OUTPUT_FILE"
  #use for API rate-limiting
  sleep 1
done

trap 'rm -f "$TEMP_FILE"' EXIT

echo "Fetched $DATA_TYPE export manifest"

# Parse the links and names for the bucket objects and output them into a tsv file

echo -e "Saving package metadata exports to $PKG_METADATA_DIR\n"

# Track how many objects will be downloaded
INDEX=1
TOTAL_OBJECT_COUNT="$(wc -l "$PKG_METADATA_DOWNLOADS_OUTPUT_FILE" | awk '{print $1}')"

# Download the objects
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 "Downloading $FILE"

  if [ ! -f "$OUTPUT_PATH" ]; then
    curl --progress-bar --create-dirs --output "$OUTPUT_PATH" --request "GET" "$URL"
  else
    echo "Existing file found"
  fi

  echo -e "$INDEX of $TOTAL_OBJECT_COUNT objects downloaded\n"

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

echo "All objects saved to $PKG_METADATA_DIR"

자동 동기화#

GitLab 인스턴스는 package_metadata 디렉토리의 내용과 정기적으로 동기화됩니다. 업스트림 변경 사항으로 로컬 복사본을 자동으로 업데이트하려면 새 내보내기를 주기적으로 다운로드하도록 cron 작업을 추가할 수 있습니다. 예를 들어 다음 crontab을 추가하여 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. cron 항목을 업데이트하여 vendor/package_metadata_dbvendor/package_metadata/licenses로 변경합니다.

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

트러블슈팅#

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

라이선스 또는 어드바이저리 데이터가 의존성 목록, 취약성 보고서 또는 머지 리퀘스트 페이지에서 누락된 경우 데이터베이스가 내보내기 데이터와 동기화되지 않았을 수 있습니다.

활성화된 패키지 레지스트리 유형 확인#

package_metadata 동기화는 cron 작업(어드바이저리 동기화라이선스 동기화)을 사용하여 트리거됩니다. 관리자 설정에서 활성화된 패키지 레지스트리 유형만 가져옵니다.

예를 들어, maven이 선택되었지만 golang이 선택되지 않은 경우 Maven에 대한 어드바이저리 및 라이선스 정보만 볼 수 있습니다.

올바른 파일 구조 확인#

vendor/package_metadata의 파일 구조는 이전에 활성화된 패키지 레지스트리 유형과 일치해야 합니다. 예를 들어 maven 라이선스 또는 어드바이저리 데이터를 동기화하려면 Rails 디렉토리 아래의 패키지 메타데이터 디렉토리는 $GITLAB_RAILS_ROOT_DIRgitlab-rails runner 'puts Rails.root.to_s' 명령의 출력과 일치하는 다음 구조를 가져야 합니다:

  • 라이선스의 경우: $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/licenses/v2/maven/**/*.ndjson.
  • 어드바이저리의 경우: $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/advisories/v2/maven/**/*.ndjson.

Rails 콘솔에서 GitLab이 파일 경로를 인식하는지 확인할 수 있습니다:

  • 라이선스의 경우: sudo gitlab-rails runner "puts File.exist?(PackageMetadata::SyncConfiguration::Location::LICENSES_PATH)"
  • 어드바이저리의 경우: sudo gitlab-rails runner "puts File.exist?(PackageMetadata::SyncConfiguration::Location::ADVISORIES_PATH)"

위 명령이 false를 반환하면 GitLab이 예상 패키지 경로를 찾을 수 없습니다. 경로의 모든 폴더와 파일에는 755 권한이 있어야 합니다. 권한을 업데이트하려면:

sudo chmod -R 755 $GITLAB_RAILS_ROOT_DIR/vendor/package_metadata/

데이터 확인#

동기화 작업이 성공적으로 실행된 후 데이터베이스의 pm_ 테이블 아래에 데이터가 채워져야 합니다.

Rails 콘솔을 사용하여 공급업체별로 존재하는 패키지 수를 확인할 수 있습니다. 예를 들어 Maven 라이선스 및 어드바이저리 데이터가 로드되었는지 확인하려면 다음을 실행합니다:

  • 라이선스의 경우: sudo gitlab-rails runner "puts \"Package model has #{PackageMetadata::Package.where(purl_type: 'maven').size} packages\""
  • 어드바이저리의 경우: sudo gitlab-rails runner "puts \"Advisory model has #{PackageMetadata::AffectedPackage.where(purl_type: 'maven').size} packages\""

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

  • 라이선스의 경우: sudo gitlab-rails runner "puts \"maven data has been synced up to #{PackageMetadata::Checkpoint.where(data_type: 'licenses', purl_type: 'maven')}\""
  • 어드바이저리의 경우: sudo gitlab-rails runner "puts \"maven data has been synced up to #{PackageMetadata::Checkpoint.where(data_type: 'advisories', purl_type: 'maven')}\""
로그#

application_json.log 파일은 동기화 작업이 실행되었고 오류가 없는지 확인하는 데 도움이 됩니다. 동기화와 관련된 이벤트의 심각도는 DEBUG이고 클래스는 PackageMetadata::SyncService입니다. 예시: {"severity":"DEBUG","time":"2026-01-07T02:15:49.618Z","meta.caller_id":"PackageMetadata::AdvisoriesSyncWorker","correlation_id":"43008e30dd708eadbe1ab16ad7fa953f","meta.root_caller_id":"Cronjob","meta.feature_category":"software_composition_analysis","meta.client_id":"ip/","class":"PackageMetadata::SyncService","message":"Evaluating data for advisories:offline//opt/gitlab/embedded/service/gitlab-rails/vendor/package_metadata/advisories/v2/maven/1761761049/0.ndjson"}

sidekiq 로그는 동기화 작업 중에 오류가 발생했는지 표시합니다. 동기화에 대해 기록된 이벤트는 관련 클래스를 언급합니다:

  • 라이선스의 경우: PackageMetadata::LicensesSyncWorker
  • 어드바이저리의 경우: PackageMetadata::AdvisoriesSyncWorker