InfoGrab DocsInfoGrab Docs

GitLab Duo Self-Hosted: AWS Bedrock BYOM 배포 가이드

요약

이 가이드는 AWS Bedrock을 사용하는 자체 호스팅 AI 모델과 함께 GitLab을 배포하는 과정을 안내합니다. 이 가이드에서는 AWS Bedrock을 LLM 공급자로 사용하여 GitLab(Docker)과 AI Gateway(Docker Compose)를 단일 EC2 인스턴스에서 나란히 실행합니다.

이 가이드는 AWS Bedrock을 사용하는 자체 호스팅 AI 모델과 함께 GitLab을 배포하는 과정을 안내합니다. 빈 EC2 인스턴스에서 시작해 Duo Agent Platform(DAP) 플로우가 작동하는 상태까지 이끌어 드립니다. 모든 명령어는 복사·붙여넣기 가능하며, 자주 발생하는 실수도 모두 문서화되어 있습니다.

이 가이드에서는 AWS Bedrock을 LLM 공급자로 사용하여 GitLab(Docker)과 AI Gateway(Docker Compose)를 단일 EC2 인스턴스에서 나란히 실행합니다. 이 아키텍처는 개념 증명(PoC) 및 평가 배포에 적합합니다.

프로덕션 배포에 대해서는 참조 아키텍처를 참조하세요.

사전 요구사항#

시작하기 전에 다음이 필요합니다.

요구사항 세부 정보
AWS 계정 타깃 리전(us-east-1 권장)에서 Bedrock 액세스가 활성화된 계정.
EC2 인스턴스 t3.xlarge 최소 사양(4 vCPU, 16 GB RAM). 프로덕션에는 t3.2xlarge 권장(8 vCPU, 32 GB).
도메인 이름 EC2 인스턴스를 가리키는 두 개의 DNS 레코드: gitlab.example.com 및 aigw.example.com.
GitLab 라이선스 Premium 또는 Ultimate. 클래식 Duo 기능(Chat, Code Suggestions)은 Duo 시트 할당이 필요합니다. 온라인 라이선스로 사용하는 DAP(GitLab 18.9 이상)는 GitLab 크레딧을 통한 사용량 기반 결제를 사용하며 Duo Enterprise 시트가 필요 없습니다. 오프라인 라이선스로 사용하는 DAP의 경우 ELA 옵션에 대해 GitLab 계정 팀에 문의하세요.
SSH 액세스 EC2 인스턴스에 대한 SSH 액세스.
보안 그룹 인바운드 포트 80, 443, 8443 개방.

아키텍처 개요#

%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
    accTitle: GitLab Duo Self-Hosted with AWS Bedrock architecture
    accDescr: Shows the flow from a browser to GitLab on EC2, which connects to the AI Gateway sidecar, which routes LLM requests to AWS Bedrock.

    A[Browser / IDE] --> B[GitLab EE<br/>Port 443]
    B --> C[AI Gateway<br/>Port 5052 HTTP<br/>Port 50052 gRPC]
    C --> D[AWS Bedrock<br/>Claude / GPT]

AI Gateway는 GitLab 옆에서 사이드카 컨테이너로 실행됩니다. GitLab에 내장된 NGINX가 HTTPS 및 gRPC 트래픽을 AI Gateway로 프록시합니다. AI Gateway는 LLM 요청을 AWS Bedrock으로 전달합니다.

DAP 플로우에는 포트 8443이 필요합니다. DAP는 gRPC를 사용해 AI Gateway Duo Workflow Service(DWS)와 통신합니다. GitLab NGINX는 포트 8443에서 gRPC TLS를 AI Gateway의 gRPC 포트(50052)로 프록시해야 합니다.

1단계: AWS 인프라 프로비저닝#

EC2 인스턴스 시작#

Ubuntu 22.04 이상 인스턴스를 다음 설정으로 시작하세요.

  • 인스턴스 유형: t3.xlarge(최소) 또는 t3.2xlarge(권장)

  • 스토리지: 100 GB gp3

  • AMI: Ubuntu Server 22.04 LTS 또는 24.04

보안 그룹 구성#

다음 인바운드 포트를 개방하세요.

