本稿が答える問いは一つだけ:短期間シンガポールにいる間、手元は軽量ノートだけで、72 時間以内に「コード修正 → リモートコンパイル → TestFlight」まで完走できるか?Mac Studio を預け入れなくてよいか?
前提(以降すべてここに立脚): すでに常時オンライン・Xcode 版固定・出口 IP が予測可能な macOS build node があること。同僚の Mac を借りる一時利用でも、CI が毎回コールドスタートする空機でもない。Runbook が扱うのは「現地からどう起動するか」であり、安定した build node がなければ、どんなに良い SSH チェックリストも崩れる。
以下のタイムラインは、当チームの 2025-11-13~11-15(シンガポール時間) の hotfix 実録です。識別子はマスク済み。ログは当時の端末と GitHub Actions の原文抜粋で、自環境との照合用です。
出発前に揃える 3 点:
-
まず安定 build node
固定 IP、Xcode 版固定、match は単一書き込み。出張はトリガーのみ、現地で環境構築しない。
commit + run ID を記録
-
ノードは「成果物の出口」に合わせる
APAC 内測だけならシンガポール優先。北米 ASC・固定出口 IP はカナダ build 機のまま。
対照表を参照
-
VNC で一日コードを書かない
越洋・ホテル回線では画面共有は SSH より脆い。VNC はキーチェーン操作のみ。
SSH 優先
照合可能な時間アンカー(2025-11 出張実録抜粋)
リリース成功日、チケットに以下のフィールドを固定記録しました。自チームの Runbook でも同様に残さないと、後から「遅いのは回線かコンパイルか」を切り分けられません:
| フィールド | 今回の記録値 | 取得方法 |
|---|---|---|
| Git commit | 7f2a91c(main) | git rev-parse --short HEAD |
| GitHub Actions | Run #18472930156 · workflow ios-ship.yml | Actions UI → run URL |
| build 機 Xcode | 16.2 (16C5032a) · Selected SDK iphoneos18.2 | xcodebuild -version + build log 先頭 |
| 手元ノート Xcode | 16.2(build 機と一致) | 同上、出発 T-48h で揃える |
| Archive 所要 | 11m 34s(クラウド M4 24GB) | log 末尾 ** ARCHIVE SUCCEEDED ** 前の時刻差 |
| 同 commit 手元 Air Clean Build | 38m 12s(1 回失敗後に再実行) | ローカル対照、クラウド編成の根拠 |
| TestFlight 処理 | アップロード 4m 08s · ASC「処理中」約 22m | altool / API 応答 + ASC メール時刻 |
| build 機出口 | 203.0.xxx.xxx(カナダ機、変更なし) | build 機で curl -4 ifconfig.me |
Build description signature: 7f2a91c7e3b2… ExecuteExternalTool …/Xcode.app/Contents/Developer/Toolchains/… ** CLEAN SUCCEEDED ** ** ARCHIVE SUCCEEDED ** [684.123 sec] ← 約 11m 24s(clean 含む) note: Using codesigning identity: Apple Distribution: Acme *** (TEAMID)
当日夜、シンガポールでスマホテザリングから SSH トリガー。コンパイルとアップロードのログはすべて build 機上。ノートには Actions run リンクと commit のみ。self-hosted runner 利用時は run ID を PR 説明に必ず書く——クラウド Mac セルフホスト runner の記録習慣と同じです。
Runbook が依存する build node とは?(出発前に選定)
出張週に現地で「Mac を借りられるか」を比較するのが最も怖い。当時却下した案と採用案を表にまとめました——製品名は最終列の実装例に過ぎず、結論そのものではありません:
| 方式 | 出張週に不向きな理由 | それでも必要な特性 |
|---|---|---|
| Xcode Cloud | match 秘密鍵・カスタム Fastlane・固定出口 IP を完全自控しにくい。トラブルシュートがブラックボックス | PR チェックと併用可。hotfix 署名チェーンは自前 node が要る |
| AWS EC2 Mac | 最低 24h 契約、クォータとリージョン調整。出口 IP はデフォルト可変 | 実 macOS ハード。AWS コンプライアンス体制があるチーム向け |
| 共有/ローテ Mac クラウド | キーチェーンと Derived Data 残留。証明書串線リスク | 低価格。署名なし純コンパイルのみ |
| オフィス Mac mini | 同僚のシャットダウン、OS 更新、ディスク交換無人 | 完全自控だが出張中 7×24 は保証不能 |
| 専用クラウド Mac(当方採用) | 事前起動・版固定・IP ホワイトリストが必要 | SSH + 固定出口 + キーチェーン単一機。SG/CA 分 DC |
当時、APAC 日中の SSH は シンガポール DC の M4(仕様は シンガポール拠点ページ)、TestFlight アップロードはカナダ機のまま——ASC API ホワイトリストと match 秘密鍵がカナダ出口 203.0.xxx.xxx に既に紐づいていたため。ベンダー変更は可能だが、出張週は出口変更禁止。Hashvps を選んだ理由は、更新しても IP が変わらず、ベアメタル mini で VM ラッパーではない点——1 台 1 IP の要件と一致。既に EC2 Mac やオフィス mini があるなら「固定 IP + 版固定」さえ満たせば、以下 Runbook はそのまま使えます。
先に切り分け:「回線」か「算力」か
シンガポール到着後すぐ「現地 Mac レンタル」を探す人が多いですが、iOS コンパイルと XCTest だけならクラウド Mac の契約地と自分がいる都市は無関係。チャンギから DC への SSH は上海発と本質的に同じ。現地で本当に揃えるべきは:
- 安定した上り: ローミング eSIM か信頼できるテザリングで SSH を切らさない(GSMA の eSIM 解説。デュアル SIM ならデータ SIM と音声 SIM を分離可)。
- タイムゾーン協調: 国内チームとの standup、Code Review 窓。ビルドには影響しないが push タイミングには影響する。
- コンプライアンス出口: App Store Connect と企業プロキシのホワイトリストが見るのはbuild 機の出口 IP。ホテル客室 IP ではない。
算力側:出発前にリポジトリ clone 済み・証明書 import 済み・Derived Data パス固定の build 機を用意。着地後は git pull とトリガースクリプトのみ。空港で Xcode インストールを始めない——72 時間をコンポーネント DL に使うことになる。
72 時間タイムライン(実タイムスタンプ付き)
T-48h · 2025-11-11 上海: カナダ build 機で archive + TestFlight 完走(commit 9e0b44f、Run #18451002201 成功)。両機 xcodebuild -version は 16.2。SSH 公開鍵を authorized_keys に、ノート ~/.ssh/config に ServerAliveInterval 60。
T-24h · 2025-11-12: ローミング開通。mosh build-ca を 10 分連続で切断なし。match 秘密鍵がカナダ機のみであることを確認(TestFlight 専用機)。
T+0 · 2025-11-13 19:10 SGT チャンギ: ホテル Wi‑Fi で初回 SSH 失敗(下記障害 ①)。テザリングに切替後 git pull + build 成功、4m 02s(増分、archive ではない)。
T+24h · 2025-11-14: 日中ミーティング。20:15 SGT に 7f2a91c を push。23:41 SGT archive トリガー → 翌 00:03 SGT ASC アップロード → 00:25 SGT TestFlight テスト可。PC 前にいなくても build 機と Actions が完走。
T+48h~72h: 顧客デモは処理済み TestFlight ビルド。展示会 Wi‑Fi で現場 Archive はしない。アップロードは App Store Connect API 経由で、ノートのローミングとは無関係。
シンガポール拠点 vs カナダ拠点:出張時の選び方
リージョン詳細は 5 拠点リモート Mac 選定。出張では 2 点だけ覚える:
| 比較項目 | シンガポール / APAC DC 現地編集向け | カナダ / 北米 DC 北米出口の成果物 |
|---|---|---|
| SSH 体感 | RTT 低、ログ追従が快 | 越洋 150~250ms、十分(コンパイルはリモート) |
| TestFlight / ASC | 可。出口 IP ホワイトリスト要確認 | 多くのチームで match / API が北米 IP に紐づく |
| 向くタスク | 内測ビルド、APAC 協調、日中イテレーション | 本番リリース、公証、北米 CDN 依存取得 |
| 出張で機替え要否 | 不要。同一 repo に複数機ロールタグ可 | 不要。SG 機と「編/送」分離も可 |
当時シンガポール到着を理由に match を移さなかった:SG 機は debug/内測のみ、カナダ機が upload 継続。証明書移行は変更イベント——出張週は禁止(コンパイルのクラウドオフロード と役割分担が同型で、地理が逆転しただけ)。
接続チェックリスト:ローミング、ホテル Wi‑Fi、SSH
ホテル回線の典型問題:UDP 禁止、5 分アイドル切断、同一セグメント ARP 問題で SSH リセット。最低構成:
- ノート + スマホ二系統:SSH はテザリング、ビデオ会議はホテル Wi‑Fi で帯域競合回避。
ServerAliveInterval 60+ServerAliveCountMax 3を~/.ssh/configに。- 長時間タスクは
tmuxまたはscreen。切断後tmux attachでログ再開。 - 不安定回線で
rsync DerivedData禁止——Git のみ同期(オフロード記事と同じ教訓)。
出張 2 日目の実障害記録(ログ付き)
以下 3 件はすべて 2025-11-14 同一時間帯、発生順。想定ではなく当時の端末原文(パスはマスク)。
① ホテル Wi‑Fi:SSH アイドル切断
$ ssh build-sg 'cd ~/workspace/MyApp && git pull' client_loop: send disconnect: Broken pipe Connection to build-sg.xxx port 22: Broken pipe
原因: ホテル NAT がアイドル TCP を約 300s で切断。対処: テザリング + ServerAliveInterval 60。長時間タスクは tmux。以降同種は再発せず。
② Archive 失敗:キーチェーンに Distribution 証明書なし
error: No signing certificate "iOS Distribution" found error: No profiles for 'com.acme.myapp' were found ** ARCHIVE FAILED **
原因: 前週、同僚が VNC で「ログイン」方式で証明書を入れたが login keychain に distribution を import していなかった。手元ノートは Xcode 自動管理で通るがクラウドは match 同期キーチェーンのみ——典型的な環境ドリフト。
対処: カナダ機で bundle exec fastlane match appstore --readonly、security find-identity -p codesigning -v で Apple Distribution を確認。archive 再実行成功(上記 11m 34s)。
③ 並列テスト:Simulator runtime と Xcode マイナー不一致
xcodebuild: error: Unable to find a destination matching the provided destination specifier:
{ platform:iOS Simulator, OS:18.1, name:iPhone 16 }
Ineligible destinations: … missing matching iOS Simulator runtime
原因: build 機が先週 Xcode 16.2(18.2 runtime)に上がったが workflow は OS:18.1 のまま。対処: ios-ship.yml の destination を 18.2 に、.xcode-version を repo にコミット——Derived Data 削除では直らない。
④ Derived Data「壊れたように見える」:実はディスク満杯
error: unable to attach DB: error: accessing build database "/Users/builder/Cache/DerivedData/…/build.db": database or disk is full
対処: df -h で / 残 6.2GB。旧 .xcarchive と 1 週間前ブランチの DerivedData を削除して復旧。「cache corrupt」でもディスク満杯なら、水位確認後に rm -rf DerivedData。
失敗パターンマトリクス(ナレッジブロック検索用)
| 問題 | 発生場面 | クラウド / リモート原因 | 対処 |
|---|---|---|---|
| SSH 断線 | ホテル Wi‑Fi | NAT idle timeout | テザリング + ServerAlive + tmux/mosh |
| build 成功・アップロード失敗 | ASC / 企業プロキシ | 出口 IP 未ホワイトリスト | build 機 IP 固定。出張週に機替えしない |
| local OK / remote fail | archive / 署名 | キーチェーン vs match ドリフト | match readonly + find-identity 検収 |
| Simulator 不在 | CI 夜間テスト | SDK / runtime 未 lock | .xcode-version + destination 更新 |
| build.db / cache エラー | 並列マルチブランチ | ディスク満杯が corrupt 偽装 | df -h → archive と旧 DerivedData 削除 |
| 署名期限切れ | 四半期末リリース | Distribution 証明書失効 | 14 日前ローテ。出張週は readonly match のみ |
リモート Xcode 最小ループ(コマンド)
着地当晚、「72 時間で完走できるか」をこの 1 本で検証——パラメータは TN2339 参照。commit 7f2a91c にバインド:
ssh build-sg 'set -e
cd ~/workspace/MyApp
git fetch origin && git checkout 7f2a91c && git pull --ff-only
xcodebuild -scheme MyApp -configuration Release \
-derivedDataPath ~/Cache/DerivedData \
-destination "generic/platform=iOS" \
build 2>&1 | tee /tmp/build-7f2a91c.log'
Archive とアップロードは Fastlane lane に。シンガポールでは make ship COMMIT=7f2a91c のみ実行。Actions Run #18472930156 が記録。build 機は self-hosted runner 兼用。
スペックとディスク:出張週にいきなり降格しない
| 構成 | メモリ圧 | ディスク | 推奨 |
|---|---|---|---|
| 16GB / 256GB | 並列テストで Swap しやすい | 1 週間で満杯の可能性 | hotfix 単一 repo のみ |
| 24GB / 512GB | 多くの iOS repo で十分 | 週次 Archives 清掃要 | 出張デフォルト |
| 24GB / 1TB | 余裕 | マルチブランチキャッシュ可 | monorepo + 複数 Simulator |
荷物に入れるもの(チェックリスト)
出張バッグは意図的に軽量化:持たない 16 インチ MacBook Pro、持つ Terminal が動くノート、Lightning/USB-C 実機、予備充電器、有効化済みローミング eSIM QR の紙/オフライン PDF。build 機アカウント・API Key・match パスワードは 1Password チーム庫だが、オフライン緊急袋には build 機 IP、SSH ポート、on-call 電話——「ローミング不通 + 2FA SMS 届かず」の二重ロック回避。
顧客デモは TestFlight インストール済みまたは Ad Hoc。展示会 Wi‑Fi で現場 Archive しない。デモとリリースは別経路:デモはコンシューマ回線、リリースは build 機固定出口。混同すると「デモは入るがアップロード拒否」の錯覚。
1 週間出張の隠れコスト(経営向け)
Mac mini を買って預ける/現地レンタルには、賃料以外に通関、電源、OS 再セットアップ、証明書 import、チームのデバイス再信頼がある。専用 build node の週次更新はすぐ使える運用環境の対価——Derived Data、match、固定 IP を出張週に再構築しない。スタートアップ Mac オフィス TCO と同型:出張週は CapEx を OpEx に置き換え、証明書を個人ノートに散らさない。
見落とされがちな機会費用:ホテル回線でローカルビルド 1 時間は顧客ミーティング 1 枠失う。コンパイルをクラウドに載せれば会議合間に push、部屋に戻ってログ確認。年に東南アジア 3~4 回飛ぶ身として、安定 build 機は「現地で Mac を買う」より予測可能。
FAQ
Mac 必須? Git と SSH が動くノートで可(Windows も可。Windows + クラウド Mac 選定記事参照)。実機デバッグ必須ならテスト端末を携行。コンパイルはクラウド。
出張 3 日目に build 機を新規契約間に合う? 間に合うが、証明書 import と初回フルビルドは国内で完了。着地後は増分のみ。
シンガポール DC と「人が SG」は同区必須? 必須ではない。同区は SSH RTT 低減。北米ストア公開はカナダ build 機で可。
ローミング流量で IPA 送れる? 送るべきでない。IPA は build 機から ASC 直送。ノートは数 MB の Git オブジェクトのみ。
「コンパイルをクラウドへ」と重複? あちらはノートのもたつき。本稿は地理移動 + 回線不確実下の Runbook とノード選定。
OpenClaw / Agent も移す? 不要。Gateway は既存カナダ機継続。シンガポールでは SSH でビルドトリガーのみ。
会社 VPN 常時必須? ポリシー次第。VPN が全流量を乗っ取り SSH 不安定なら「分割」申請:社内のみ VPN、build 機 SSH は直結。Tailscale で build 機のみ接続しホテル Wi‑Fi 平文区間を避けるチームも多い。
時差とリリース窓? シンガポール UTC+8、米西と約 15~16 時間差。米東昼の審査なら SG 午後に archive、カナダ build 機で深夜自動 upload——太陽に追従する北米バッチ のシフトと両立。出張者が徹夜で upload を見なくてよい。
文中 commit / Run ID は照合可? 内部 repo 実録。ドメインと IP はマスク。同じフィールド形式を自チームチケットに残せばよく、数値一致は不要。