에이전틱 개발 파이프라인 – 06. GitHub 대신 Gitea: 셀프호스팅 CI/CD (Gitea Actions)

2026.08.24

·

TL;DR

  • Gitea는 운영 Proxmox 위의 단일 목적 VM에서 셀프호스팅한다 — 코드와 AI 산출물이 외부 서버를 거치지 않는다.
  • Claude Code가 스스로 이슈를 등록하고, MSA 서비스별 담당을 지정하며, 그 이슈 안에서 개발을 진행한다.
  • Gitea Actions는 GitHub Actions 문법 호환 — 빌드→레지스트리 푸시→배포 흐름을 그대로 구성할 수 있다.

“코드는 GitHub에 있는데 AI가 거기 접근해도 되나?” — 에이전틱 파이프라인을 처음 설계하는 팀이 가장 먼저 막히는 지점이다. 소스코드와 AI 작업 산출물이 외부 클라우드를 경유하는 순간 데이터 주권 문제가 생긴다. 주니크(GUNIQ)의 답은 Gitea를 운영 Proxmox 위의 단일 목적 VM에 직접 올리는 것이었다.

그리고 하나 더 — Gitea는 단순한 “사내 GitHub 대체재”가 아니다. Claude Code가 이슈를 직접 등록하고, 진행 상황을 코멘트로 남기고, PR을 올리는 에이전틱 프로젝트 관리 허브로 쓰인다. AI 도구가 개발 주체가 될수록, 그 AI를 추적·소통·조율하는 관리 체계가 성패를 가른다. 이번 편에서 그 흐름 전체를 정리한다.

Sponsored


왜 셀프호스팅 Gitea인가 — GitHub과 비교

GitHub은 훌륭한 플랫폼이다. 그러나 에이전틱 개발 환경에서 셀프호스팅이 더 나은 경우가 분명히 있다.

항목GitHub (SaaS)Gitea (셀프호스팅)
코드 저장 위치GitHub 서버 (미국)우리 Proxmox VM — 외부 전송 없음
AI 산출물 외부 전송있음없음 (데이터 주권 보장)
비용팀 플랜 유료무료 (서버 비용만)
Actions 문법GitHub Actions동일 문법 (act_runner)
이슈·PR있음있음 (API 호환)
메모리 요구512MB 내외 (경량 Go 바이너리)

AI 에이전트가 코드 생성의 주체가 될수록, 그 코드가 담는 비즈니스 맥락의 민감도도 함께 높아진다. 데이터 주권을 지키는 것 자체가 하나의 아키텍처 결정이다.


Gitea 설치 — Proxmox VM에 docker-compose로

주니크 운영 환경은 Proxmox 서버 1노드(듀얼 Xeon E5-2683 v4, 32코어/64스레드, DDR4 128GB) 위에 단일 목적 VM들을 만들어 서비스를 분리한다. Gitea도 그 중 하나의 전용 VM이다. “사내 어딘가의 컨테이너”가 아니라 Proxmox가 관리하는 독립 VM — 같은 방식으로 PSTA(프로젝트 추적 앱)도 별도 VM에 올린다.

VM 내부에서는 docker-compose로 Gitea를 구동한다. 데이터 경로는 파티션 정책에 따라 /data/gitea에 고정하고, Docker data-root도 /data/docker로 옮겨 이미지·볼륨이 OS 파티션(/)을 위협하지 못하게 한다. (파티션 설계 철학은 이 글에서 상세히 다뤘다 — 리스크와 관심사를 파티션 단위로 격리한다는 사고는 프로젝트 관리에서 WBS를 분리하는 원칙과 정확히 같다.)

# /app/gitea/docker-compose.yml (Gitea VM 내부 — 예시)
services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    restart: unless-stopped
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=sqlite3
      # 운영 규모라면 외부 PostgreSQL로 교체 권장
    volumes:
      - /data/gitea:/data          # 저장소·설정 → /data 파티션
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"   # 웹 UI
      - "2222:22"     # SSH git (호스트 22와 충돌 방지)