포트 프로토콜 소스 용도
22 TCP 내 IP SSH
80 TCP 0.0.0.0/0 HTTP(Let's Encrypt 검증)
443 TCP 0.0.0.0/0 HTTPS(GitLab 및 AI Gateway 프록시)
8443 TCP 0.0.0.0/0 gRPC TLS(DAP 플로우)

IDE 클라이언트(VS Code, JetBrains)는 DAP 플로우를 위해 포트 8443에 직접 연결합니다. 사용자가 VPN 뒤에 있다면 소스 IP 범위를 제한할 수 있습니다.

Docker 설치#

인스턴스에 SSH로 접속한 뒤 Docker를 설치하세요.

sudo apt-get update && sudo apt-get upgrade -y

# Install Docker (official method)
curl --fail --silent --show-error --location "https://get.docker.com" | sudo bash

# Install Docker Compose plugin
sudo apt-get install -y docker-compose-plugin

# Verify
sudo docker --version
sudo docker compose version

DNS 설정#

EC2 공개 IP를 가리키는 A 레코드 두 개를 생성하세요.

레코드 유형
gitlab.example.com A EC2 공개 IP
aigw.example.com A EC2 공개 IP

두 도메인 모두 동일한 IP를 가리킵니다. GitLab NGINX는 호스트 이름을 기반으로 트래픽을 라우팅합니다.

DNS 전파를 확인하세요.

dig gitlab.example.com +short
dig aigw.example.com +short

두 명령어 모두 EC2 공개 IP를 반환해야 합니다.

2단계: GitLab 설치#

데이터 디렉터리 생성#

sudo mkdir -p /srv/gitlab/config /srv/gitlab/logs /srv/gitlab/data

GitLab 실행#

이 명령어는 Let's Encrypt와 함께 GitLab EE를 설치하고 시작합니다.

sudo docker run --detach \
  --hostname gitlab.example.com \
  --env GITLAB_OMNIBUS_CONFIG="
    external_url 'https://gitlab.example.com';
    letsencrypt['enable'] = true;
    letsencrypt['auto_renew'] = true;
    letsencrypt['contact_emails'] = ['you@example.com'];
    gitlab_rails['gitlab_shell_ssh_port'] = 2222;
  " \
  --publish 443:443 \
  --publish 80:80 \
  --publish 2222:22 \
  --publish 8443:8443 \
  --name gitlab \
  --restart always \
  --volume /srv/gitlab/config:/etc/gitlab \
  --volume /srv/gitlab/logs:/var/log/gitlab \
  --volume /srv/gitlab/data:/var/opt/gitlab \
  --shm-size 256m \
  gitlab/gitlab-ee:latest
Note

--publish 8443:8443 플래그는 DAP(gRPC TLS)에 필수입니다. 생략하면 DAP 플로우가 자동으로 실패합니다. 실행 중인 컨테이너에는 포트를 추가할 수 없으므로 컨테이너를 다시 생성해야 합니다.

GitLab 시작 대기#

GitLab은 첫 실행 시 초기화에 3~5분이 소요됩니다.

until curl --silent --fail "https://gitlab.example.com/-/health" > /dev/null 2>&1; do
  echo "Waiting for GitLab to start..."
  sleep 10
done
echo "GitLab is up!"

root 비밀번호 설정#

sudo docker exec gitlab cat /etc/gitlab/initial_root_password

https://gitlab.example.com에 사용자 이름 root와 명령어 출력에 나온 비밀번호로 로그인하세요. 즉시 비밀번호를 변경하세요.

라이선스 적용#

  • Admin > Subscription으로 이동하세요.

  • GitLab 라이선스 파일을 업로드하세요.

3단계: AI Gateway 배포#

올바른 이미지 태그 찾기#

AI Gateway 이미지는 Docker Hub의 gitlab/model-gateway에 있습니다. GitLab 버전과 일치하는 버전 태그를 사용해야 합니다.

Note

latest 태그는 존재하지 않습니다. gitlab/model-gateway:latest를 사용하면 이미지를 찾을 수 없다는 오류가 발생합니다.

태그 형식: self-hosted-v{MAJOR}.{MINOR}.{PATCH}-ee

사용 가능한 태그를 확인하세요.

curl --silent "https://hub.docker.com/v2/repositories/gitlab/model-gateway/tags?page_size=10&ordering=last_updated" | \
  python3 -c "import sys,json; [print(t['name'], '  ', t['last_updated'][:10]) for t in json.load(sys.stdin)['results']]"

JWT 서명 키 생성#

AI Gateway는 DWS 요청을 인증하기 위한 JWT 키가 필요합니다.

sudo mkdir -p /srv/enterprise-sidecar
openssl genrsa -out /srv/enterprise-sidecar/duo_workflow_jwt.key 2048

환경 파일 생성#

/srv/enterprise-sidecar/.env 파일을 생성하세요.

cat << 'EOF' | sudo tee /srv/enterprise-sidecar/.env
# AWS Bedrock credentials
AWS_ACCESS_KEY_ID=<your-aws-access-key>
AWS_SECRET_ACCESS_KEY=<your-aws-secret-key>
AWS_REGION=us-east-1

# AI Gateway: JWT signing key (for DWS authentication)
AIGW_JWT_SIGNING_KEY=<paste contents of duo_workflow_jwt.key>
EOF

환경 파일에 제한적인 권한을 설정하세요.

sudo chmod 600 /srv/enterprise-sidecar/.env

JWT 키를 환경 파일에 삽입하려면 줄 바꿈을 리터럴 \n으로 변환해 키가 한 줄에 들어가도록 하세요.

JWT_KEY=$(sudo awk '{printf "%s\\n", $0}' /srv/enterprise-sidecar/duo_workflow_jwt.key)
sudo sed -i "s|AIGW_JWT_SIGNING_KEY=.*|AIGW_JWT_SIGNING_KEY=${JWT_KEY}|" /srv/enterprise-sidecar/.env

Docker Compose 파일 생성#

/srv/enterprise-sidecar/docker-compose.yml 파일을 생성하세요.

services:
  ai-gateway:
    image: gitlab/model-gateway:self-hosted-v-ee  # Replace  with your GitLab version (for example, 18.11.0)
    container_name: ai-gateway
    restart: unless-stopped
    environment:
      AIGW_GITLAB_URL: https://gitlab.example.com
      AIGW_GITLAB_API_URL: https://gitlab.example.com/api/v4/
      DUO_WORKFLOW_SELF_SIGNED_JWT__SIGNING_KEY: ${AIGW_JWT_SIGNING_KEY}
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
      AWS_REGION: ${AWS_REGION:-us-east-1}
      AIGW_LOGGING__LEVEL: INFO
      DUO_WORKFLOW_LOGGING__LEVEL: INFO
    ports:
      - "5052:5052"
      - "50052:50052"
    deploy:
      resources:
        limits:
          memory: 2048M
        reservations:
          memory: 512M
    healthcheck:
      test: ["CMD", "curl", "--silent", "--fail", "http://localhost:5052/monitoring/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

AI Gateway 시작#

cd /srv/enterprise-sidecar
sudo docker compose up -d

AI Gateway 상태 확인#

# Check container is running
sudo docker ps | grep ai-gateway

# Check HTTP health endpoint (empty JSON means healthy)
curl --silent "http://localhost:5052/monitoring/healthz"

# Check logs for errors
sudo docker logs ai-gateway --tail 20

4단계: AI Gateway TLS 구성#

AI Gateway에는 HTTPS(Chat 및 Code Suggestions용)와 gRPC TLS(DAP 플로우용)가 필요합니다. GitLab에 내장된 NGINX를 리버스 프록시로 사용하여 Let's Encrypt 인증서를 공유하세요.

Let's Encrypt에 AI Gateway 서브도메인 추가#

GitLab 구성을 편집하세요.

sudo docker exec -it gitlab editor /etc/gitlab/gitlab.rb

letsencrypt 섹션을 찾아 alt_names를 추가하세요.

letsencrypt['alt_names'] = ['aigw.example.com']

레지스트리 서브도메인 등 이미 다른 alt_names가 있다면 기존 배열에 aigw.example.com을 추가하세요.

letsencrypt['alt_names'] = ['registry.example.com', 'aigw.example.com']

새 SAN을 포함하도록 인증서를 갱신하세요.

sudo docker exec gitlab gitlab-ctl renew-le-certs

인증서에 AI Gateway 서브도메인이 포함되었는지 확인하세요.

echo | openssl s_client -connect gitlab.example.com:443 2>/dev/null | \
  openssl x509 -noout -ext subjectAltName

출력에 DNS:aigw.example.com이 표시되어야 합니다.

NGINX 프록시 구성 생성#

호스트에 프록시 구성 파일을 생성하세요.

cat << 'NGINX' | sudo tee /srv/gitlab/config/nginx/aigw-proxy.conf
# AI Gateway reverse proxy: HTTPS for HTTP API, gRPC TLS for DAP

# HTTP API: Duo Chat, Code Suggestions
server {
    listen 443 ssl;
    server_name aigw.example.com;

    ssl_certificate /etc/gitlab/ssl/gitlab.example.com.crt;
    ssl_certificate_key /etc/gitlab/ssl/gitlab.example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://172.17.0.1:5052;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_read_timeout 600s;
        proxy_send_timeout 600s;
    }

    location /monitoring/healthz {
        proxy_pass http://172.17.0.1:5052/monitoring/healthz;
        access_log off;
    }
}

# gRPC TLS: DAP / Duo Agent Platform flows
server {
    listen 8443 ssl http2;
    server_name aigw.example.com;

    ssl_certificate /etc/gitlab/ssl/gitlab.example.com.crt;
    ssl_certificate_key /etc/gitlab/ssl/gitlab.example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        grpc_pass grpc://172.17.0.1:50052;
        grpc_read_timeout 600s;
        grpc_send_timeout 600s;
    }
}
NGINX

172.17.0.1은 Docker의 기본 브리지 게이트웨이 IP입니다. GitLab 컨테이너 내부에서 이 IP를 통해 호스트 머신과 AI Gateway 컨테이너의 공개 포트에 접근할 수 있습니다.

GitLab NGINX에 구성 포함#

구성 파일을 컨테이너 내 NGINX 런타임 디렉터리로 복사하세요.

sudo docker exec gitlab mkdir -p /var/opt/gitlab/nginx/conf
sudo docker cp /srv/gitlab/config/nginx/aigw-proxy.conf \
  gitlab:/var/opt/gitlab/nginx/conf/aigw-proxy.conf
Note

파일을 /etc/gitlab/nginx/에 두지 마세요. gitlab.rbcustom_nginx_config에서 참조하는 파일만 로드됩니다. 런타임 디렉터리는 /var/opt/gitlab/nginx/conf/입니다.

gitlab.rb에 include 지시어를 추가하세요.

sudo docker exec -it gitlab editor /etc/gitlab/gitlab.rb

nginx['custom_nginx_config'] 행을 찾거나 추가하세요.

nginx['custom_nginx_config'] = "include /var/opt/gitlab/nginx/conf/aigw-proxy.conf;"

KeyCloak 프록시 등 이미 사용자 정의 NGINX 구성이 있다면 세미콜론으로 연결하세요.

nginx['custom_nginx_config'] = "include /var/opt/gitlab/nginx/conf/keycloak-proxy.conf; include /var/opt/gitlab/nginx/conf/aigw-proxy.conf;"

GitLab 재구성#

sudo docker exec gitlab gitlab-ctl reconfigure

TLS 확인#

# HTTPS for AI Gateway HTTP API
curl --silent "https://aigw.example.com/monitoring/healthz"
# Expected: {}

# gRPC TLS for DAP
openssl s_client -connect aigw.example.com:8443 < /dev/null 2>/dev/null | \
  grep "Verify return code"
# Expected: Verify return code: 0 (ok)

