- 설치
- SSL 활성화
- GitLab 컨테이너 레지스트리 활성화
- Docker 데몬이 레지스트리 및 GitLab Runner를 신뢰하도록 허용하기
- GitLab Runner 활성화
- 패키지 메타데이터 데이터베이스 활성화
오프라인 자체 관리 GitLab 인스턴스 설치하기
이 가이드는 오프라인에서 완전히 자체 관리 GitLab 인스턴스를 설치, 구성 및 사용하는 단계별 안내입니다.
설치
또한 이 가이드는 서버 호스트가
my-host.internal
로 확인된다고 가정하며, 이는 서버의 FQDN으로 교체해야 하며, 필요한 패키지 파일을 다운로드하기 위해 다른 인터넷에 연결된 서버에 접근할 수 있어야 합니다.
이 프로세스의 비디오 안내를 보려면 오프라인 GitLab 설치: 다운로드 및 설치를 참조하세요.
GitLab 패키지 다운로드
인터넷에 접근할 수 있는 동일한 운영 체제의 서버를 사용하여 GitLab 패키지와 관련 종속성을 수동으로 다운로드해야 합니다.
오프라인 환경에 로컬 네트워크 접근이 없는 경우, USB 드라이브와 같은 물리적 매체를 통해 관련 패키지를 수동으로 전송해야 합니다.
Ubuntu에서 이것은 인터넷에 접근할 수 있는 서버에서 다음 명령어로 수행할 수 있습니다:
# 리포지토리를 준비하는 bash 스크립트 다운로드
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh" | sudo bash
# /var/cache/apt/archives에 gitlab-ee 패키지 및 종속성 다운로드
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을 수동으로 구성하는 방법을 반영합니다:
-
/etc/gitlab/gitlab.rb
에 다음 변경 사항을 적용합니다:# external_url을 "http"에서 "https"로 업데이트 external_url "https://my-host.internal" # Let's Encrypt를 false로 설정 letsencrypt['enable'] = false
-
자체 서명된 인증서를 생성하기 위해 적절한 권한으로 다음 디렉토리를 생성합니다:
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
-
변경 사항을 적용하기 위해 인스턴스를 재구성합니다:
sudo gitlab-ctl reconfigure
GitLab 컨테이너 레지스트리 활성화
컨테이너 레지스트리를 활성화하려면 다음 단계를 따르세요. 이 단계는 기존 도메인에서 컨테이너 레지스트리 구성과 동일합니다:
-
/etc/gitlab/gitlab.rb
에 다음 변경을 적용합니다:# external_registry_url을 external_url과 일치하도록 변경하되 포트 4567을 추가합니다. external_url "https://gitlab.example.com" registry_external_url "https://gitlab.example.com:4567"
-
변경 사항을 적용하기 위해 인스턴스를 재구성합니다:
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
다음에 설치될 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
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
에 다음 변경을 적용합니다:
-
volumes
에 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에 대한 레지스트리 인증
도커 레지스트리 인증 문서에서 언급된 바와 같이, 특정 버전의 도커는 OS 수준에서 인증서 체인을 신뢰해야 합니다.
우분투의 경우, 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 클러스터가 pool.ntp.org
에 접근할 수 있다고 가정합니다. pool.ntp.org
에 접근할 수 없는 경우, Gitaly 및 Praefect 서버에서 시간 서버 설정 사용자 지정을 통해 접근할 수 있는 NTP 서버를 사용해야 합니다.
오프라인 인스턴스에서는 GitLab Geo 확인 Rake 작업이 항상 pool.ntp.org
를 사용하기 때문에 실패합니다. 이 오류는 무시할 수 있지만, 우회 방법에 대해 더 읽어보실 수 있습니다.
패키지 메타데이터 데이터베이스 활성화
패키지 메타데이터 데이터베이스를 활성화하는 것은 지속적인 취약점 스캔 및 CycloneDX 파일의 라이센스 스캔을 활성화하기 위해 필요합니다. 이 과정은 패키지 메타데이터 데이터베이스라는 집합체에서 라이센스 및/또는 권고 데이터를 사용해야 하며, 이는 EE 라이센스에 따라 라이센스가 부여됩니다.
패키지 메타데이터 데이터베이스 사용과 관련하여 다음 사항에 유의하십시오:
- 우리는 패키지 메타데이터 데이터베이스의 모든 부분 또는 일부를 언제든지 사전 통지 없이 변경하거나 중단할 수 있습니다.
- 패키지 메타데이터 데이터베이스는 제3자 웹사이트나 리소스에 대한 링크를 포함할 수 있습니다. 우리는 이러한 링크를 편의상 제공할 뿐이며, 해당 웹사이트 또는 리소스에서 제공되는 제3자 데이터, 콘텐츠, 제품 또는 서비스, 또는 그러한 웹사이트에 표시된 링크에 대한 책임을 지지 않습니다.
- 패키지 메타데이터 데이터베이스는 부분적으로 제3자가 제공한 정보를 기반으로 하며, GitLab은 제공된 콘텐츠의 정확성이나 완전성에 대해 책임을 지지 않습니다.
패키지 메타데이터는 다음 Google Cloud 제공업체(GCP) 버킷에 저장됩니다:
-
라이센스 스캔 - prod-export-license-bucket-1a6c642fc4de57d4
-
의존성 스캔 - prod-export-advisory-bucket-1a6c642fc4de57d4
gsutil 도구를 사용하여 패키지 메타데이터 내보내기 다운로드
-
gsutil
도구를 설치합니다. -
GitLab Rails 디렉터리의 루트를 찾습니다.
export GITLAB_RAILS_ROOT_DIR="$(gitlab-rails runner 'puts Rails.root.to_s')" echo $GITLAB_RAILS_ROOT_DIR
-
동기화를 원하는 데이터의 유형을 설정합니다.
# 라이선스 스캐닝 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"
-
패키지 메타데이터 내보내기를 다운로드합니다.
# 패키지 메타데이터 내보내기를 다운로드하려면 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 Rails 디렉터리의 루트에 복사할 수 있습니다. 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/o 및 https://storage.googleapis.com/storage/v1/b/prod-export-advisory-bucket-1a6c642fc4de57d4/o에서 사용할 수 있습니다. 다음은 cURL 및 jq를 사용하여 이를 다운로드하는 방법의 예입니다.
#!/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"
# 버킷의 내용을 다운로드합니다.
# v2 객체만 다운로드하기 위해 `prefix=v2`를 사용하여 결과를 필터링합니다. v1 데이터는 더 이상 사용되지 않으며 16.3 이후로 사용 중단되었습니다.
# 이 스크립트는 모든 객체를 다운로드하고 파일마다 최대 1000개의 객체를 JSON 형식으로 생성합니다.
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 of $TOTAL_OBJECT_COUNT 객체가 다운로드되었습니다\n"
INDEX=$((INDEX + 1))
done <"$PKG_METADATA_DOWNLOADS_OUTPUT_FILE"
echo "모든 객체가 $PKG_METADATA_DIR에 저장되었습니다."
자동 동기화
귀하의 GitLab 인스턴스는 package_metadata
디렉토리의 내용을 정기적으로 동기화합니다.
로컬 복사본을 업스트림 변경 사항으로 자동으로 업데이트하려면 크론 작업을 추가하여 주기적으로 새로운 내보내기를 다운로드할 수 있습니다. 예를 들어, 매 30분마다 실행되는 크론 작업을 설정하기 위해 다음과 같은 크론탭을 추가할 수 있습니다.
라이센스 스캐닝의 경우:
*/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
로 변경되었습니다. 이 디렉토리가 인스턴스에 이미 존재하고 종속성 스캐닝을 추가해야 하는 경우 다음 단계를 따라야 합니다.
-
라이센스 디렉토리 이름 변경:
mv vendor/package_metadata_db vendor/package_metadata/licenses
. -
vendor/package_metadata_db
를vendor/package_metadata/licenses
로 변경하기 위한 자동화 스크립트나 명령을 업데이트합니다. -
vendor/package_metadata_db
를vendor/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 콘솔 사용하여 확인):
- 라이센스의 경우:
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
로그를 확인하여 동기화 작업이 실행되고 오류가 없는지 검증할 수 있습니다. PackageMetadata::SyncService
클래스를 검색하여 DEBUG
메시지를 찾으면 됩니다. 예: {"severity":"DEBUG","time":"2023-06-22T16:41:00.825Z","correlation_id":"a6e80150836b4bb317313a3fe6d0bbd6","class":"PackageMetadata::SyncService","message":"Evaluating data for licenses:gcp/prod-export-license-bucket-1a6c642fc4de57d4/v2/pypi/1694703741/0.ndjson"}
.