Xcode Cloudでsudoが使えない:2026年、リモートMacへ移行すべき?

Xcode Cloudでsudoが使えない:2026年、リモートMacへ移行すべき?

Appleの公式ドキュメントでは、Xcode Cloudのカスタムビルドスクリプトからsudoで管理者権限を取得できないことが明記されています。自作ビルドスクリプトの権限に関する説明に反する形で、パスワード入力や再試行を続けても制限は解除されません。結論は明確です。Homebrewのツール導入や環境変数の読み取りだけならXcode Cloudを修正して継続し、常駐サービス、構築間の永続化、深いシステム設定が必要ならリモートMacへ移行します。標準テストをXcode Cloud、複雑な配布処理をリモートMacに分ける二重運用が、失敗範囲を抑えやすい選択です。

この判断が必要なのは、ci_post_clone.shなどで依存関係を導入している独立開発者、バックグラウンドサービスや独自ツールチェーンを使う小規模チームです。Xcode Cloudと、管理可能なリモートMacのどちらを公開用ビルドに使うか迷う担当者にも適しています。

sudoエラーの正体

まず、失敗ログをそのまま読まず、権限問題を三つに分けます。次の例では、ユーザー名、パス、リポジトリ名、Bundle ID、Team ID、秘密情報を実値に置き換えません。

#!/bin/sh
set -eu

echo "user=$(id -un)"
echo "home=$HOME"
command -v brew || true
sudo -n true

出力が次のような内容なら、sudoのパスワードを再入力する問題ではありません。

user=build-user
home=/Users/build-user
sudo: a password is required
sudo: a terminal is required to read the password

切り分けは次の順番です。

  • command not foundなら、コマンドの導入場所またはPATHの問題です。
  • Permission deniedなら、実行ビット、所有者、書き込み先を確認します。
  • sudo自体が拒否されるなら、管理者権限が必要な設計を疑います。

Xcode Cloudのカスタムスクリプトは所定のワークフローフェーズで実行されますが、sudoを使って管理者権限へ昇格する仕組みではありません。Xcode Cloudのワークフローリファレンスでも、実行段階と環境の扱いを確認できます。したがって、対話式のパスワード入力、sudoersの変更、管理者アカウントの追加を回避策にしてはいけません。

Xcode Cloudの自作スクリプトでsudoは使えるか

通常のビルドスクリプトから管理者権限を取得する用途では使えません。必要なのは、sudoを外して一般ユーザーの書き込み範囲で処理できる設計に変えることです。管理者権限が必須なら、同じコマンドを何度も試すのではなく環境の選択を見直します。

依存関係の導入

第三者ライブラリの導入失敗を、すべてsudoの問題にしてはいけません。CocoaPods、Carthage、Swift Package Manager、補助CLIでは、ツールそのものの導入と、プロジェクト依存関係の解決が別の失敗になるためです。

AppleはXcode Cloudで依存関係を利用可能にする方法として、Homebrew、リポジトリ内のファイル、スクリプトによる準備などを案内しています。依存関係の導入に関する公式手順に合わせ、次のようにユーザー領域へ導入できるかを確認します。

#!/bin/sh
set -eu

export PATH="$HOME/.local/bin:$PATH"
mkdir -p "$HOME/.local/bin"

if command -v brew >/dev/null 2>&1; then
  brew install --quiet "<TOOL_NAME>"
fi

"<TOOL_NAME>" --version

この設計で通る条件は、次のとおりです。

  • ツールが一般ユーザーのホームディレクトリへ導入できる。
  • バージョンをロックできる。
  • 毎回の依存関係解決が再現できる。
  • ビルド後にツール自体を保持しなくても問題がない。

一方、/Library/usr/localの保護された場所、システム全体の証明書ストアへの変更が必要なら、単純なスクリプト修正では不十分です。プロジェクト内に実行可能ファイルを置ける場合でも、ライセンス、更新方法、署名検証を確認してください。

一時領域とキャッシュ

Xcode Cloudの実行環境では、構築のたびに同じホスト状態が残るとは限りません。生成ファイルをホームディレクトリへ置いただけでは、次回の構築で存在する前提にできません。Appleの初回ワークフロー設定環境変数リファレンスを確認し、どの段階で何を生成し、どこへ渡すかを明示します。

