본문 바로가기
Infra2025년 5월 15일8분 읽기

GitHub Actions Self-Hosted Runner 구축과 보안

YS
김영삼
조회 654

Self-Hosted Runner를 사용하는 이유

GitHub-hosted Runner는 편리하지만, 빌드 시간 제한(6시간), 제한된 하드웨어, 프라이빗 네트워크 접근 불가 등의 한계가 있습니다. Self-Hosted Runner는 자체 인프라에서 실행되어 GPU 빌드, 사내 네트워크 접근, 커스텀 환경이 필요할 때 사용합니다.

기본 설치

# 러너 다운로드 및 설정
mkdir actions-runner && cd actions-runner

curl -o actions-runner-linux-x64-2.311.0.tar.gz -L \
  https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz

tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz

# 러너 등록 (GitHub Settings > Actions > Runners에서 토큰 발급)
./config.sh --url https://github.com/ORG/REPO \
  --token AXXXXXXXXXXXXXXX \
  --name "build-server-01" \
  --labels "linux,x64,gpu" \
  --work "_work" \
  --runnergroup "default"

# 서비스로 설치 (자동 시작)
sudo ./svc.sh install
sudo ./svc.sh start
sudo ./svc.sh status

Docker 기반 격리 실행

# Dockerfile for Runner
FROM ubuntu:22.04

RUN apt-get update && apt-get install -y \
    curl jq git docker.io nodejs npm \
    && rm -rf /var/lib/apt/lists/*

# 비루트 사용자 생성
RUN useradd -m runner && usermod -aG docker runner

USER runner
WORKDIR /home/runner

# 러너 설치
RUN curl -o actions-runner.tar.gz -L \
  https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz \
  && tar xzf actions-runner.tar.gz \
  && rm actions-runner.tar.gz

COPY entrypoint.sh .
ENTRYPOINT ["./entrypoint.sh"]

# entrypoint.sh
#!/bin/bash
./config.sh --url "$REPO_URL" --token "$RUNNER_TOKEN" \
  --labels "$RUNNER_LABELS" --ephemeral --disableupdate
./run.sh

Docker Compose로 멀티 러너

# docker-compose.yml
services:
  runner-1:
    build: .
    environment:
      REPO_URL: https://github.com/org/repo
      RUNNER_TOKEN: ${RUNNER_TOKEN}
      RUNNER_LABELS: "linux,docker"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

  runner-2:
    build: .
    environment:
      REPO_URL: https://github.com/org/repo
      RUNNER_TOKEN: ${RUNNER_TOKEN}
      RUNNER_LABELS: "linux,docker"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

워크플로에서 사용

# .github/workflows/build.yml
name: Build and Deploy
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: [self-hosted, linux, x64]
    steps:
      - uses: actions/checkout@v4

      - name: Build Docker Image
        run: |
          docker build -t myapp:${{ github.sha }} .
          docker push registry.internal/myapp:${{ github.sha }}

      - name: Deploy to Internal Server
        run: |
          ssh deploy@internal-server "docker pull registry.internal/myapp:${{ github.sha }}"
          ssh deploy@internal-server "docker service update --image registry.internal/myapp:${{ github.sha }} myapp"

보안 강화 체크리스트

항목위험대응
퍼블릭 레포에서 사용악성 PR이 러너에서 코드 실행퍼블릭 레포에서는 Self-Hosted 금지
시크릿 노출환경 변수로 시크릿 유출--ephemeral 모드 사용
Docker 소켓 마운트컨테이너 탈출 -> 호스트 접근rootless Docker 또는 별도 Docker-in-Docker
빌드 아티팩트 잔존이전 빌드 데이터 유출--ephemeral 또는 작업 후 정리
네트워크 접근내부 서비스 무단 접근러너 전용 네트워크 격리
# 보안 설정 예시
# 1. Ephemeral 러너: 작업 1개 실행 후 자동 제거
./config.sh --ephemeral ...

# 2. 러너 그룹으로 접근 제어 (Organization 레벨)
# Settings > Actions > Runner groups
# - production-runners: 특정 레포만 접근 허용

# 3. 필수 워크플로 승인
# Settings > Actions > General
# - "Require approval for all outside collaborators"

# 4. 러너 토큰 자동 갱신 스크립트
#!/bin/bash
TOKEN=$(curl -s -X POST \
  -H "Authorization: token $PAT" \
  "https://api.github.com/orgs/ORG/actions/runners/registration-token" \
  | jq -r .token)
./config.sh --url https://github.com/ORG --token "$TOKEN" --replace --ephemeral
  • 퍼블릭 레포에서는 절대 Self-Hosted Runner를 사용하지 마세요 — 포크 PR로 임의 코드 실행이 가능합니다
  • Ephemeral 모드를 강력히 권장합니다: 각 작업이 깨끗한 환경에서 실행되고 완료 후 폐기됩니다
  • 대규모 환경에서는 actions-runner-controller(ARC)로 Kubernetes에서 자동 스케일링을 구성하세요

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록