docker compose up -d

브라우저에서 http://서버IP:3000에 접속하면 초기 설정 마법사가 뜬다. 관리자 계정을 만들면 바로 사용 가능하다. Nginx 리버스 프록시를 앞에 두면 도메인 + HTTPS를 붙일 수 있다.


★ Gitea = 에이전틱 프로젝트 관리 허브

Gitea를 단순한 코드 저장소로만 쓰면 절반의 가치만 쓰는 것이다. 에이전틱 개발에서 Gitea의 진가는 이슈 기반 프로젝트 관리 허브로 쓸 때 나온다.

레포지토리 구조 잡기

먼저 서버 레포지토리를 Gitea에 생성한다. 인프라 설정·docker-compose·nginx 설정 등 서버 전체를 관리하는 코드가 여기 들어간다. MSA 구조라면 서비스별로 앱 전용 레포지토리를 추가한다. iam(인증), api-search(검색 백엔드), front-web(통합 프론트) 같은 식이다.

Claude Code가 이슈를 직접 등록한다

이 부분이 에이전틱 개발에서 Gitea가 갖는 핵심 역할이다. Claude Code는 Gitea REST API를 통해 스스로 이슈를 등록할 수 있다. 작업 지시를 받으면 태스크를 이슈로 분해하고, MSA 각 서비스의 개발 담당(레이블·담당자)을 지정하며, 그 이슈 안에서 실제 작업 진행 상황을 코멘트로 남긴다. 사람 팀이 GitHub 이슈로 협업하듯, Claude Code가 Gitea 이슈로 에이전틱 협업하는 구조다.

이슈·PR 히스토리에는 Claude Code가 남긴 작업 로그, 선택 근거, 블로커가 코멘트로 쌓인다. 나중에 “왜 이 구조를 택했는가”를 역추적할 때 커밋 로그보다 훨씬 풍부한 맥락이 된다.

✦ guniq 시각 — AX와 프로젝트 관리의 연결
개발 환경의 AX(AI Transformation) 수준은 결국 프로젝트 관리 능력과 비례한다. AI가 개발 주체가 될수록, 그 AI를 조율하고 추적하고 소통시키는 관리 체계가 성패를 가른다. PSTA 같은 방법론도 좋지만, 도구 레벨에서 가장 직접적인 구현은 이슈 트래커다. Gitea 이슈가 그 실행 레이어다.


Gitea Actions — 빌드 → 레지스트리 → 배포

Gitea는 GitHub Actions와 문법이 호환되는 Gitea Actions를 내장하고 있다. 실행 환경은 act_runner를 등록해 구동한다.

① Gitea 서버에서 Actions 활성화

# /data/gitea/gitea/conf/app.ini 에 추가
[actions]
ENABLED = true
docker compose restart gitea

② act_runner 등록 (예시)

Gitea 웹 UI → 사이트 관리 → Actions → Runners에서 등록 토큰을 발급받는다.

# act_runner 등록 (예시 — 토큰·URL은 실제 값으로 교체)
docker run --rm 
  -v /var/run/docker.sock:/var/run/docker.sock 
  -v /data/gitea-runner:/data 
  gitea/act_runner:latest 
  register 
  --no-interactive 
  --instance http://서버IP:3000 
  --token <발급받은토큰> 
  --name my-runner 
  --labels ubuntu-latest:docker://node:20-bookworm

# 등록 후 데몬 실행
docker run -d 
  --name act_runner 
  --restart unless-stopped 
  -v /var/run/docker.sock:/var/run/docker.sock 
  -v /data/gitea-runner:/data 
  gitea/act_runner:latest daemon

③ 빌드→레지스트리 푸시 워크플로 예시

파이프라인의 큰 그림은 이렇다 — runner가 빌드해 레지스트리에 이미지를 올리고, Proxmox 운영 VM이 그 이미지를 당겨 배포한다. 레지스트리 구성 상세는 다음 편(07)에서 다룬다.

# .gitea/workflows/build.yml (예시 — GitHub Actions와 경로만 다름)
name: Build and Push

