Mac mini의 GitHub Actions 셀프호스트 Runner란?
Mac mini GitHub Actions 셀프호스트 Runner는 Apple Silicon에서 빌드를 실행하는 자체 관리 CI 환경입니다. GitHub 호스팅 macOS Runner 대신 캐시 영속화·빠른 iOS 빌드·Xcode 완전 제어가 가능합니다—Mac 임대·클라우드 Mac mini에 적합합니다.
Mac mini에서 GitHub Actions Runner를 구축하려면?
- macOS에 전용
ci사용자 생성 - GitHub Actions Runner 패키지 설치
- 등록 토큰으로 Runner 구성
- launchd 서비스로 부팅 시 자동 시작
- 라벨로 workflow 라우팅
- 빈 Job으로 검증
검색 의도(5유형)
- 정의 — Mac mini 셀프호스트 Runner
- 이유 — iOS CI에 Mac mini 필요(GitHub 호스팅 대비)
- 방법 — 프로덕션 설치(4단계 + launchd)
- 보안 — ci 사용자 격리 + fork PR 방어
- 성능 — 캐시 최적화 30%–60% 단축
GitHub Actions 셀프호스트 Runner(Mac mini版)
Mac mini GitHub Actions 셀프호스트 Runner는 로컬 또는 클라우드 Mac mini에서 workflow Job을 실행하는 자체 CI 환경입니다.
Mac mini에서 Runner의 5가지 핵심 이점:
- ✔ 빌드 캐시 장기 보존(DerivedData/CocoaPods/SPM)
- ✔ Xcode 버전 완전 통제(Golden Image 고정)
- ✔ CI 비용 고정(분당 과금 없음)
- ✔ iOS 빌드 대폭 단축(핫 빌드 5–6분)
- ✔ 엔터프라이즈 격리(전용 ci 사용자+Keychain 분리)
iOS CI에 Mac mini 셀프호스트 Runner가 필수인 이유
GitHub 호스팅 Runner 3대 병목
| 문제 | GitHub 호스팅 macOS | Mac mini 셀프호스트 |
|---|---|---|
| 빌드 캐시 | 매 Job 리셋(무상태) | 영속(Pods/DerivedData on SSD) |
| Xcode 버전 | GitHub 업그레이드 추종 | 완전 고정(Golden Image) |
| CI 비용 | 분당 과금 | 고정(월 Mac 임대/자가) |
| 빌드 속도 | 콜드 8–12분 | 핫 5–6분 |
핵심 결론
GitHub 호스팅 = 무상태
Mac mini Runner = 기억 있는 CI
iOS CI 성능 차이의 본질. 관련: Flutter iOS CI 최적화: 28분→9분.
Mac mini CI Runner 프로덕션 3계층 아키텍처
전체 모델
┌──────────────────────────────┐
│ Layer 1: launchd daemon │ ← reliability (auto-restart / crash recovery)
├──────────────────────────────┤
│ Layer 2: ci user isolation │ ← security (Keychain / permission boundary)
├──────────────────────────────┤
│ Layer 3: label routing │ ← maintainability (workflow → Runner)
└──────────────────────────────┘
1계층 — launchd 상시 실행(안정성 핵심)
launchd = macOS systemd. 자동 재시작·재부팅 복구·크래시 복구·데몬급 실행.
필수 plist 3항목:
RunAtLoad = true— 로그인 후 자동 시작KeepAlive = true— 크래시 후 자동 재기동WorkingDirectory— 필수 설정(오프라인 최다 원인)
LaunchAgents 사용(LaunchDaemons 아님)—iOS CI는 코드 서명에 사용자 Keychain 필요. macOS 자동 로그인으로 ci 세션 복귀.
| 방식 | 재부팅 복구 | 크래시 복구 | 프로덕션 신뢰성 |
|---|---|---|---|
| nohup / screen | ❌ | ❌ | 부적합 |
| launchd | ✅ | ✅ | 프로덕션급 |
2계층 — CI 사용자 격리(보안 핵심)
관리자 계정을 쓰면 안 되는 이유?
sudo가능 → 공격면 무한 확대- Keychain 읽기 → 인증서 유출
- fork PR 악성 스크립트 → 전체 침해
권장: 전용 ci 사용자
- ❌ sudo 없음, 관리자 그룹 제외
- ✅ 독립 Keychain(
/Users/ci/Library/Keychains/) - ✅
_developer그룹(xcodebuild/simctl)
sudo dscl . -create /Users/ci UserShell /bin/zsh
sudo dscl . -create /Users/ci RealName "CI Runner"
sudo dscl . -create /Users/ci UniqueID 505
sudo dscl . -create /Users/ci PrimaryGroupID 20
sudo dscl . -create /Users/ci NFSHomeDirectory /Users/ci
sudo createhomedir -c -u ci
sudo passwd ci
sudo dscl . -append /Groups/_developer GroupMembership ci
3계층 — Runner 라벨 라우팅
라벨 체계 = CI 스케줄러. 3계층 구조 권장:
runs-on: [self-hosted, macOS, ARM64, flutter-ios, xcode-16, m4]
┌──────────────┐ ┌───────────────────┐ ┌──────────────┐
│ Platform │ │ Workload │ │ Hardware │
│ self-hosted │ │ flutter-ios │ │ m4, 16gb │
│ macOS, ARM64 │ │ xcode-16 │ │ region:tokyo │
└──────────────┘ └───────────────────┘ └──────────────┘
라벨은 AND 매칭; workflow 완전 일치; 동일 라벨 다중 머신 = 자동 로드밸런싱.
Mac mini Runner 프로덕션 설치 절차
1단계 — Runner 설치
# Run as ci user
mkdir -p ~/actions-runner && cd ~/actions-runner
curl -fsSL -O https://github.com/actions/runner/releases/download/v2.316.1/actions-runner-osx-arm64-2.316.1.tar.gz
tar xzf actions-runner-osx-arm64-2.316.1.tar.gz
2단계 — 등록
./config.sh \
--url https://github.com/your-org/your-repo \
--token YOUR_REGISTRATION_TOKEN \
--name "$(hostname -s)" \
--labels "self-hosted,macOS,ARM64,flutter-ios,xcode-16,m4,16gb" \
--work _work \
--replace \
--unattended
3단계 — launchd 설정(핵심)
~/Library/LaunchAgents/com.kvmboot.github-runner.plist에 저장:
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0"><dict>
<key>Label</key><string>com.kvmboot.github-runner</string>
<key>ProgramArguments</key>
<array><string>/Users/ci/actions-runner/run.sh</string></array>
<key>WorkingDirectory</key><string>/Users/ci/actions-runner</string>
<key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
</dict>
<key>StandardOutPath</key><string>/Users/ci/Library/Logs/github-runner.log</string>
<key>StandardErrorPath</key><string>/Users/ci/Library/Logs/github-runner.err</string>
</dict></plist>
/. WorkingDirectory 없으면 .credentials 미발견으로 조용히 종료—GitHub는 오프라인, launchctl list는 loaded.
4단계 — 시작
launchctl load ~/Library/LaunchAgents/com.kvmboot.github-runner.plist
launchctl list | grep github-runner
tail -f ~/Library/Logs/github-runner.log # expect: Listening for Jobs
네트워크·프록시(아웃바운드 허용)
Runner는 *.github.com, api.github.com, *.actions.githubusercontent.com, objects.githubusercontent.com 접근 필수. 프록시는 plist EnvironmentVariables에 주입. IP 범위: api.github.com/meta.
프로덕션 보안 강화
최대 위험은 공개 저장소 fork PR. 3중 방어:
1. 저장소级 Runner(조직级 금지)
저장소级 등록으로 조직横向 확산 방지—한 repo 침해 시 모든 Keychain/Secrets 노출.
2. Fork PR 보호
GitHub repo → Settings → Actions → General에서 활성화:
외부 협력자 fork PR workflow 승인 요구
fork PR이 셀프호스트 Runner에서 자동 실행되지 않도록. 참고: 클라우드 Mac CI 보안 격리(fork PR 공격면).
3. Secrets 격리
- ❌
.p12/.env를 ci 홈에 두지 않음 - ❌ workflow에 API Key 하드코딩 금지
- ✅ GitHub Secrets+런타임 주입; 인증서는 Fastlane match+Keychain
concurrency:
group: flutter-ios-${{ github.ref }}
cancel-in-progress: true
CI 성능 최적화(iOS/Flutter)
Mac mini 셀프호스트 Runner는 로컬 캐시 영속으로 iOS CI 최적화를 증폭:
캐시 3계층
- CocoaPods(
~/.cocoapods+ios/Pods) - DerivedData(고정
-derivedDataPath) - SPM/Flutter pub
| 최적화 | 전형 단축 | 비고 |
|---|---|---|
| Pods 캐시 | 약 40% 단축 | 콜드 28분→19분 |
| DerivedData | 약 30% 단축 | 핫 12분→6분 |
| Xcode 고정 | 안정성 향상 | 예기치 않은 파괴 변경 제거 |
전략 전문: iOS CI 캐시 설계(DerivedData/CocoaPods/SPM).
원클릭 Runner 재구축(DR)
macOS 메이저 업그레이드·Golden Image 드리프트·보안 사건 후 rebuild_runner.sh로 약 5분 재구축:
#!/usr/bin/env zsh
set -euo pipefail
CI_USER="ci"
PLIST_DEST="/Users/$CI_USER/Library/LaunchAgents/com.kvmboot.github-runner.plist"
sudo -u "$CI_USER" launchctl unload "$PLIST_DEST" 2>/dev/null || true
sudo -u "$CI_USER" bash -c "cd /Users/$CI_USER/actions-runner && ./config.sh remove --token \$(gh api -X POST /repos/your-org/your-repo/actions/runners/remove-token --jq '.token') 2>/dev/null || true"
sudo -u "$CI_USER" zsh /Users/$CI_USER/scripts/setup_runner.sh
sudo -u "$CI_USER" launchctl load "$PLIST_DEST"
echo "[OK] Runner rebuilt."
프로덕션 준비 검증(체크리스트)
검수 전 기반 환경 확인(클라우드 Mac 온보딩 체크리스트).
레벨 1 — Runner 온라인
- ✅ GitHub UI Idle
- ✅
launchctl list | grep github-runner정상 PID - ✅ 로그에
Listening for Jobs
레벨 2 — 빈 Job
runs-on: [self-hosted, macOS, flutter-ios]
- ✅ 30초 내 할당(장기 대기 없음)
- ✅ Runner 이름·OS 버전 출력
레벨 3 — 툴체인
xcodebuild -version # matches Golden Image
flutter --version
pod --version
| 증상 | 원인 | 조치 |
|---|---|---|
| Runner 오프라인 | WorkingDirectory 미설정 | .err 확인, plist 필드 추가 |
| Job 대기 | 라벨 불일치 | runs-on vs 등록 라벨 비교 |
| 크래시 루프 | PATH 누락 | plist EnvironmentVariables 보완 |
프로덕션 포지셔닝(E-E-A-T)
본 설계는 프로덕션 CI 대상: iOS는 Golden Image 고정, fork PR 격리, 재부팅·크래시 내구.
3계층: macOS(launchd)·실행 격리(ci 샌드박스)·라우팅(GitHub Actions 라벨).
kvmboot 클라우드 Mac 검증 Mac mini CI—월간 Runner·일일 릴리스 스프린트. Mac 임대 일일 검증→월간.
FAQ(롱테일)
Mac mini에서 GitHub Actions Runner 가능?
예. iOS CI 대표 프로덕션 구성. launchd로 GitHub Actions 셀프호스트 Runner(macOS) 장기 안정 운영.
셀프호스트가 GitHub 호스팅보다 얼마나 빠른가?
iOS CI에서 보통 30%–60% 단축. CocoaPods/DerivedData 영속화—호스팅은 매 Job 신규 환경.
launchd vs brew services?
launchd는 macOS 시스템 데몬(systemd 상당); brew services는 래퍼로 비 Homebrew Runner에 부적합. 프로덕션은 plist 직접 작성.
Runner 오프라인排查?
우선순위:
launchctl list | grep github-runner- plist WorkingDirectory
runs-on라벨 완전 일치
Mac mini 1대에 Runner 몇 개?
16GB→1 권장; 24GB→1–2(경량). xcodebuild 메모리 포화—다중은 concurrency 필수.
클라우드 Mac mini에 Runner 배포
Mac mini GitHub Actions 셀프호스트 Runner 최적 호스트는 Apple Silicon M4: ARM64 Xcode, 통합 메모리, 대기 약 4W. SIP·Gatekeeper·독립 Keychain이 Runner 보안 격리 강화—fork PR 폭발 반경은 ci 홈 내부로.
Flutter iOS CI 이전 검토? kvmboot 클라우드 Mac mini M4 일일 검증→월간 Runner—요금제 보기.