MacでCircleCIのセルフホストrunnerを動かす方法
CircleCI machine runner 3は、CircleCIのHomebrew tapからmacOSにインストールでき、LaunchAgentとして動きます。ネームスペースとリソースクラスを作成し、トークンをコピーしてrunnerのconfig.yamlに書き、サービスをbootstrapします。ジョブからはmachine: trueとresource_class: namespace/nameで指定します。
最初に必要なもの
- CircleCIのOrganization管理者権限。メニューが表示される前に、管理者が「Org」、「Runners」でrunnerの規約に同意する必要があります。
- アカウントに1クレジット以上。CircleCIによると、runnerのジョブはクレジットを使いません。ただしストレージとネットワーク転送には使われることがあります。
- 管理者権限、Homebrew、XcodeのあるApple silicon Mac。
- CircleCIが前提条件に挙げている
sha256sum。brew install coreutilsで入手できます。
1. ネームスペースとリソースクラスを作成する
Webアプリで「Runners」を開き、「Create Resource Class」を選びます。ネームスペースはOrganizationごとに1つです。orbを公開しているなら、すでに持っています。リソースクラスにはmac-mini-m6のような名前を付けます。保存してトークンをコピーします。CircleCIがトークンを表示するのは一度だけです。
CLIでも同じことができます。
circleci namespace create <name> --org-id <your-organization-id> circleci runner resource-class create <namespace>/<resource-class> <description> --generate-token
2. Homebrewでrunnerをインストールする
brew tap circleci-public/circleci brew trust circleci-public/circleci brew install circleci-runner
真ん中の行は新しい手順です。2026年10月に当社のMacに入っていたHomebrew 7.0.7は、サードパーティのtapを信頼するまで、そこからパッケージを読み込みません。CircleCIのページにはまだこの手順がありません。runnerはHomebrewのcaskとして入ります。
macOSが、Circle Internet Servicesのバックグラウンド項目が追加されたという通知を出すことがあります。これは想定どおりです。HomebrewはLaunchAgentのplistも~/Library/LaunchAgents/com.circleci.runner.plistに書き込みます。
3. config.yamlにトークンを追加する
nano $HOME/Library/Preferences/com.circleci.runner/config.yaml
runner: name: "mac-mini-m6" working_directory: "/Users/$USER/Library/com.circleci.runner/workdir" cleanup_working_directory: true api: auth_token: "your-resource-class-token"
cleanup_working_directoryをオンにすると、各ジョブはクリーンなチェックアウトから始まります。XcodeのDerivedDataは標準で~/Library/Developer/Xcode/DerivedDataにあるので、ビルドのキャッシュは残ります。作業ディレクトリ内に-derivedDataPathを指定すると、ジョブのたびにクリーンアップで削除されます。
トークンを守る
リソースクラスのトークンは、マシンがそのクラスのジョブを受け取るためのものです。これを読んだ人は誰でも自分のマシンを接続し、あなたのシークレットごとジョブを受け取れます。設定ファイルは自分のユーザーだけが読めるようにし、漏れた場合はトークンをローテーションしてください。
chmod 600 $HOME/Library/Preferences/com.circleci.runner/config.yaml ls -l $HOME/Library/Preferences/com.circleci.runner/config.yaml
ジョブにも同じ考え方が当てはまります。ジョブはrunnerを起動したmacOSユーザーとして、ほかのすべてと同じディスク上で動きます。このリソースクラスを指定するのは、信頼できるプロジェクトだけにしてください。
4. 公証を承認する
バイナリはインターネットから来るので、macOSの承認が必要です。CircleCIは、まず署名を確認し、次にquarantineフラグを外す手順を記載しています。
spctl -a -vvv -t install "$(brew --prefix)/bin/circleci-runner" sudo xattr -r -d com.apple.quarantine "$(brew --prefix)/bin/circleci-runner"
1つ目のコマンドは、ソースがNotarized Developer IDで、acceptedと表示されるはずです。
5. GUIドメインでrunnerを起動する
以下はMacのデスクトップ上のターミナルから実行します。GUIドメインとは、ログインしているデスクトップセッションのことです。シミュレータとログインキーチェーンはそこにあります。
launchctl bootstrap gui/$(id -u) $HOME/Library/LaunchAgents/com.circleci.runner.plist launchctl enable gui/$(id -u)/com.circleci.runner launchctl kickstart -k gui/$(id -u)/com.circleci.runner launchctl print gui/$(id -u)/com.circleci.runner
CircleCIは、ヘッドレスのセッション向けにユーザードメインの方法も記載しています。この方法ではplistを/Library/LaunchAgentsに移します。macOS 27では、このフォルダにplistがあると、起動のたびに自動ログインが壊れることを確認しました。ヘッドレスMacでの自動ログインをご覧ください。iOSの作業には、GUIドメインと自動ログインの組み合わせをおすすめします。
6. 再起動後も動くようにする
~/Library/LaunchAgentsのplistは、そのユーザーがログインすると読み込まれます。「システム設定」の「ユーザとグループ」で、このアカウントの自動ログインをオンにします。sudo pmset -a sleep 0でスリープをオフにします。一度再起動し、もう一度launchctl printを確認します。ログは~/Library/Logs/com.circleci.runner/runner.logにあります。
7. ジョブからMacを指定する
version: 2.1
jobs:
ios-tests:
machine: true
resource_class: your-namespace/mac-mini-m6
steps:
- checkout
- run:
name: Run tests
command: |
rm -rf build/TestResults.xcresult
xcodebuild test -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' -resultBundlePath build/TestResults.xcresult
- run:
name: Zip result bundle
when: always
command: ditto -c -k --keepParent build/TestResults.xcresult TestResults.xcresult.zip
- store_artifacts:
path: TestResults.xcresult.zip
workflows:
ios:
jobs:
- ios-testsCircleCIのドキュメントは、runnerのジョブに必要なフィールドを2つ挙げています。machine: trueとresource_classです。イメージを選ばないので、ここにはmacos: xcode:のキーはありません。ジョブは、Macで選択されているXcodeをそのまま使います。MacRunのMacなら、Xcode 26.6とiOS 26.5のシミュレータランタイムです。
よくあるエラーと対処法
Refusing to load cask ... from untrusted tap。brew trust circleci-public/circleciを実行してから、もう一度インストールします。- macOSがバイナリをブロックする。公証の手順を飛ばしています。上の
xattrコマンドを実行してください。 - ジョブがキューに入ったまま始まらない。config.ymlのリソースクラスが作成したものと一致しているか確認し、
runner.logを読んでください。 - Dockerレイヤーキャッシュが動かない。CircleCIは、セルフホストrunnerでは非対応としています。
xcodebuild: error: Existing file at -resultBundlePath。テストのステップの前に古いbundleを削除してください。Xcode 26.6で実際に遭遇しました。
runnerを止めるにはlaunchctl bootout gui/$(id -u)/com.circleci.runnerを使います。削除するにはbrew uninstall --cask circleci-public/homebrew-circleci/circleci-runnerを実行します。
専用Macが役立つ理由
一番の利点はウォームなキャッシュです。当社のベンチマークでは、Xcode 26.6でWikipediaのiOSアプリをビルドしました。小さな変更後の一般的なジョブは、ウォームなM6で27秒でした。新規のGitHubホスト型macos-26 runnerでは269秒でした。クリーンビルドは86秒対183秒でした。
CircleCIのホスト型macOSで足りる場合
CircleCIは自社でMacのexecutorを運用しています。2026年10月に読んだドキュメントでは、6 vCPUで28 GBのm4pro.mediumと、12 vCPUで56 GBのm4pro.largeが載っています。どちらも当社の16 GBのM6よりメモリが多いです。テストスイートにそれだけのメモリが必要な場合や、ビルドが週に数回の場合は、ホスト型のままにしてください。SLA、固定IP、複数のリージョンが必要な場合も、MacRunは向きません。
MacRun側のセットアップはその他のCIシステムをご覧ください。ご自身の分数でコストを比較することもできます。
よくある質問
CircleCIのセルフホストrunnerは無料ですか?
+
CircleCIによると、runnerでの実行はクレジットを使いません。ただし、アカウントには1クレジット以上が必要です。ストレージとネットワーク転送は課金されることがあるからです。
macOSでのCircleCI runnerの設定ファイルはどこですか?
+
$HOME/Library/Preferences/com.circleci.runner/config.yamlです。ログは$HOME/Library/Logs/com.circleci.runner/runner.logに出力されます。
GUIドメインとユーザードメインのどちらを使うべきですか?
+
iOSのビルドなら、GUIドメインと自動ログインの組み合わせです。シミュレータとログインキーチェーンが必要とするデスクトップセッションの中で動きます。
CircleCIのセルフホストrunnerでDockerレイヤーキャッシュは使えますか?
+
いいえ。CircleCIは、Dockerレイヤーキャッシュをセルフホストrunnerでは非対応としています。