生成物の扱いは、次のように分けます。

  • ソースに含められる小さな設定ファイルは、リポジトリまたはci_scriptsで管理する。
  • 同じ構築内で使う中間ファイルは、指定された作業ディレクトリから次のフェーズへ渡す。
  • Archiveやログは、構築成果物として保存する。
  • 大型キャッシュや秘密でない外部データは、必要性と保存先を分けて設計する。
  • 次回以降も必ず残す必要がある状態は、永続ディスクを持つ環境で管理する。

「生成したファイルが消える」ことと「スクリプトがファイルを別の場所へ作っている」ことは別です。pwdid -unls -laを各フェーズで出力し、ファイルの受け渡しを確認します。

pwd
id -un
mkdir -p "$CI_WORKSPACE_PATH/build-assets"
printf '%s\n' "<GENERATED_VALUE>" > "$CI_WORKSPACE_PATH/build-assets/generated.txt"
test -s "$CI_WORKSPACE_PATH/build-assets/generated.txt"

自作スクリプトのファイルを継続して保存できない理由

構築間で保持されると保証されていない一時領域に置いている可能性があります。次回も必要なファイルをリポジトリ、成果物、外部ストレージのいずれかへ明示的に渡せないなら、永続化できるリモートMacを候補にします。

常駐サービスとシステム設定

データベース、モックサーバー、独自デーモンを一回の構築中だけ起動するなら、一般ユーザーのプロセスとして実行できる場合があります。反対に、再起動後も自動起動するサービス、launchdのシステム領域、システム拡張、macOS全体の設定変更が必要な処理は、Xcode Cloudのカスタムスクリプトに押し込む設計と相性がよくありません。

たとえば、単一のテスト中だけ使うサービスなら次のように終了処理まで含めます。

#!/bin/sh
set -eu

"<LOCAL_SERVICE>" --port "<PORT>" > "$TMPDIR/service.log" 2>&1 &
SERVICE_PID=$!
trap 'kill "$SERVICE_PID" 2>/dev/null || true' EXIT

"<TEST_COMMAND>"

ここで重要なのは、リモートのグラフィカルセッション、バックグラウンドプロセス、無人運転の構築は同じ要件ではないことです。VNCで画面を操作できても、SSH経由の無人Archiveが再起動後に復旧するとは限りません。サービスのライフサイクルを完全に制御したい場合は、常時稼働するMacのほうが検証対象を固定できます。

署名と公開処理

署名エラーが出たときも、最初にsudoへ戻るべきではありません。次の四つを区別します。

  • Keychainへ秘密鍵を読み込めていない。
  • 非対話式のKeychainアクセスが許可されていない。
  • 証明書とProvisioning Profileの組み合わせが違う。
  • 環境変数、Bundle ID、Team IDの値が欠けている。

Appleはチームの署名証明書共有について、証明書だけでなく秘密鍵の扱いも問題になることを説明しています。チーム署名証明書の公式資料を確認し、秘密鍵をログへ出力しない構成にします。クラウド管理証明書を使う場合も、Appleのクラウド管理証明書の説明に沿って、対象チームと権限を確認します。

set -eu

test -n "${APPLE_TEAM_ID:-}"
test -n "${BUNDLE_IDENTIFIER:-}"
test -n "${ASC_KEY_ID:-}"

xcodebuild \
  -scheme "<SCHEME_NAME>" \
  -configuration Release \
  -destination "generic/platform=iOS" \
  -archivePath "$PWD/<ARCHIVE_NAME>.xcarchive" \
  archive

Keychainのアクセス制御を変更する場合は、影響を受ける証明書、対象ユーザー、回復手順を先に記録します。署名資産を置き換える場合も、直前のArchiveが再現できるかを確認してから実行します。単なる認証情報の設計不備であれば、リモートMacへ移しても解決しません。

判定カード