5단계: AWS Bedrock 연결#

Bedrock용 IAM 사용자 생성#

AWS 콘솔에서 IAM > Users > Create user로 이동하세요.

  • 이름: gitlab-bedrock(또는 유사한 이름)

  • 권한: AmazonBedrockFullAccess 관리형 정책 연결

액세스 키를 생성하세요(사용 사례: "Application running outside AWS"). 액세스 키 ID시크릿 액세스 키를 저장하세요.

EC2 인스턴스에 Bedrock 권한이 있는 IAM 역할이 있다면 액세스 키를 건너뛸 수 있습니다. AI Gateway는 인스턴스 프로파일을 자동으로 사용합니다.

Bedrock에서 Anthropic 모델 활성화#

이 단계는 필수이며 많은 사람이 놓치는 부분입니다.

  • AWS 콘솔 > Amazon Bedrock > Providers > Anthropic으로 이동하세요.

  • Submit use case details 양식을 작성하세요.

  • 활성화까지 약 15분을 기다리세요.

Note

이 양식 없이는 Anthropic 모델에 대한 모든 Bedrock API 호출에서 다음 오류가 반환됩니다. "Model use case details have not been submitted for this account." 기존 "Model access" 페이지는 폐기되었습니다. 모델은 첫 번째 호출 시 자동으로 활성화되지만, Anthropic 모델은 사용 사례 양식이 필요합니다.

모델의 추론 프로파일 ID 찾기#

최신 Claude 모델(Claude 4.5 Sonnet 이상)은 직접 모델 ID 대신 추론 프로파일 ID가 필요합니다.

aws bedrock list-inference-profiles --region us-east-1 --output json | \
  python3 -c "
import sys, json
profiles = json.load(sys.stdin)['inferenceProfileSummaries']
for p in profiles:
    if 'claude' in p['inferenceProfileId'].lower():
        print(p['inferenceProfileId'])
"
Note

기본 모델 ID(anthropic.claude-sonnet-4-6)가 아닌 us. 접두사(예: us.anthropic.claude-sonnet-4-6)를 사용하세요.

모델 식별자 결과
bedrock/anthropic.claude-sonnet-4-6 400 Bad Request: "on-demand throughput isn't supported"
bedrock/us.anthropic.claude-sonnet-4-6 작동함

us. 접두사는 미국 전용 리전으로 라우팅합니다. global. 접두사는 활성화된 모든 리전에 걸쳐 라우팅합니다.

애플리케이션 추론 프로파일 ARN 사용#

팀이나 프로젝트별 비용 할당 또는 지출 추적을 원한다면 추론 프로파일 ID 대신 애플리케이션 추론 프로파일 ARN을 모델 식별자로 사용하세요. 다음 형식을 사용하세요.

bedrock/converse/arn:aws:bedrock:<region>:<account-id>:application-inference-profile/<id>

converse/ 접두사는 ARN 기반 식별자에 필요한 Amazon Bedrock Converse API를 통해 요청을 라우팅합니다.

자격 증명으로 AI Gateway 재시작#

아직 하지 않았다면 AWS 자격 증명을 /srv/enterprise-sidecar/.env에 추가한 뒤 재시작하세요.

cd /srv/enterprise-sidecar
sudo docker compose down ai-gateway
sudo docker compose up -d ai-gateway

6단계: GitLab 관리자 설정 구성#

AI Gateway URL 설정#

Admin > GitLab Duo로 이동한 후 Change configuration을 선택하세요.

설정
연결 방법 GitLab Self-Managed를 통한 간접 연결
로컬 AI Gateway URL https://aigw.example.com
로컬 DAP 서비스 URL aigw.example.com:8443
AI Gateway 요청 타임아웃 300(초)
Note

기본 타임아웃 60초는 Bedrock에서 너무 짧습니다. 단일 DAP 플로우는 5~10분이 소요될 수 있습니다. 최소 300으로 설정하세요.

Save changes를 선택하세요.

상태 확인 실행#

같은 페이지에서 Run health check를 선택하세요. 다음 네 가지 항목이 녹색으로 표시되어야 합니다.

확인 항목 예상 결과
AI Gateway Connected
Network Reachable
Code Suggestions Available
DAP Available

자체 호스팅 모델 추가#

Admin > GitLab Duo > Configure models for GitLab Duo로 이동하세요.

Add self-hosted model을 선택하고 다음을 입력하세요.

필드
배포 이름 Bedrock Claude Sonnet 4.6(또는 설명적인 이름)
플랫폼 Amazon Bedrock
모델 패밀리 Claude
모델 식별자 bedrock/us.anthropic.claude-sonnet-4-6
Note

모델 식별자는 반드시 bedrock/으로 시작해야 합니다.

Test connection을 선택하세요. 다음 메시지가 표시되어야 합니다. "Successfully connected to the self-hosted model."

"400 Bad Request"가 표시되면 잘못된 모델 식별자를 사용하고 있는 것입니다. 직접 모델 ID가 아닌 추론 프로파일 ID(us.anthropic.claude-sonnet-4-6)를 사용하세요.

Add model을 선택하세요.

기능에 모델 할당#

같은 페이지에서 AI-native features 탭을 선택하세요.

Bedrock을 통해 라우팅할 각 기능에 대해 드롭다운 목록에서 자체 호스팅 모델을 선택하세요.

기능 권장 할당
GitLab Duo Agent Platform > Agents & flows Bedrock Claude Sonnet 4.6
GitLab Duo Agent Platform > Agentic Chat Bedrock Claude Sonnet 4.6
Code Suggestions GitLab 관리(기본값) 또는 Bedrock
Chat GitLab 관리(기본값) 또는 Bedrock
Code Review GitLab 관리(기본값) 또는 Bedrock

먼저 DAP 기능만 Bedrock에 할당하고 Chat과 Code Suggestions는 GitLab 관리 기본값으로 유지하세요. 이렇게 하면 일상적인 개발자 경험에 영향을 주지 않고 Bedrock 연결을 검증할 수 있습니다. 모든 것이 정상적으로 작동하는 것을 확인한 후 더 많은 기능을 전환하세요.

7단계: DAP 플로우를 위한 러너 등록#

DAP 플로우는 CI/CD 파이프라인을 생성합니다. 등록된 러너가 없으면 DAP 플로우는 무기한 대기 상태에 머뭅니다.

러너 설치 및 등록#

EC2 인스턴스(또는 별도 머신)에 GitLab Runner를 설치하세요.

curl --location "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install -y gitlab-runner

GitLab 인스턴스에 러너를 등록하세요. Admin > CI/CD > Runners로 이동해 New instance runner를 선택하여 등록 토큰을 받은 후 다음을 실행하세요.

sudo gitlab-runner register \
  --url "https://gitlab.example.com" \
  --token "" \
  --executor docker \
  --docker-image "ruby:3.2" \
  --tag-list "docker" \
  --description "Docker runner for DAP"

자세한 내용은 GitLab Runner 설치러너 생성 및 등록을 참조하세요.

Note

DAP 플로우는 Docker-in-Docker 워크플로를 사용합니다. 러너는 docker executor를 사용해야 합니다.

8단계: 그룹 및 프로젝트에서 Duo 기능 활성화#

6단계의 관리자 수준 구성으로 Duo 기능을 인스턴스 전체에서 사용할 수 있게 되지만, 그룹 및 프로젝트 수준에서도 활성화해야 합니다.

그룹에서 Duo 활성화#

  • 그룹의 Settings > General로 이동하세요.

  • Permissions and group features를 펼치세요.

  • GitLab Duo features 아래에서 Enable GitLab Duo features를 선택하세요.

  • DAP를 사용하려면 Enable experiment and beta featuresAllow flow execution도 선택하세요(활성화할 플로우 유형 체크).

  • Save changes를 선택하세요.

자세한 내용은 GitLab Duo 켜기 또는 끄기를 참조하세요.

프로젝트에서 Duo 활성화#

  • 프로젝트의 Settings > General로 이동하세요.

  • Visibility, project features, permissions를 펼치세요.

  • GitLab Duo 아래에서 Use GitLab Duo features를 켜세요.

  • Save changes를 선택하세요.