on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: 코드 체크아웃
        uses: actions/checkout@v4

      - name: Docker 이미지 빌드
        run: |
          docker build -t registry.example.com/myapp:${{ gitea.sha }} .

      - name: 레지스트리 푸시
        run: |
          echo "${{ secrets.REGISTRY_PASSWORD }}" | 
            docker login registry.example.com 
            -u ${{ secrets.REGISTRY_USER }} --password-stdin
          docker push registry.example.com/myapp:${{ gitea.sha }}

      - name: 운영 VM 배포
        run: |
          ssh deploy@prod-vm 
            "docker pull registry.example.com/myapp:${{ gitea.sha }} && 
             docker compose -f /app/myapp/docker-compose.yml up -d"

워크플로 파일 위치만 .gitea/workflows/로 바꾸면 GitHub Actions용 yaml이 거의 그대로 동작한다. ${{ github.sha }}${{ gitea.sha }}로 교체한다.

참고로 주니크 운영 환경에서 배포 형태는 워크로드별로 다르다 — Spring Boot API는 Docker로 감싸지 않고 JAR(내장 톰캣)로 바로 실행하고, Keycloak·Kong·Elasticsearch 같은 서비스는 Docker로 구동한다. PostgreSQL과 nginx는 소스 설치로 상주한다. 파티션 정책과 같은 사고 — 일의 성격에 맞는 형태를 선택한다.


흔한 함정 3가지

함정 1: runner Docker 소켓 권한

act_runner가 /var/run/docker.sock을 마운트하면 사실상 호스트 root 수준의 접근이 된다. 내부 팀 전용 private 저장소라면 대부분 문제없다. 외부 PR을 자동 실행하는 public 저장소라면 별도 격리 환경을 고려해야 한다.

함정 2: 시크릿 하드코딩

레지스트리 비밀번호·SSH 키·API 토큰을 워크플로 YAML에 직접 쓰면 안 된다. Gitea 저장소 설정 → Secrets에 등록하고 워크플로에서 ${{ secrets.MY_SECRET }}으로 참조한다. GitHub Actions와 동일한 방식이다.

함정 3: 데이터 경로 기본값 방치

Gitea 데이터와 Docker data-root를 기본 경로(/var/lib/gitea, /var/lib/docker)에 두면 OS 파티션이 가득 차는 사고가 난다. 처음부터 /data/gitea·/data/docker로 잡는 것이 가장 안전하다. 볼륨 마운트를 처음 설정할 때 제대로 잡지 않으면 나중에 데이터 마이그레이션이 번거롭다.


GUNIQ 실제 사례

주니크의 파이프라인은 다음 구조다. 개발 서버(구형 워크스테이션 — Intel Xeon E5-2690 v2 20코어, DDR3 64GB, Ubuntu 24, Docker)에서 Claude Code가 코드를 작성하고, 완료된 코드를 Proxmox VM 위의 셀프호스팅 Gitea에 푸시한다. 운영 Proxmox(E5-2683 v4 32코어, DDR4 128GB)의 act_runner가 이를 받아 빌드하고 레지스트리를 경유해 각 Proxmox VM에 배포한다.

개발 서버에는 GPU가 없다. Claude Code는 클라우드 모델이라 로컬 GPU가 불필요하다. 코어 20개·64GB 메모리는 MSA 서비스 컨테이너 여러 개를 동시에 구동하는 데 충분하다 — 여러 서버가 도는 것처럼 컨테이너들이 안정적으로 올라간다.

Gitea 이슈에는 Claude Code가 남긴 작업 로그·선택 근거·PR 참조가 쌓인다. 코드 리뷰와 배포 승인만 사람 손을 탄다. 나중에 “이 서비스를 왜 이렇게 설계했는가”를 역추적할 때 커밋 로그보다 이슈 히스토리가 훨씬 유용하다.


