プラットフォームとモバイルのリードは 2026 年も同じトレードオフに直面し続けます。Linux ランナーは安価ですが、Xcode を実行できません。 GitHub でホストされる macOS の時間は高価であり、ピークの週にはキューが追加されます。 Mac を購入すると、設備投資とデータセンターの仕事があなたに代わってしまいます。この記事は、すでに VPS の観点から考えており、リモート Mac の容量をノードのようにレンタルしたいと考えているチームを対象としています。ラベル プール、DerivedData キャッシュ、安全な廃止を通じた SSH 強化までの実際的なパスに加え、比較表とすぐに貼り付けられるワークフロー スニペットが含まれています。
ホストされたランナーは、メタル操作をゼロにしたい場合に最適ですが、リリース週に加えて依存関係のチャーンにより、共有プールの末端が伸びてカレンダーが消費される可能性があります。 macOS ジョブは、Xcode バージョン、シミュレーター ランタイム、キーチェーン署名パスと密接に結合しています。コールド スタートは Linux よりもはるかに高価です。キュー、キャッシュ、同時実行性を分割せずに「1 回通過」が SLA として扱われる場合、予測可能な日中の待機と深夜のビルドのベビーシッターが得られます。
これら 6 つの問題点は常にレビューに現れます。これらはホスト型プールに対する議論ではありません。これらは、いつ macOS の実行を専用のリモート ノードに移動し、Runbook でリスクを把握するかを示します。
非表示のキュー末尾:待ち時間は統計的なものですが、計画会議では「理想的な 15 分」を想定しています。 P95 データがなければ、関係者を調整することはできません。
分 × コールド スタート:過度にクリーンなワークスペースでは、依存関係の解決と完全な再コンパイルが強制されます。 1 分あたりの料金は変わりませんが、合計分数は膨れ上がります。
ツールチェーンのドリフト:ホストされたイメージのアップグレードが固定された Xcode マイナーから逸脱すると、「昨日は緑、今日は赤に署名」というノイズが発生します。
同時実行設計が欠落しています:リリース ブランチ、夜間ブランチ、実験ブランチを同じデフォルト キューにバインドすると、プリエンプションが発生します。ラベルがないということは、事実上、分離されていないことを意味します。
ディスクのホットスポットが過小評価されている:DerivedData とシミュレーター イメージは継続的に増加しますが、予算については vCPU と RAM のみについて議論が続いています。
セキュリティと監査のギャップ:平文スクリプト内の共有インタラクティブ セッションと長期間の PAT は、監査中に爆発的に発生します。
2 週間以内に 2 つ以上が再発する場合は、オプションに「専用 Apple Silicon をレンタルし、セルフホスト ランナーを登録する」を追加し、比較表を使用してキューの所有権、キャッシュ ポリシー、運用責任を明確にします。
もう 1 つの盲点: キューペインは依存関係グラフに沿って伝播します。 iOS が 1 段階のみの場合、macOS ジョブがホストされたプールで待機している間に Linux コンテナのビルドがすぐに終了する可能性があります。リリース トレインのクリティカル パスは依然として最も遅いホップによってバインドされています。 macOS を専用ハードウェアに移行すると、共有ディストリビューションから監視、拡張、呼び出し可能なハードウェアに移行します。
最後に、セルフホスティングは「GitHub のセキュリティ モデルを無視する」ものではありません。マシンの表面積はユーザーが所有するため、トークンのローテーション、ランナーのアップグレード、監査ログは変更管理に属します。漏洩したシークレットはリポジトリとホストの両方にまたがるようになりました。
セルフホスティングでは、貨物やスペアパーツを購入する必要はありません。 VPS 形式のパスは、配送されたリモート Mac をレンタルし、自動化のために SSH で標準化し、安定したサービス ホームにランナーを登録することです。購入と比較した場合、デルタはキャッシュ フローの形状、リージョン切り替えの摩擦、およびストレージ層であり、ディスク上にキャッシュを保持できるかどうか、および複数の Xcode スタックを並行して支払うかどうかが決まります。
SSH 強化により、「エンジニアはログインできる」が「CI はいつでもログインできる」に変わります。つまり、CI ユーザー専用キー、パスワード認証オフ、エグレス IP のプロバイダー側ホワイトリスト、known_hosts とキー ローテーションの四半期チケットです。分散チームの場合は、ラップトップからランナーへの追加のホップについて疑問を持ちます。Git、レジストリ、ランナーが同じプライマリ コラボレーション パス上にある方が良いため、デバッグがアドホック トンネルに依存しなくなります。
「クローゼットに収納する」と比較すると、レンタルはクラウド VM に近いと感じられます。スケールは、資産タグではなく、ディスクのアップグレードやリージョンの移動として現れます。まだパッチ ウィンドウとメジャー ランナー アップグレードの義務があります。それを RACI に入れます。プラットフォームはランナー/ラベル ポリシーを所有し、モバイル リードは Xcode マイナーをピン留めし、セキュリティ レビュー トークンと分割アカウントを所有します。そのため、クリーンアップ スクリプトがローカルにあったときにインシデントが「ベンダーのせい」に発展することはありません。
| 寸法 | GitHub でホストされる macOS ランナー | レンタルしたリモート Mac + セルフホスト ランナー |
|---|---|---|
| キューと同時実行性 | ピークテールレイテンシーを伴う共有プール。上限は計画と割り当てに従う | 専用ハードウェア。キューはラベルとワークフローのデザインです |
| キャッシュ戦略 | ジョブは「よりクリーンに」開始されます。耐久性のあるキャッシュには明示的な設計が必要です (アクション キャッシュなど) | コールド スタートを短縮するために、DerivedData および CocoaPods/SPM キャッシュをローカル ディスクに保持します。 |
| コストモデル | ホストされた分ごと - 頻度が低い場合は問題ありません | レンタルとディスク層。高頻度のビルドでは TCO がよりスムーズになることがよくあります |
| 運営 | GitHub によって管理されるイメージとベース OS | macOS のアップデート、ランナーのアップグレード、クリーンアップを保守し、それを文書化します。 |
| コンプライアンスと隔離 | 強力なプラットフォーム分離、少ないカスタマイズ | 個別の組織/リポジトリのトークン、アカウント、ボリュームによるより強力な分離 |
セルフホスティングは「安価」というスローガンではありません。共有キューのランダム性を測定可能なディスク、同時実行性、およびキャッシュ ポリシーと交換します。
これらの手順は、キーベースの非対話型ログインによる SSH アクセスを前提としています。コマンドはポリシーによって異なりますが、順序は一貫している必要があります: 専用アカウント → ディレクトリ レイアウト → ランナーのダウンロード → サービスのインストール → ワークフローをラベルにバインドします。ランナーを個人の GUI セッションに残さないでください。スリープ、ログアウト、および権限のポップアップにより、CI が非決定的になります。
ランタイム ID を固定します。CI 用に macOS ユーザーを作成し (またはプロバイダーの専用アカウントを使用し)、それを個人の Apple ID やブラウザー セッションから分離します。
ディレクトリとクォータ:に標準化する~/actions-runnerディスクが 2 つの Xcode スタックと DerivedData を保持できることを確認します。
ダウンロードして設定します。正しいアーキテクチャを取得しますactions-runnerGitHub のドキュメントからのバンドル。走るconfig.sh組織/リポジトリ URL、トークン、ランナー名を使用して 1 回。
パーティションラベル:少なくとも分割するmacos、xcode-16、region-sg(例) そのため、リリース ジョブと実験的ジョブが相互にプリエンプトされることはありません。
デーモン化:使用svc.sh install、LaunchDaemon、または自動再起動とログ ファイル用にプロバイダーが推奨するサービス ユニット。
最小限のワークフローをスモークテストします。走るuname -aそしてxcodebuild -version実際の署名を多用するビルドを配線する前に。
jobs:
ios_build:
runs-on: [self-hosted, macOS, ARM64, nodemini-ios]
steps:
- uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_16.app
- name: Build
run: xcodebuild -scheme App -destination 'platform=iOS Simulator,name=iPhone 16' build
注記:のカスタムラベルruns-on登録と一致する必要があります。リポジトリレベルのランナーと組織レベルのランナーでは可視性が異なります。シークレットとGITHUB_TOKENワークロードを移動するときのスコープ。
Apple Silicon では、並列処理は生のコア数ではなく、メモリ帯域幅とディスク IO によって制限されることがよくあります。一般的なパターンは、DerivedData と依存関係キャッシュをウォームに保つリリース用の「ホット」ランナーと、クリーンアップ スクリプトがメインラインを破壊しないように実験用の 2 番目のマシンまたはラベル プールです。ステップをコンテナ化する場合は、Docker Desktop のオーバーヘッドを考慮します。純粋な Xcode ビルドの場合、ベアメタルの方が安定していることがよくあります。
キャッシュの書き込みとアーティファクトのコンシューマを調整します。大規模な共有依存関係をオブジェクト ストレージまたは内部レジストリに保存し、ワークフローでリストアを階層化します。アクション キャッシュは、中程度の再生可能なレイヤーに適合します。いずれにしても、誰がランナーをクリーンアップできるか、どのディレクトリが立ち入り禁止であるかを文書化してください。そうでない場合は、リリース週にコールドコンパイルすることになります。
少なくとも 4 つの信号 (ランナーのハートビート、キューの待機、空きディスク、ラベルごとに分割された障害率) を監視します。ラベルを認識したメトリクスがないと、「実験的ジョブの枯渇リリース」は Xcode のアップグレードの問題のように見せかけます。システム データ パスとユーザー ライブラリ パスの両方を監視します。シミュレーターとキャッシュは、明らかなフォルダーの外側に隠れます。
1 つのホスト上でインタラクティブなデバッグと CI を混在させる場合は、ラベルまたは時間枠を使用して分離します。そうしないと、人間のセッションからのキーチェーン プロンプトによって無人ジョブが停止します。 AI エージェントまたは常時稼働タスクの場合は、CI との CPU/ディスク競合を確認し、エージェント ログがシステム ボリュームをいっぱいにしないように、より高いディスク層を選択します。
警告:共有リモート環境では、マシンレベルで分離せずに、グローバル キーチェーンに配布証明書と秘密キーを残さないでください。プロバイダーからの別のアカウントまたはノードを優先し、署名素材をリリースタグ付きランナーに制限します。
以下の参考資料は、GitHub の公開ドキュメントと、期待値を一致させるための一般的なコミュニティの実践 (GitHub プランとベンダー契約に照らして請求書を検証する) から引用したものです。
デスク Mac または「借りた」ハードウェアでランナーを実行すると、短期的には現金が節約されますが、スリープ ポリシー、更新ポップアップ、および共有インタラクティブ セッションが再導入されます。 Linux VPS 上のネストされた仮想化がネイティブの Metal および署名の安定性と一致することはほとんどありません。 iOS CI/CD およびエージェント自動化における 24 時間 365 日の予測可能なキュー、耐久性のあるキャッシュ、監査可能な分離の場合、通常は、契約した専用のリモート Mac に実行を配置することが運用環境に合わせた答えになります。キュー、ディスク、コンプライアンスのコストのバランスを考慮した NodeMini のクラウド Mac Mini レンタルは、セルフホスト型ランナーの長期容量基盤として適しています。ノードのようにリージョンとディスクを選択し、自動化のために SSH を強化し、ラベルとクリーンアップ ポリシーをハンドオーバー準備の整った運用資産として扱います。
イテレーション週では、P95 ビルド時間とキャッシュ ヒットが考慮されます。ホストされたキューが急増した場合は、最初に専用のセルフホスト ランナーでメインを安定させます。を使用してレンタル期間とディスクを比較します。レンタル料金ページにアクセスしてから、階層をロックする前に 2 週間のパイロットを実行します。
多くの CLI ビルドとシミュレーター フローは、適切なセッション構成を使用して SSH 経由で動作します。 GUI が必要な場合は、セッション永続性とロック画面ポリシーを明示的に設計し、セキュリティ要件を SOP に取り込みます。
まず、SSH ポート、キー、ネットワーク ポリシーから始めます。ヘルプセンター、次に、ワークフロー側でラベルとランナーのオンライン状態を確認します。