자세한 내용은 GitLab Duo 켜기 또는 끄기를 참조하세요.

9단계: 엔드-투-엔드 검증#

상태 확인#

# AI Gateway HTTP health
curl --silent "https://aigw.example.com/monitoring/healthz"
# Expected: {}

# gRPC TLS connectivity
openssl s_client -connect aigw.example.com:8443 < /dev/null 2>/dev/null | \
  grep "Verify return code"
# Expected: Verify return code: 0 (ok)

브라우저에서 Admin > GitLab Duo로 이동해 Change configuration을 선택한 후 Run health check를 선택하세요. 네 가지 항목 모두 녹색이어야 합니다.

Rake 검증 태스크 실행#

sudo docker exec gitlab gitlab-rake "gitlab:duo:verify_self_hosted_setup[your_username]"

이 태스크는 라이선스, 기능 플래그, AI Gateway 연결, 모델 구성 등 전체 체인을 검증합니다.

Note

Rake 태스크의 모델 연결 테스트는 플레이스홀더 URL(bedrockselfhostedmodel.com)을 사용하므로, 배포가 정상적으로 작동하는 상태에서도 실패를 보고할 수 있습니다. 나머지 모든 확인(라이선스, AI Gateway, 기능 할당)은 유효합니다.

Duo Chat 테스트#

Note

일부 AI Gateway 버전에서 Bedrock을 사용하는 Duo Chat이 400 오류 ("This model does not support assistant message prefill")를 반환할 수 있습니다. 이는 Duo Chat에만 영향을 미칩니다. DAP 플로우는 다른 코드 경로를 사용하므로 정상 작동합니다. 이 오류가 발생하면 Chat은 GitLab 관리 모델로 유지하고 DAP 기능에만 Bedrock을 사용하세요.

  • GitLab 인스턴스에서 아무 프로젝트나 여세요.

  • Duo Chat 아이콘을 선택하세요.

  • "What is a merge request?"와 같은 간단한 질문을 하세요.

  • 응답이 오는지 확인하세요.

AI Gateway 로그에서 Bedrock 활동을 확인하세요.

sudo docker logs -f ai-gateway 2>&1 | grep -i "litellm\|bedrock\|chat"

DAP 플로우 테스트#

이것이 진짜 테스트입니다. Bedrock에서 GitLab Duo Agent Platform 플로우를 엔드-투-엔드로 실행합니다.

  • 코드가 있는 프로젝트를 생성하거나 여세요.

  • 이슈를 생성하세요(예: "Add input validation to the login form").

  • 이슈 페이지에서 Duo > Start workflow를 선택하세요.

  • 기다리세요. Bedrock을 사용하는 DAP 플로우는 일반적으로 3~10분이 소요됩니다.

  • 파이프라인을 확인하세요: Build > Pipelines. source: duo_workflow를 찾으세요.

플로우 진행 중 AI Gateway 로그를 확인하세요.

sudo docker logs -f ai-gateway 2>&1 | grep -i "workflow\|bedrock\|litellm"

DAP 플로우 진행 중 예상 로그 출력:

LiteLLM completion() model= us.anthropic.claude-sonnet-4-6; provider = bedrock
Note

플로우가 약 10초 만에 완료되면 문제가 있는 것입니다. 정상적인 플로우는 초가 아닌 분 단위로 소요됩니다. AI Gateway 로그에서 오류를 확인하세요.

10단계: 모니터링(선택 사항)#

AI Gateway Prometheus 메트릭#

AI Gateway는 두 포트에서 메트릭을 노출합니다.

포트 엔드포인트 내용
8082 /metrics AI Gateway(FastAPI) 메트릭: 요청 수, 지연 시간
8083 /metrics DWS 메트릭: gRPC 호출 수

Prometheus 스크래핑을 위해 docker-compose.yml의 ports에 추가하세요.

ports:
  - "5052:5052"
  - "50052:50052"
  - "8082:8082"
  - "8083:8083"

그리고 해당 환경 변수를 추가하세요.

environment:
  AIGW_FASTAPI__METRICS_HOST: "0.0.0.0"
  AIGW_FASTAPI__METRICS_PORT: "8082"
  PROMETHEUS_METRICS__ADDR: "0.0.0.0"
  PROMETHEUS_METRICS__PORT: "8083"

문제 해결#

AI Gateway가 시작되지 않는 경우#

컨테이너가 즉시 종료되거나 상태 확인이 통과되지 않는 경우:

sudo docker logs ai-gateway --tail 50
오류 해결 방법
Image not found latest 태그를 사용했습니다. self-hosted-v18.9.0-ee와 같은 명시적 버전을 사용하세요.
AIGW_GITLAB_URL must be set docker-compose.yml에 환경 변수를 추가하세요.
Connection refused on health check 시작에 30초를 기다리세요. 계속 발생하면 포트 바인딩을 확인하세요.

관리자 UI에서 상태 확인 실패#

확인 항목 일반적인 원인 해결 방법
AI Gateway: Not connected 관리자 설정의 잘못된 URL https://aigw.example.com을 사용하세요(http://, 포트 5052 제외).
Network: Unreachable 컨테이너 내부에서 DNS 미해석 docker exec gitlab dig aigw.example.com으로 확인하세요.
DAP: Unavailable 포트 8443 미공개 --publish 8443:8443으로 GitLab 컨테이너를 재생성하세요.

모델 연결 테스트 시 400 Bad Request#

직접 모델 ID 대신 추론 프로파일 ID를 사용해야 합니다.

bedrock/anthropic.claude-sonnet-4-6bedrock/us.anthropic.claude-sonnet-4-6으로 변경하세요(us. 접두사 주의).

"Model use case details have not been submitted"#

  • AWS 콘솔 > Amazon Bedrock > Providers > Anthropic으로 이동하세요.

  • 사용 사례 세부 정보 양식을 제출하세요.

  • 활성화까지 약 15분을 기다리세요.

  • 재시도하세요.

TLS 오류#

curl "https://aigw.example.com/monitoring/healthz"에서 SSL 오류가 반환되는 경우:

  • gitlab.rbletsencrypt['alt_names']aigw.example.com을 추가했는지 확인하세요.

  • gitlab-ctl renew-le-certs를 실행했는지 확인하세요.

  • NGINX 구성에 올바른 인증서 경로가 사용되고 있는지 확인하세요.

  • NGINX 구성 파일이 /var/opt/gitlab/nginx/conf/에 있는지 확인하세요(/etc/gitlab/nginx/ 아님).

  • gitlab.rbcustom_nginx_config가 해당 파일을 참조하는지 확인하세요.

DAP 플로우가 시작되지 않는 경우#

Start workflow를 선택했는데 파이프라인이 나타나지 않는 경우:

  • 러너가 등록되어 온라인 상태인지 확인하세요(Admin > CI/CD > Runners). 7단계를 참조하세요.

  • 그룹 및 프로젝트에 Duo가 활성화되어 있는지 확인하세요. 8단계를 참조하세요.

  • 사용자에게 GitLab 크레딧 또는 Duo 시트가 있는지 확인하세요(Admin > GitLab Duo > Seat assignment).

  • GitLab 컨테이너에 포트 8443이 공개되어 있는지 확인하세요.

NGINX 구성이 적용되지 않는 경우#

gitlab.rb를 편집하고 reconfigure를 실행한 후:

  • 런타임 디렉터리에 파일이 있는지 확인하세요.
sudo docker exec gitlab ls -la /var/opt/gitlab/nginx/conf/
  • 파일이 없으면 다시 복사하세요.
sudo docker cp /srv/gitlab/config/nginx/aigw-proxy.conf \
  gitlab:/var/opt/gitlab/nginx/conf/aigw-proxy.conf
  • reconfigure 후 NGINX를 재시작하세요.
sudo docker exec gitlab gitlab-ctl reconfigure
sudo docker exec gitlab gitlab-ctl restart nginx