🎓 오늘 할 수 있는 것

  1. docker-compose.yml을 복사하고 볼륨 경로를 /data/gitea로 지정한다.
  2. docker compose up -d → 브라우저 :3000 접속 → 관리자 계정 생성 → 첫 저장소 만들기.
  3. app.ini[actions] ENABLED = true 추가 → 재시작.
  4. act_runner 등록 → Runners 목록에서 “온라인” 확인.
  5. 기존 GitHub Actions YAML을 .gitea/workflows/로 복사 → 커밋·푸시 → Actions 탭에서 결과 확인.

FAQ

Q. GitHub Actions YAML을 그대로 쓸 수 있나?

대부분 그대로 동작한다. 경로만 .github/workflows/.gitea/workflows/로 바꾸면 된다. ${{ github.sha }}처럼 GitHub 전용 컨텍스트 변수는 ${{ gitea.sha }}로 치환한다. actions/checkout, actions/setup-node 등 공식 기본 action은 대부분 정상 동작한다.

Q. Claude Code가 Gitea 이슈를 자동 등록하게 하려면?

Gitea REST API와 토큰 인증을 사용한다. Claude Code 환경에 API 토큰과 Gitea 주소를 설정하면 MCP 서버 또는 직접 API 호출로 이슈 생성·코멘트·라벨 지정을 자동화할 수 있다. 주니크는 자체 Gitea 스킬을 Claude Code에 연결해 이 흐름을 운영 중이다.

Q. Gitea와 GitLab 중 어느 것을 선택해야 하나?

GitLab도 셀프호스팅이 가능하지만 RAM 4GB 이상이 권장되고 무겁다. Gitea는 512MB 내외에서 동작한다. 대규모 팀에 패키지 레지스트리·내장 위키·올인원 기능이 필요하다면 GitLab, 경량·빠른 셋업·코드 저장소 + CI가 목표라면 Gitea가 낫다.

Q. runner를 개발 서버에 두면 안 되나?

기술적으로는 가능하다. 다만 빌드·배포까지 개발 서버가 처리하면 개발 환경과 운영 환경이 섞인다. 주니크는 빌드·배포를 운영 Proxmox runner가 담당하게 분리했다. 개발 서버는 코드 작성과 로컬 테스트에만 집중하는 구조다.


코드를 내 손 안에 두고 싶다면, Gitea는 가장 현실적인 출발점이다. 다음 편에서는 이 코드가 실제로 배포되는 환경 — 레지스트리 구성과 Proxmox VM 분산 배포 구조를 다룬다.

에이전틱 개발 파이프라인 구축, 직접 상담이 필요하다면 → guniq.co.kr/contact


『에이전틱 개발 파이프라인』 시리즈
← 이전: 05. AI가 짠 코드, 어떻게 믿나 (검증 게이트)
→ 다음: 07. Proxmox VM 자동 배포 파이프라인


MORE POSTS

다른 글 보기

테크 랩

에이전틱 개발 파이프라인 – 06. GitHub 대신 Gitea: 셀프호스팅 CI/CD (Gitea Actions)

데이터 주권을 지키는 셀프호스팅 Gitea 설치와 Gitea Actions로 CI/CD를 구성하는 실전 — GitHub Actions 문법 호환.
2026.08.24
테크 랩

에이전틱 개발 파이프라인 – 05. AI가 짠 코드, 어떻게 믿나: 검증 게이트 설계

AI 코드를 완전 위임하지 않고 다층 검증 게이트(셀프체크·CI·AI리뷰·사람 최종판정)로 신뢰를 확보하는 파이프라인 설계.
2026.08.21
테크 랩

에이전틱 개발 파이프라인 – 04. Claude Code로 MSA 설계·구현하기

AI에게 마이크로서비스 경계를 그리게 하는 프롬프트 패턴과, 설계 판단은 사람이 하는 오케스트레이션 방식.
2026.08.20

프로젝트 문의 환영합니다

기획부터 개발, 운영까지 함께 만들어 드립니다.

무료 3분 자가진단

우리 회사, 자체 클라우드가 답일까?

AWS vs 자체 인프라 · 11개 항목 3분 체크