VPS のように算力を管理する感覚はある一方で、React Native / Expo では EAS のキュー、ネイティブモジュール、クレデンシャルの形に足を取られている、という方へ向けた記事です。マネージドビルドと専有の macOS 面を同じ対照表に載せ、痛み分けのあとに意思決定のマトリクスと 6 ステップの導入チェック、監査可能なセルフホスト運用のリズムまで落とし込みます。読み終えたころには、EAS のまま進める条件と、iOS ビルドをノードを買うのと同じ発想で借りる専有リモート Macに載せ替える条件が、はっきり分かるはずです。
Expo Application Services(EAS)は、証明書、アップロード、クラウド上のビルドまでまとまっており、王道の導線には合います。ただ、リポジトリに大規模なネイティブ差分、プライベート Pod、もしくはビルドログとシェル監査をコンプラ資料に載せる必要が出ると、マネージドプールの目に見えないキューとイメージの壁が減速要因になります。次の 6 条は、実際の手当て場面を整理した抽出であり、「SSH できる第 2 のビルド面」が要るかの材料になります。
キュー意味の不透明さ:負荷の高い時間帯、同一ワークフローが何十分も待たされることがあり、リリース枠をビジネス側に固定していると、その不確実性が本番障害のリスクに直結します。専有機のように社内 SLA に「同時実行の上限」を書き込めない、という違いです。
ネイティブ依存の連鎖が長い:react-native-config、Firebase、地図や Bluetooth など、カスタム Podspec やプリビルドが絡むとイメージキャッシュの当たり率が下がり、1 回のビルド時間のばらつきが大きくなります。切り分けのとき、ホスト相当のシェルがなく xcodebuild -showBuildSettings の出力を突き合わせにくい、という壁も出ます。
クレデンシャルと署名モデルの分岐:チームで EAS のマネージド署名と社内 match / 自前 CA を併用すると、「ローカルでは Archive できるのに、クラウドではときどき失敗する」二重化が生じます。根っこは、キーチェーン文脈と CODE_SIGN_IDENTITY の組合せをマネージドイメージ上で完全に再現しにくい、という点にありがちです。
ディスクと DerivedData の水位を押さえにくい:大規模な monorepo はマネージド側で掃除ポリシーに当たりやすく、熱いキャッシュ層が流れ去りがちです。UI テストと Archive を高頻度で回すチームにとっては、想定外に長い尾の時間になります。
既存 CI のラベル体系と切り離される:バックエンドと Web では GitHub Actions に labels、同時実行の上限、セルフホスト Runner まで定義済みなのに、iOS だけが別系統のオーケストレーションに乗ると、運用の頭の中が二つに分かれ、当番の負担が増えます。
監査フィールドの不足:金融、医療、越境展開のコンプラでは「誰が、どの IP から、どのビルド機に、どのコマンドを打ったか」が問われます。マネージド側が社内の SOC2 と突き合わせられる生の SSH /セッションログを出し切れないなら、専有ノードで証拠の連鎖を補完する必要があります。
2 件以上当てはまるなら、以降の比較表と手順に進む価値があります。ビルドはたまにしか走らず、ネイティブ層が薄いなら、まず EAS の機能を使い切る方が手早いでしょう。専有機に Runner を乗せる具体は、GitHub Actions セルフホスト Runner の稿をあわせて読むと分かりやすいです。本稿は、RN/Expo の文脈で境界線を引くことに注力します。
2 案を 1 枚の表に置くのは、EAS を否定するためではありません。レビュー会で「キュー、イメージ、署名、監査」を同じ語彙で扱うための装置です。前提として、チームは eas.json の profile を扱い、基礎的な macOS 運用もできる想定にしています。
| 観点 | EAS Build(マネージド) | 専有リモート Mac セルフホスト |
|---|---|---|
| 提供までの速さ(冷起動) | 高く、マシン調達と OS 導入を省略できます | 中。SSH、Ruby/Node の指紋、Runner 登録の一度きり作業は要ります |
| キューと同時実行の制御 | 共有プールの影響を受け、ピークの予測は難しい | CPU/ディスクを専有でき、同時上限と掃除の窓を文書化できます |
| ネイティブ層の複雑さ | 標準的な Expo マネージドの道に合います | 深いネイティブ、独自 Pod、プリビルドやローカルパッチの列に合います |
| 署名と証明書方針 | EAS のマネージドクレデンシャルに深く接続します | match、自前 KMS、環境別キーチェーンに寄せ切れます |
| ログと監査 | プロダクトの範囲内のログが中心です | xcodebuild とシェルセッションを通しで取り、内製の監査に乗りやすいです |
| 運用の負担 | 低く、「サービス化された CI」に近いです | 中から高。VPS クラスタに近い感覚です |
「マネージドのビルドは 0 から 1 まで。専有ノードは 1 から N の再現性と監査性です。」
折衷としてよく出るのは、日々の成果物と PR は EAS に残し、Release の Archive、UI テストの行列、ネイティブ反復の試行錯誤を専有リモート Mac に寄せるパターンです。最も人日が乗る工程を、制御可能な面に集約し、マネージド側の接続のしやすさは維持します。
次の表は、チーム規模・ネイティブの深さ・コンプラの厳しさの目安に沿った実務向けの結論です。容量計画の表の代わりではありませんが、アーキテクチャのレビューで優先度を揃えるのに使えます。
| シグナル | EAS を主役に保つ | 専有リモート Mac を入れる |
|---|---|---|
| ネイティブ依存 | コミュニティ製モジュールが中心で、独自 Pod はほぼない | プライベート Pod、バイナリのクローズド SDK、独自のビルドフラグが要る |
| リリースの頻度 | 週次や隔週で、キューの揺れを許容できる | 日次や時間と箱で縛ったリリースで、同時実行と枠を固定したい |
| コンプラ | 厳格な監査フィールドの要求はない | SSH/コマンドレベル監査、固定の出口、パーティション化した VPC が要る |
| 既存 CI | iOS のパイプラインとバックエンドのパイプラインは切り離せる | iOS ジョブを GitHub Actions / GitLab と同じ labels とキャッシュ方針に乗せたい |
// eas.json 抜粋:マネージドのビルドと、外付けのセルフホスト Job を分ける
{
"build": {
"preview": { "distribution": "internal", "channel": "preview" },
"release-selfhosted": {
"extends": "production",
"env": { "EXPO_USE_FAST_RESOLVER": "1" },
"ios": { "image": "latest" }
}
},
"submit": { "production": {} }
}
注意:同じブランチでマネージドとセルフホストを混ぜるなら、README に「どの profile が、どのクレデンシャル束を起こすか」を明記する必要があります。新しいメンバーがキーチェーンと EXPO_TOKEN の間を往復しなくて済みます。
マトリクスの外に、体感的な一線があります。「動く」と「再現できる」は別物です。マネージドイメージの更新は目立たないことが多く、リポジトリに Xcode や Node のマイナー版まで固定していないと、ネイティブ周りは無言のアップグレードで一斉に赤くなりがちです。専有ノードなら、xcode-select や Ruby Bundler を、カーネル版を固定する感覚で固定し、指紋を CI 契約に刻めます。
以降は、ローカルで npx expo prebuild まで出せる前提で、専有機で xcodebuild や Fastlane を回す流れをまとめます。VPS 運用に慣れている人が一度で通るよう、アカウント、鍵、ディスク、ログ還流の 4 点を一気通貫で扱います。
ツールチェーンの指紋を凍らせる:リモート Mac 上で xcodebuild -version、node -v、ruby -v、pod --version を記録し、BUILD_ENV.lock としてリポジトリに置きます。更新は必ず PR 経由にし、「誰かが SSH で上げたつもり」が生じないようにします。
CI 用の非対話ユーザーを作る:個人の Apple ID セッションにバッチを乗せない。Runner や SSH ジョブ専用のユーザーとキーチェーン区画を分け、再現性のあるビルド 稿のキーチェーン分離方針と揃えます。
DerivedData と Pods のパスを分ける:リポジトリやブランチごとに、例 ~/DerivedData/$REPO/$BRANCH と ~/PodsCache/$REPO のように掛け、掃除は OS の一時掃除に任せず、cron や手順に書きます。
iOS ジョブを本流の CI に戻す:GitHub Actions / GitLab のセルフホスト labels を専有機向けに張り、Android ジョブと同じ承認と同時実行ゲートに載せます。GUI が要る切り分けは、常時は開かない VNC の窓に閉じます。
成果物とログの還流:.ipa、dSYM、xcodebuild 生ログを、統制したオブジェクトストレージか社内のレジストリに送ります。金融顧客向けに、事後の検証用にコマンド単位のセッション記録を足す、という選び方もあります。
2 週間の対照実験をする:代表的なブランチを 5 本選び、EAS と専有機の P50/P95 の所要と失敗の型を併記します。ネイティブが重い条件で専有が揺れ幅を小さくし、キューの分散も抑えられれば、Release トラフィックの移し先にします。
ヒント:リージョンとディスクの階層をまだ詰めている段階なら、レンタル料金の説明を先に読み、「同時実行 × ディスク水位 × 出口の地域」の 3 軸を調達の添付にし、上の 6 ステップと一緒に受け入れ基準にします。
xcodebuild のリンク段でランダムに落ち始めます。iOS ビルドをマネージドプールに完全に任せるのは、短期の人日ではもっとも楽です。ただ、ネイティブ依存、監査フィールド、既存の Actions / GitLab との一貫したスケジュールが重くなると、目に見えないキューと、ピン留めしきれないイメージが不確実性を積み上げます。逆に、専有の Mac 群にディスク統治と指紋の方針がないと、すぐ「別の技術的負債の山」になり得ます。
ざっくりいえば、週 7 日で予測可能なキュー、コマンドセッションの監査、既存の Runner ラベル体との統一が RN/Expo の配列にとってハード制約なら、重い負荷は専有の macOS 面に乗せ、EAS は軽い統合と外向きの協働向け、という分け方が合います。実行環境を「契約で書ける 1 ノード」に近づけ、キューの分散を抑え、iOS CI/CD と常時自動化の両方に使いたいなら、NodeMini の Mac mini クラウドレンタルは、現実的な選択肢になり得ます。
iOS ビルドを、スケールする 1 ノードとして扱い、ディスクと同時実行を一定に保ち、コマンド単位のログを出す必要があります。もしくは、ネイティブ依存列がマネージドのイメージに収まらない、という状況では、専有リモート Mac の方が合います。まず レンタル料金の説明に照らし合わせ小さく試し、Release ジョブを一括移すかを決めてください。
難しくなります。profile とキーチェーンの境界を分け、マネージド側は EAS マネージド署名のみ、セルフホスト側は match か企業向け KMS のみ、とし、README に切り替え条件を残してください。接続と権限の補足は、ヘルプセンターの SSH とアカウントの章を参照してください。
Runner の稿は、ラベル、キャッシュ、キューを扱います。本稿は、RN/Expo における EAS と専有面の棲み分けを扱います。すでにリモート Mac に Runner を置いていれば、本稿の 6 ステップを、そのまま本番扱いの拡張チェックリストにできます。