관련 항목#

GitLab Duo Self-Hosted: AWS Bedrock BYOM 배포 가이드

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

이 가이드는 AWS Bedrock을 사용하는 자체 호스팅 AI 모델과 함께 GitLab을 배포하는 과정을 안내합니다. 이 가이드에서는 AWS Bedrock을 LLM 공급자로 사용하여 GitLab(Docker)과 AI Gateway(Docker Compose)를 단일 EC2 인스턴스에서 나란히 실행합니다.

이 가이드는 AWS Bedrock을 사용하는 자체 호스팅 AI 모델과 함께 GitLab을 배포하는 과정을 안내합니다. 빈 EC2 인스턴스에서 시작해 Duo Agent Platform(DAP) 플로우가 작동하는 상태까지 이끌어 드립니다. 모든 명령어는 복사·붙여넣기 가능하며, 자주 발생하는 실수도 모두 문서화되어 있습니다.

이 가이드에서는 AWS Bedrock을 LLM 공급자로 사용하여 GitLab(Docker)과 AI Gateway(Docker Compose)를 단일 EC2 인스턴스에서 나란히 실행합니다. 이 아키텍처는 개념 증명(PoC) 및 평가 배포에 적합합니다.

프로덕션 배포에 대해서는 참조 아키텍처를 참조하세요.

사전 요구사항#

시작하기 전에 다음이 필요합니다.

요구사항 세부 정보
AWS 계정 타깃 리전(us-east-1 권장)에서 Bedrock 액세스가 활성화된 계정.
EC2 인스턴스 t3.xlarge 최소 사양(4 vCPU, 16 GB RAM). 프로덕션에는 t3.2xlarge 권장(8 vCPU, 32 GB).
도메인 이름 EC2 인스턴스를 가리키는 두 개의 DNS 레코드: gitlab.example.com 및 aigw.example.com.
GitLab 라이선스 Premium 또는 Ultimate. 클래식 Duo 기능(Chat, Code Suggestions)은 Duo 시트 할당이 필요합니다. 온라인 라이선스로 사용하는 DAP(GitLab 18.9 이상)는 GitLab 크레딧을 통한 사용량 기반 결제를 사용하며 Duo Enterprise 시트가 필요 없습니다. 오프라인 라이선스로 사용하는 DAP의 경우 ELA 옵션에 대해 GitLab 계정 팀에 문의하세요.
SSH 액세스 EC2 인스턴스에 대한 SSH 액세스.
보안 그룹 인바운드 포트 80, 443, 8443 개방.

아키텍처 개요#

%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
    accTitle: GitLab Duo Self-Hosted with AWS Bedrock architecture
    accDescr: Shows the flow from a browser to GitLab on EC2, which connects to the AI Gateway sidecar, which routes LLM requests to AWS Bedrock.

    A[Browser / IDE] --> B[GitLab EE<br/>Port 443]
    B --> C[AI Gateway<br/>Port 5052 HTTP<br/>Port 50052 gRPC]
    C --> D[AWS Bedrock<br/>Claude / GPT]

AI Gateway는 GitLab 옆에서 사이드카 컨테이너로 실행됩니다. GitLab에 내장된 NGINX가 HTTPS 및 gRPC 트래픽을 AI Gateway로 프록시합니다. AI Gateway는 LLM 요청을 AWS Bedrock으로 전달합니다.

DAP 플로우에는 포트 8443이 필요합니다. DAP는 gRPC를 사용해 AI Gateway Duo Workflow Service(DWS)와 통신합니다. GitLab NGINX는 포트 8443에서 gRPC TLS를 AI Gateway의 gRPC 포트(50052)로 프록시해야 합니다.

1단계: AWS 인프라 프로비저닝#

EC2 인스턴스 시작#

Ubuntu 22.04 이상 인스턴스를 다음 설정으로 시작하세요.

  • 인스턴스 유형: t3.xlarge(최소) 또는 t3.2xlarge(권장)

  • 스토리지: 100 GB gp3

  • AMI: Ubuntu Server 22.04 LTS 또는 24.04

보안 그룹 구성#

다음 인바운드 포트를 개방하세요.