次の条件分岐で、修正、二重運用、移行を選びます。

  • 依存関係がHomebrewまたはユーザー領域へ導入でき、構築ごとに再現できるなら、Xcode Cloudを継続します。
  • ファイルが同じ構築内で完結し、成果物として渡せるなら、Xcode Cloudを継続します。
  • 標準テストとPull Request検証はXcode Cloudに残し、署名、Archive、公開だけを固定ホストで行えるなら、二重運用にします。
  • 管理者権限、常駐サービス、システム拡張のいずれかが必須なら、リモートMacへ移します。
  • 大型キャッシュ、生成済みツール、現場状態を次回構築でも保持する必要があり、外部化できないなら、リモートMacへ移します。
  • 失敗を同じプロジェクトで再現できず、ログだけでは原因を確定できないなら、短期間のリモートMac検証を先に行います。
  • 定期的なOS更新、証明書更新、再起動後の復旧を管理できない場合は、移行後の運用負担も含めて二重運用へ戻します。

選択肢の比較

判定項目 Xcode Cloudを継続 二重運用 リモートMacへ移行
ツール導入 Homebrewまたはユーザー領域 標準依存はXcode Cloud、特殊依存はMac システム全体の導入も管理
ファイル 同一構築または成果物で完結 テストと公開で保存先を分離 永続ディスクへ保持
サービス 構築中だけ起動 通常テストだけクラウド 常駐・再起動復旧を管理
署名 環境変数とKeychain設計で対応 検証と公開を分離 Keychainをホスト側で管理
適した用途 通常ビルド、自動テスト 標準CIと複雑な配布 特殊ツールチェーン、無人公開

移行前の検証手順

リモートMacへ移す場合も、sudoエラーだけを根拠に契約してはいけません。次の手順で、同一プロジェクトの再現性を確認します。

  1. 失敗したci_scriptsを複製し、秘密情報と固有IDをプレースホルダーへ置き換えます。
  2. id -unPATH、作業ディレクトリ、macOSとXcodeの組み合わせを記録します。
  3. 依存関係を空の作業領域から復元し、固定したバージョンで成功するか確認します。
  4. xcodebuild archiveを実行し、Archiveの生成場所と成果物の受け渡しを検証します。
  5. Keychain、証明書、Provisioning Profileを非対話式で確認します。
  6. App Store Connectへのアップロードを、実運用と同じ秘密管理で試します。
  7. Macを再起動し、SSH接続、サービス、依存関係、署名、無人Archiveが復旧するか確認します。

この検証では、単発のBuild Succeededだけを合格条件にしません。依存関係の復元、Archive、署名、アップロード、再起動後の無人実行まで連続して確認できて初めて、移行の効果を判断できます。

運用条件の比較

条件 Xcode Cloud リモートMac
権限モデル 管理者権限へ昇格しない前提で設計 管理対象ホストの権限を設定可能
実行状態 構築単位で再現性を確認 ホスト状態と保存先を継続管理
キャッシュ 外部化または成果物化が必要 ディスク、容量、削除方針を管理
公開処理 署名資産と環境変数を安全に注入 Keychainと自動化ジョブを管理
保守 Appleのワークフロー仕様に依存 OS、Xcode、サービス更新を担当
向いている判断 変更の少ない標準CI 完全なホスト制御が必要な公開工程

現在の構成からの切り替え方

現在のXcode Cloud構成は、セットアップ不要で標準テストを回しやすい反面、管理者権限を使えず、構築間のホスト状態を前提にできず、常駐サービスやシステム設定も管理できません。これらが公開工程の失敗原因なら、無理にスクリプトを複雑化するより、制御可能なMacへ役割を移すほうが切り分けやすくなります。

一方、すべてを移すと、OS更新、証明書、Keychain、再起動、監視をチーム側で維持する負担が発生します。まずは標準テストをXcode Cloudに残し、問題のあるArchiveとアップロードだけをSFTPMACのリモートMacで短期間検証する方法が現実的です。料金や利用形態を確認する場合は、SFTPMACのMacレンタル案内と、Mac miniレンタルの料金情報を参照し、必要な期間と運用範囲を先に決めます。

sudoの拒否だけなら、移行理由としては弱いです。依存関係を一般ユーザー領域へ移せるか、生成ファイルを成果物として渡せるか、署名を非対話式に再現できるかを確認してください。管理者権限、常駐サービス、永続ファイル、深いシステム設定のどれかが公開処理を止めているなら、リモートMacで短周期の実Archiveと再起動後の復旧まで検証する価値があります。そこまで必要な構成では、Xcode Cloud単独より、標準CIとSFTPMACのリモートMacを分担させるほうが、失敗時の戻し先を残した運用になります。