포트 프로토콜 소스 용도
22 TCP 내 IP SSH
80 TCP 0.0.0.0/0 HTTP(Let's Encrypt 검증)
443 TCP 0.0.0.0/0 HTTPS(GitLab 및 AI Gateway 프록시)
8443 TCP 0.0.0.0/0 gRPC TLS(DAP 플로우)

IDE 클라이언트(VS Code, JetBrains)는 DAP 플로우를 위해 포트 8443에 직접 연결합니다. 사용자가 VPN 뒤에 있다면 소스 IP 범위를 제한할 수 있습니다.

Docker 설치#

인스턴스에 SSH로 접속한 뒤 Docker를 설치하세요.

sudo apt-get update && sudo apt-get upgrade -y

# Install Docker (official method)
curl --fail --silent --show-error --location "https://get.docker.com" | sudo bash

# Install Docker Compose plugin
sudo apt-get install -y docker-compose-plugin

# Verify
sudo docker --version
sudo docker compose version

DNS 설정#

EC2 공개 IP를 가리키는 A 레코드 두 개를 생성하세요.

레코드 유형
gitlab.example.com A EC2 공개 IP
aigw.example.com A EC2 공개 IP

두 도메인 모두 동일한 IP를 가리킵니다. GitLab NGINX는 호스트 이름을 기반으로 트래픽을 라우팅합니다.

DNS 전파를 확인하세요.

dig gitlab.example.com +short
dig aigw.example.com +short

두 명령어 모두 EC2 공개 IP를 반환해야 합니다.

2단계: GitLab 설치#

데이터 디렉터리 생성#

sudo mkdir -p /srv/gitlab/config /srv/gitlab/logs /srv/gitlab/data

GitLab 실행#

이 명령어는 Let's Encrypt와 함께 GitLab EE를 설치하고 시작합니다.

sudo docker run --detach \
  --hostname gitlab.example.com \
  --env GITLAB_OMNIBUS_CONFIG="
    external_url 'https://gitlab.example.com';
    letsencrypt['enable'] = true;
    letsencrypt['auto_renew'] = true;
    letsencrypt['contact_emails'] = ['you@example.com'];
    gitlab_rails['gitlab_shell_ssh_port'] = 2222;
  " \
  --publish 443:443 \
  --publish 80:80 \
  --publish 2222:22 \
  --publish 8443:8443 \
  --name gitlab \
  --restart always \
  --volume /srv/gitlab/config:/etc/gitlab \
  --volume /srv/gitlab/logs:/var/log/gitlab \
  --volume /srv/gitlab/data:/var/opt/gitlab \
  --shm-size 256m \
  gitlab/gitlab-ee:latest
Note

--publish 8443:8443 플래그는 DAP(gRPC TLS)에 필수입니다. 생략하면 DAP 플로우가 자동으로 실패합니다. 실행 중인 컨테이너에는 포트를 추가할 수 없으므로 컨테이너를 다시 생성해야 합니다.

GitLab 시작 대기#

GitLab은 첫 실행 시 초기화에 3~5분이 소요됩니다.

until curl --silent --fail "https://gitlab.example.com/-/health" > /dev/null 2>&1; do
  echo "Waiting for GitLab to start..."
  sleep 10
done
echo "GitLab is up!"

root 비밀번호 설정#

sudo docker exec gitlab cat /etc/gitlab/initial_root_password

https://gitlab.example.com에 사용자 이름 root와 명령어 출력에 나온 비밀번호로 로그인하세요. 즉시 비밀번호를 변경하세요.

라이선스 적용#

  • Admin > Subscription으로 이동하세요.

  • GitLab 라이선스 파일을 업로드하세요.

3단계: AI Gateway 배포#

올바른 이미지 태그 찾기#

AI Gateway 이미지는 Docker Hub의 gitlab/model-gateway에 있습니다. GitLab 버전과 일치하는 버전 태그를 사용해야 합니다.

Note

latest 태그는 존재하지 않습니다. gitlab/model-gateway:latest를 사용하면 이미지를 찾을 수 없다는 오류가 발생합니다.

태그 형식: self-hosted-v{MAJOR}.{MINOR}.{PATCH}-ee

사용 가능한 태그를 확인하세요.

curl --silent "https://hub.docker.com/v2/repositories/gitlab/model-gateway/tags?page_size=10&ordering=last_updated" | \
  python3 -c "import sys,json; [print(t['name'], '  ', t['last_updated'][:10]) for t in json.load(sys.stdin)['results']]"

JWT 서명 키 생성#

AI Gateway는 DWS 요청을 인증하기 위한 JWT 키가 필요합니다.

sudo mkdir -p /srv/enterprise-sidecar
openssl genrsa -out /srv/enterprise-sidecar/duo_workflow_jwt.key 2048

환경 파일 생성#

/srv/enterprise-sidecar/.env 파일을 생성하세요.

cat << 'EOF' | sudo tee /srv/enterprise-sidecar/.env
# AWS Bedrock credentials
AWS_ACCESS_KEY_ID=<your-aws-access-key>
AWS_SECRET_ACCESS_KEY=<your-aws-secret-key>
AWS_REGION=us-east-1

# AI Gateway: JWT signing key (for DWS authentication)
AIGW_JWT_SIGNING_KEY=<paste contents of duo_workflow_jwt.key>
EOF

환경 파일에 제한적인 권한을 설정하세요.

sudo chmod 600 /srv/enterprise-sidecar/.env

JWT 키를 환경 파일에 삽입하려면 줄 바꿈을 리터럴 \n으로 변환해 키가 한 줄에 들어가도록 하세요.

JWT_KEY=$(sudo awk '{printf "%s\\n", $0}' /srv/enterprise-sidecar/duo_workflow_jwt.key)
sudo sed -i "s|AIGW_JWT_SIGNING_KEY=.*|AIGW_JWT_SIGNING_KEY=${JWT_KEY}|" /srv/enterprise-sidecar/.env

Docker Compose 파일 생성#

/srv/enterprise-sidecar/docker-compose.yml 파일을 생성하세요.

services:
  ai-gateway:
    image: gitlab/model-gateway:self-hosted-v-ee  # Replace  with your GitLab version (for example, 18.11.0)
    container_name: ai-gateway
    restart: unless-stopped
    environment:
      AIGW_GITLAB_URL: https://gitlab.example.com
      AIGW_GITLAB_API_URL: https://gitlab.example.com/api/v4/
      DUO_WORKFLOW_SELF_SIGNED_JWT__SIGNING_KEY: ${AIGW_JWT_SIGNING_KEY}
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
      AWS_REGION: ${AWS_REGION:-us-east-1}
      AIGW_LOGGING__LEVEL: INFO
      DUO_WORKFLOW_LOGGING__LEVEL: INFO
    ports:
      - "5052:5052"
      - "50052:50052"
    deploy:
      resources:
        limits:
          memory: 2048M
        reservations:
          memory: 512M
    healthcheck:
      test: ["CMD", "curl", "--silent", "--fail", "http://localhost:5052/monitoring/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

AI Gateway 시작#

cd /srv/enterprise-sidecar
sudo docker compose up -d

AI Gateway 상태 확인#

# Check container is running
sudo docker ps | grep ai-gateway

# Check HTTP health endpoint (empty JSON means healthy)
curl --silent "http://localhost:5052/monitoring/healthz"

# Check logs for errors
sudo docker logs ai-gateway --tail 20

4단계: AI Gateway TLS 구성#

AI Gateway에는 HTTPS(Chat 및 Code Suggestions용)와 gRPC TLS(DAP 플로우용)가 필요합니다. GitLab에 내장된 NGINX를 리버스 프록시로 사용하여 Let's Encrypt 인증서를 공유하세요.

Let's Encrypt에 AI Gateway 서브도메인 추가#

GitLab 구성을 편집하세요.

sudo docker exec -it gitlab editor /etc/gitlab/gitlab.rb

letsencrypt 섹션을 찾아 alt_names를 추가하세요.

letsencrypt['alt_names'] = ['aigw.example.com']

레지스트리 서브도메인 등 이미 다른 alt_names가 있다면 기존 배열에 aigw.example.com을 추가하세요.

letsencrypt['alt_names'] = ['registry.example.com', 'aigw.example.com']

새 SAN을 포함하도록 인증서를 갱신하세요.

sudo docker exec gitlab gitlab-ctl renew-le-certs

인증서에 AI Gateway 서브도메인이 포함되었는지 확인하세요.

echo | openssl s_client -connect gitlab.example.com:443 2>/dev/null | \
  openssl x509 -noout -ext subjectAltName

출력에 DNS:aigw.example.com이 표시되어야 합니다.

NGINX 프록시 구성 생성#

호스트에 프록시 구성 파일을 생성하세요.

cat << 'NGINX' | sudo tee /srv/gitlab/config/nginx/aigw-proxy.conf
# AI Gateway reverse proxy: HTTPS for HTTP API, gRPC TLS for DAP

# HTTP API: Duo Chat, Code Suggestions
server {
    listen 443 ssl;
    server_name aigw.example.com;

    ssl_certificate /etc/gitlab/ssl/gitlab.example.com.crt;
    ssl_certificate_key /etc/gitlab/ssl/gitlab.example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://172.17.0.1:5052;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_read_timeout 600s;
        proxy_send_timeout 600s;
    }

    location /monitoring/healthz {
        proxy_pass http://172.17.0.1:5052/monitoring/healthz;
        access_log off;
    }
}

# gRPC TLS: DAP / Duo Agent Platform flows
server {
    listen 8443 ssl http2;
    server_name aigw.example.com;

    ssl_certificate /etc/gitlab/ssl/gitlab.example.com.crt;
    ssl_certificate_key /etc/gitlab/ssl/gitlab.example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        grpc_pass grpc://172.17.0.1:50052;
        grpc_read_timeout 600s;
        grpc_send_timeout 600s;
    }
}
NGINX

172.17.0.1은 Docker의 기본 브리지 게이트웨이 IP입니다. GitLab 컨테이너 내부에서 이 IP를 통해 호스트 머신과 AI Gateway 컨테이너의 공개 포트에 접근할 수 있습니다.

GitLab NGINX에 구성 포함#

구성 파일을 컨테이너 내 NGINX 런타임 디렉터리로 복사하세요.

sudo docker exec gitlab mkdir -p /var/opt/gitlab/nginx/conf
sudo docker cp /srv/gitlab/config/nginx/aigw-proxy.conf \
  gitlab:/var/opt/gitlab/nginx/conf/aigw-proxy.conf
Note

파일을 /etc/gitlab/nginx/에 두지 마세요. gitlab.rbcustom_nginx_config에서 참조하는 파일만 로드됩니다. 런타임 디렉터리는 /var/opt/gitlab/nginx/conf/입니다.

gitlab.rb에 include 지시어를 추가하세요.

sudo docker exec -it gitlab editor /etc/gitlab/gitlab.rb

nginx['custom_nginx_config'] 행을 찾거나 추가하세요.

nginx['custom_nginx_config'] = "include /var/opt/gitlab/nginx/conf/aigw-proxy.conf;"

KeyCloak 프록시 등 이미 사용자 정의 NGINX 구성이 있다면 세미콜론으로 연결하세요.

nginx['custom_nginx_config'] = "include /var/opt/gitlab/nginx/conf/keycloak-proxy.conf; include /var/opt/gitlab/nginx/conf/aigw-proxy.conf;"

GitLab 재구성#

sudo docker exec gitlab gitlab-ctl reconfigure

TLS 확인#

# HTTPS for AI Gateway HTTP API
curl --silent "https://aigw.example.com/monitoring/healthz"
# Expected: {}

# gRPC TLS for DAP
openssl s_client -connect aigw.example.com:8443 < /dev/null 2>/dev/null | \
  grep "Verify return code"
# Expected: Verify return code: 0 (ok)

5단계: AWS Bedrock 연결#

Bedrock용 IAM 사용자 생성#

AWS 콘솔에서 IAM > Users > Create user로 이동하세요.

  • 이름: gitlab-bedrock(또는 유사한 이름)

  • 권한: AmazonBedrockFullAccess 관리형 정책 연결

액세스 키를 생성하세요(사용 사례: "Application running outside AWS"). 액세스 키 ID시크릿 액세스 키를 저장하세요.

EC2 인스턴스에 Bedrock 권한이 있는 IAM 역할이 있다면 액세스 키를 건너뛸 수 있습니다. AI Gateway는 인스턴스 프로파일을 자동으로 사용합니다.

Bedrock에서 Anthropic 모델 활성화#

이 단계는 필수이며 많은 사람이 놓치는 부분입니다.

  • AWS 콘솔 > Amazon Bedrock > Providers > Anthropic으로 이동하세요.

  • Submit use case details 양식을 작성하세요.

  • 활성화까지 약 15분을 기다리세요.

Note

이 양식 없이는 Anthropic 모델에 대한 모든 Bedrock API 호출에서 다음 오류가 반환됩니다. "Model use case details have not been submitted for this account." 기존 "Model access" 페이지는 폐기되었습니다. 모델은 첫 번째 호출 시 자동으로 활성화되지만, Anthropic 모델은 사용 사례 양식이 필요합니다.

모델의 추론 프로파일 ID 찾기#

최신 Claude 모델(Claude 4.5 Sonnet 이상)은 직접 모델 ID 대신 추론 프로파일 ID가 필요합니다.

aws bedrock list-inference-profiles --region us-east-1 --output json | \
  python3 -c "
import sys, json
profiles = json.load(sys.stdin)['inferenceProfileSummaries']
for p in profiles:
    if 'claude' in p['inferenceProfileId'].lower():
        print(p['inferenceProfileId'])
"
Note

기본 모델 ID(anthropic.claude-sonnet-4-6)가 아닌 us. 접두사(예: us.anthropic.claude-sonnet-4-6)를 사용하세요.

모델 식별자 결과
bedrock/anthropic.claude-sonnet-4-6 400 Bad Request: "on-demand throughput isn't supported"
bedrock/us.anthropic.claude-sonnet-4-6 작동함

us. 접두사는 미국 전용 리전으로 라우팅합니다. global. 접두사는 활성화된 모든 리전에 걸쳐 라우팅합니다.

애플리케이션 추론 프로파일 ARN 사용#

팀이나 프로젝트별 비용 할당 또는 지출 추적을 원한다면 추론 프로파일 ID 대신 애플리케이션 추론 프로파일 ARN을 모델 식별자로 사용하세요. 다음 형식을 사용하세요.

bedrock/converse/arn:aws:bedrock:<region>:<account-id>:application-inference-profile/<id>

converse/ 접두사는 ARN 기반 식별자에 필요한 Amazon Bedrock Converse API를 통해 요청을 라우팅합니다.

자격 증명으로 AI Gateway 재시작#

아직 하지 않았다면 AWS 자격 증명을 /srv/enterprise-sidecar/.env에 추가한 뒤 재시작하세요.

cd /srv/enterprise-sidecar
sudo docker compose down ai-gateway
sudo docker compose up -d ai-gateway

6단계: GitLab 관리자 설정 구성#

AI Gateway URL 설정#

Admin > GitLab Duo로 이동한 후 Change configuration을 선택하세요.

설정
연결 방법 GitLab Self-Managed를 통한 간접 연결
로컬 AI Gateway URL https://aigw.example.com
로컬 DAP 서비스 URL aigw.example.com:8443
AI Gateway 요청 타임아웃 300(초)
Note

기본 타임아웃 60초는 Bedrock에서 너무 짧습니다. 단일 DAP 플로우는 5~10분이 소요될 수 있습니다. 최소 300으로 설정하세요.

Save changes를 선택하세요.

상태 확인 실행#

같은 페이지에서 Run health check를 선택하세요. 다음 네 가지 항목이 녹색으로 표시되어야 합니다.

확인 항목 예상 결과
AI Gateway Connected
Network Reachable
Code Suggestions Available
DAP Available

자체 호스팅 모델 추가#

Admin > GitLab Duo > Configure models for GitLab Duo로 이동하세요.

Add self-hosted model을 선택하고 다음을 입력하세요.

필드
배포 이름 Bedrock Claude Sonnet 4.6(또는 설명적인 이름)
플랫폼 Amazon Bedrock
모델 패밀리 Claude
모델 식별자 bedrock/us.anthropic.claude-sonnet-4-6
Note

모델 식별자는 반드시 bedrock/으로 시작해야 합니다.

Test connection을 선택하세요. 다음 메시지가 표시되어야 합니다. "Successfully connected to the self-hosted model."

"400 Bad Request"가 표시되면 잘못된 모델 식별자를 사용하고 있는 것입니다. 직접 모델 ID가 아닌 추론 프로파일 ID(us.anthropic.claude-sonnet-4-6)를 사용하세요.

Add model을 선택하세요.

기능에 모델 할당#

같은 페이지에서 AI-native features 탭을 선택하세요.

Bedrock을 통해 라우팅할 각 기능에 대해 드롭다운 목록에서 자체 호스팅 모델을 선택하세요.

기능 권장 할당
GitLab Duo Agent Platform > Agents & flows Bedrock Claude Sonnet 4.6
GitLab Duo Agent Platform > Agentic Chat Bedrock Claude Sonnet 4.6
Code Suggestions GitLab 관리(기본값) 또는 Bedrock
Chat GitLab 관리(기본값) 또는 Bedrock
Code Review GitLab 관리(기본값) 또는 Bedrock

먼저 DAP 기능만 Bedrock에 할당하고 Chat과 Code Suggestions는 GitLab 관리 기본값으로 유지하세요. 이렇게 하면 일상적인 개발자 경험에 영향을 주지 않고 Bedrock 연결을 검증할 수 있습니다. 모든 것이 정상적으로 작동하는 것을 확인한 후 더 많은 기능을 전환하세요.

7단계: DAP 플로우를 위한 러너 등록#

DAP 플로우는 CI/CD 파이프라인을 생성합니다. 등록된 러너가 없으면 DAP 플로우는 무기한 대기 상태에 머뭅니다.

러너 설치 및 등록#

EC2 인스턴스(또는 별도 머신)에 GitLab Runner를 설치하세요.

curl --location "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install -y gitlab-runner

GitLab 인스턴스에 러너를 등록하세요. Admin > CI/CD > Runners로 이동해 New instance runner를 선택하여 등록 토큰을 받은 후 다음을 실행하세요.

sudo gitlab-runner register \
  --url "https://gitlab.example.com" \
  --token "" \
  --executor docker \
  --docker-image "ruby:3.2" \
  --tag-list "docker" \
  --description "Docker runner for DAP"

자세한 내용은 GitLab Runner 설치러너 생성 및 등록을 참조하세요.

Note

DAP 플로우는 Docker-in-Docker 워크플로를 사용합니다. 러너는 docker executor를 사용해야 합니다.

8단계: 그룹 및 프로젝트에서 Duo 기능 활성화#

6단계의 관리자 수준 구성으로 Duo 기능을 인스턴스 전체에서 사용할 수 있게 되지만, 그룹 및 프로젝트 수준에서도 활성화해야 합니다.

그룹에서 Duo 활성화#

  • 그룹의 Settings > General로 이동하세요.

  • Permissions and group features를 펼치세요.

  • GitLab Duo features 아래에서 Enable GitLab Duo features를 선택하세요.

  • DAP를 사용하려면 Enable experiment and beta featuresAllow flow execution도 선택하세요(활성화할 플로우 유형 체크).

  • Save changes를 선택하세요.

자세한 내용은 GitLab Duo 켜기 또는 끄기를 참조하세요.

프로젝트에서 Duo 활성화#

  • 프로젝트의 Settings > General로 이동하세요.

  • Visibility, project features, permissions를 펼치세요.

  • GitLab Duo 아래에서 Use GitLab Duo features를 켜세요.

  • Save changes를 선택하세요.

자세한 내용은 GitLab Duo 켜기 또는 끄기를 참조하세요.

9단계: 엔드-투-엔드 검증#

상태 확인#

# AI Gateway HTTP health
curl --silent "https://aigw.example.com/monitoring/healthz"
# Expected: {}

# gRPC TLS connectivity
openssl s_client -connect aigw.example.com:8443 < /dev/null 2>/dev/null | \
  grep "Verify return code"
# Expected: Verify return code: 0 (ok)

브라우저에서 Admin > GitLab Duo로 이동해 Change configuration을 선택한 후 Run health check를 선택하세요. 네 가지 항목 모두 녹색이어야 합니다.

Rake 검증 태스크 실행#

sudo docker exec gitlab gitlab-rake "gitlab:duo:verify_self_hosted_setup[your_username]"

이 태스크는 라이선스, 기능 플래그, AI Gateway 연결, 모델 구성 등 전체 체인을 검증합니다.

Note

Rake 태스크의 모델 연결 테스트는 플레이스홀더 URL(bedrockselfhostedmodel.com)을 사용하므로, 배포가 정상적으로 작동하는 상태에서도 실패를 보고할 수 있습니다. 나머지 모든 확인(라이선스, AI Gateway, 기능 할당)은 유효합니다.

Duo Chat 테스트#

Note

일부 AI Gateway 버전에서 Bedrock을 사용하는 Duo Chat이 400 오류 ("This model does not support assistant message prefill")를 반환할 수 있습니다. 이는 Duo Chat에만 영향을 미칩니다. DAP 플로우는 다른 코드 경로를 사용하므로 정상 작동합니다. 이 오류가 발생하면 Chat은 GitLab 관리 모델로 유지하고 DAP 기능에만 Bedrock을 사용하세요.

  • GitLab 인스턴스에서 아무 프로젝트나 여세요.

  • Duo Chat 아이콘을 선택하세요.

  • "What is a merge request?"와 같은 간단한 질문을 하세요.

  • 응답이 오는지 확인하세요.

AI Gateway 로그에서 Bedrock 활동을 확인하세요.

sudo docker logs -f ai-gateway 2>&1 | grep -i "litellm\|bedrock\|chat"

DAP 플로우 테스트#

이것이 진짜 테스트입니다. Bedrock에서 GitLab Duo Agent Platform 플로우를 엔드-투-엔드로 실행합니다.

  • 코드가 있는 프로젝트를 생성하거나 여세요.

  • 이슈를 생성하세요(예: "Add input validation to the login form").

  • 이슈 페이지에서 Duo > Start workflow를 선택하세요.

  • 기다리세요. Bedrock을 사용하는 DAP 플로우는 일반적으로 3~10분이 소요됩니다.

  • 파이프라인을 확인하세요: Build > Pipelines. source: duo_workflow를 찾으세요.

플로우 진행 중 AI Gateway 로그를 확인하세요.

sudo docker logs -f ai-gateway 2>&1 | grep -i "workflow\|bedrock\|litellm"

DAP 플로우 진행 중 예상 로그 출력:

LiteLLM completion() model= us.anthropic.claude-sonnet-4-6; provider = bedrock
Note

플로우가 약 10초 만에 완료되면 문제가 있는 것입니다. 정상적인 플로우는 초가 아닌 분 단위로 소요됩니다. AI Gateway 로그에서 오류를 확인하세요.

10단계: 모니터링(선택 사항)#

AI Gateway Prometheus 메트릭#

AI Gateway는 두 포트에서 메트릭을 노출합니다.

포트 엔드포인트 내용
8082 /metrics AI Gateway(FastAPI) 메트릭: 요청 수, 지연 시간
8083 /metrics DWS 메트릭: gRPC 호출 수

Prometheus 스크래핑을 위해 docker-compose.yml의 ports에 추가하세요.

ports:
  - "5052:5052"
  - "50052:50052"
  - "8082:8082"
  - "8083:8083"

그리고 해당 환경 변수를 추가하세요.

environment:
  AIGW_FASTAPI__METRICS_HOST: "0.0.0.0"
  AIGW_FASTAPI__METRICS_PORT: "8082"
  PROMETHEUS_METRICS__ADDR: "0.0.0.0"
  PROMETHEUS_METRICS__PORT: "8083"

문제 해결#

AI Gateway가 시작되지 않는 경우#

컨테이너가 즉시 종료되거나 상태 확인이 통과되지 않는 경우:

sudo docker logs ai-gateway --tail 50
오류 해결 방법
Image not found latest 태그를 사용했습니다. self-hosted-v18.9.0-ee와 같은 명시적 버전을 사용하세요.
AIGW_GITLAB_URL must be set docker-compose.yml에 환경 변수를 추가하세요.
Connection refused on health check 시작에 30초를 기다리세요. 계속 발생하면 포트 바인딩을 확인하세요.

관리자 UI에서 상태 확인 실패#

확인 항목 일반적인 원인 해결 방법
AI Gateway: Not connected 관리자 설정의 잘못된 URL https://aigw.example.com을 사용하세요(http://, 포트 5052 제외).
Network: Unreachable 컨테이너 내부에서 DNS 미해석 docker exec gitlab dig aigw.example.com으로 확인하세요.
DAP: Unavailable 포트 8443 미공개 --publish 8443:8443으로 GitLab 컨테이너를 재생성하세요.

모델 연결 테스트 시 400 Bad Request#

직접 모델 ID 대신 추론 프로파일 ID를 사용해야 합니다.

bedrock/anthropic.claude-sonnet-4-6bedrock/us.anthropic.claude-sonnet-4-6으로 변경하세요(us. 접두사 주의).

"Model use case details have not been submitted"#

  • AWS 콘솔 > Amazon Bedrock > Providers > Anthropic으로 이동하세요.

  • 사용 사례 세부 정보 양식을 제출하세요.

  • 활성화까지 약 15분을 기다리세요.

  • 재시도하세요.

TLS 오류#

curl "https://aigw.example.com/monitoring/healthz"에서 SSL 오류가 반환되는 경우:

  • gitlab.rbletsencrypt['alt_names']aigw.example.com을 추가했는지 확인하세요.

  • gitlab-ctl renew-le-certs를 실행했는지 확인하세요.

  • NGINX 구성에 올바른 인증서 경로가 사용되고 있는지 확인하세요.

  • NGINX 구성 파일이 /var/opt/gitlab/nginx/conf/에 있는지 확인하세요(/etc/gitlab/nginx/ 아님).

  • gitlab.rbcustom_nginx_config가 해당 파일을 참조하는지 확인하세요.

DAP 플로우가 시작되지 않는 경우#

Start workflow를 선택했는데 파이프라인이 나타나지 않는 경우:

  • 러너가 등록되어 온라인 상태인지 확인하세요(Admin > CI/CD > Runners). 7단계를 참조하세요.

  • 그룹 및 프로젝트에 Duo가 활성화되어 있는지 확인하세요. 8단계를 참조하세요.

  • 사용자에게 GitLab 크레딧 또는 Duo 시트가 있는지 확인하세요(Admin > GitLab Duo > Seat assignment).

  • GitLab 컨테이너에 포트 8443이 공개되어 있는지 확인하세요.

NGINX 구성이 적용되지 않는 경우#

gitlab.rb를 편집하고 reconfigure를 실행한 후:

  • 런타임 디렉터리에 파일이 있는지 확인하세요.
sudo docker exec gitlab ls -la /var/opt/gitlab/nginx/conf/
  • 파일이 없으면 다시 복사하세요.
sudo docker cp /srv/gitlab/config/nginx/aigw-proxy.conf \
  gitlab:/var/opt/gitlab/nginx/conf/aigw-proxy.conf
  • reconfigure 후 NGINX를 재시작하세요.
sudo docker exec gitlab gitlab-ctl reconfigure
sudo docker exec gitlab gitlab-ctl restart nginx

관련 항목#