Macは再起動後にSSH接続できるのに、GitLab Runnerだけオフラインです。
最短の解決策は再インストールではなく、Mac本体、ログインセッション、LaunchAgent、Runner登録、通信の順に停止条件を設けて切り分けることです。
このガイドは、単一の遠隔Mac CIノードを保守する開発者、複数プロジェクトのGitLab Runnerを管理するDevOps・リリース担当者、再起動後の受け入れ基準を作るプラットフォームチーム向けです。初回インストールや登録方法ではなく、再起動後の復旧に絞ります。
まず「オフライン」の層を分けます
典型的な失敗は、Macの再起動後にSSHだけが先に戻り、GitLab画面ではRunnerがオフラインのままになるケースです。ここでサービスを削除すると、原因と復旧経路を同時に失います。
次の順番で確認します。
- Mac本体:SSHまたはVNCで到達できるか。
- ユーザーセッション:Runnerを登録したユーザーがグラフィカルにログインしているか。
- プロセスとLaunchAgent:Runnerプロセスが動いているか。
- GitLabへの接続:ログに接続失敗、証明書、プロキシの異常がないか。
- ジョブ割り当て:Runnerはオンラインでも、タグ不一致で待機していないか。
各層で正常なら次へ進みます。SSHが通らない段階でRunnerの登録を調べても、証拠が増えません。
第一段階:ユーザーセッションを復元します
GitLab公式は、macOSのRunnerをユーザー単位のLaunchAgentで動かす方式として説明しています。システム全体のLaunchDaemonへ置き換える構成ではありません。macOS版GitLab Runnerのサービスモードを確認し、登録したユーザーでログインしているかを調べます。
SSHで次を実行し、ユーザーとプロセスの手掛かりを取ります。<runner-user>、<runner-config>、<project>などは実環境の値に置き換えてください。
whoami
launchctl print "gui/$(id -u)"
ps aux | grep '[g]itlab-runner'
gitlab-runner verify --config <runner-config>
launchctl printでGUIドメインが見つからない、または対象ユーザーが未ログインなら、純粋なSSH操作だけで直そうとしないでください。VNCまたはWebコンソールで同じユーザーのデスクトップへ入り、その画面のターミナルでサービス操作を再実行します。
通常のShellビルドだけなら、ログイン後にRunnerが戻るかを確認できます。しかし、コード署名、Keychain、iOS Simulatorを使うジョブは、プロセスが存在するだけでは不十分です。署名鍵とシミュレーターを利用できるユーザーセッションまで復旧しているかを、実ジョブで確認します。
自動ログインは復旧手段の一つにすぎません。AppleはFileVaultや組織のセキュリティポリシーによって自動ログインが制限される場合を案内しています。Macの自動ログインに関するAppleの説明を確認し、保護機能を先に無効化しないでください。
第二段階:LaunchAgentのドメインとファイルを調べます
SSHでログインしたシェルと、MacのGUIで開いたターミナルは、同じユーザー名でもサービスのbootstrap環境が異なることがあります。launchctl failed: Could not find domain forが出た場合は、インストール失敗と決めつけず、GUIセッションの有無を先に確認します。
確認する対象は4つです。
- ユーザーのLaunchAgent plistが存在するか。
- plistが呼び出すRunnerバイナリのパスが有効か。
<runner-config>の所有者と読み取り権限が正しいか。- ログ出力先のディレクトリが存在し、対象ユーザーから書き込めるか。
GitLabのRunnerコマンドと設定パスの公式資料を基準に、実際のパスを確認します。
ls -l <launchagent-plist>
ls -l <runner-binary>
ls -ld <log-directory>
ls -l <runner-config>
plistを見つけられない場合でも、いきなり削除して再登録しないでください。登録トークン、タグ、executor、既存ログを保存したうえで、サービスファイルだけが壊れているのかを判断します。LaunchAgentをLaunchDaemonへ移す回避策は、GitLab公式のmacOSサービスモデルから外れます。
第三段階:終了コードとログから修復範囲を決めます
killed: 9、exit status 134、Load failed: 5は同じ意味ではありません。Runnerの起動ログ、LaunchAgentの読み込み結果、直前の再起動時刻を一つの時系列に並べます。
killed: 9:プロセスが強制終了された証拠として、OS側のプロセス終了記録とバイナリの実行状態を確認します。exit status 134:Runnerの標準エラー出力と設定ファイルの読み込み結果を保存します。Load failed: 5:plistのパス、所有権、GUIドメイン、ログ出力先を優先して調べます。
エラーの扱いはGitLab公式のmacOSトラブルシューティングに合わせます。修復後は、同じユーザーのGUIターミナルからサービスを読み込み、Runnerプロセス、GitLab画面、テストジョブの3点を確認します。
FAQ:再起動後に起きやすい4つの分岐
Macの起動後にRunnerが自動でオンラインへ戻らない理由
macOSのGitLab RunnerはユーザーのLaunchAgentとして動くため、Mac本体の起動とRunnerの起動は同一ではありません。対象ユーザーのGUIログインが完了していなければ、Runnerが停止したままになることがあります。FileVaultや組織ポリシーが自動ログインを制限する場合もあり、手動ログインを含む復旧経路を用意します。
SSHでlaunchctlのdomainが見つからない場合
SSHだけでLaunchAgentを扱うと、GUI bootstrap domainが存在しない、または現在のシェルから参照できない場合があります。VNCやWebコンソールで対象ユーザーのデスクトップへ接続し、そのターミナルから操作してください。plistや登録情報を先に保存すれば、再インストールが必要になった場合も復元できます。
オンラインなのにジョブが待機する場合
Runnerのオンライン表示は、ジョブを実行できることを保証しません。タグ、保護設定、executor、ジョブの実行条件を照合します。GitLab公式のRunnerタグ割り当て規則に従い、macOS用タグがジョブとRunnerの双方に設定されているか確認します。
FileVault環境で遠隔復旧する場合
FileVaultでは、起動後のディスク解除とGUIログインを分けて考えます。自動ログインを先に有効化するのではなく、コンソール接続、管理ポリシー、VNCの到達性を確認してください。署名やSimulatorのジョブがある場合は、Keychainを利用できるユーザーセッションを復元できることが合格条件です。
第四段階:Runnerオンライン後の通信と登録を確認します
プロセスが動いていても、GitLabへ接続できなければジョブを取得できません。Runnerログの接続時刻をGitLab側の最終接続時刻と照合し、次を分けて記録します。
- プロキシ変更やDNS障害による接続タイムアウト。
- 証明書チェーンや社内CAの変更。
- Runner登録情報の無効化や置き換え。
- ジョブタグの不一致による待機。
設定変更時はGitLab Runnerの高度な設定を参照し、推測で設定項目を追加しないでください。登録状態が壊れている場合も、既存の設定ファイルを保管してから再登録します。
Shell executorはRunnerユーザーの権限をそのまま使ってコマンドを実行します。GitLabのShell executor安全ガイドが示す通り、信頼できないプロジェクトを共有ノードで実行しないでください。別プロジェクトのソース、署名鍵、環境変数、キャッシュが残る構成なら、Runnerを分離する方が先です。
復旧後に実施する再起動受け入れチェック
一度オンラインになっただけでは、再起動障害は解消したと判断できません。次のチェックを上から実行し、証跡を保存します。
- [ ] 正常なCIジョブを完了させ、ログと成果物を保存する。
- [ ]
<runner-user>、<runner-config>、タグ、executorを記録する。 - [ ] Macを通常手順で再起動する。
- [ ] SSHとVNCまたはWebコンソールの両方で到達性を確認する。
- [ ] 対象ユーザーのGUIログイン状態を確認する。
- [ ] LaunchAgent、Runnerプロセス、設定ファイル、ログ出力先を確認する。
- [ ] GitLab画面で最終接続時刻とRunnerのタグを確認する。
- [ ] GUI不要のShellビルドを実行する。
- [ ] コード署名、Keychain、Simulatorを使うジョブを別に実行する。
- [ ] 失敗時の手動復旧手順と、復旧に必要なコンソール経路を文書化する。
MacをCIノードとして用意する段階では、MACCOMEのMac環境に関する案内と、物理運用との違いを整理できるMac miniの運用ガイドも確認してください。重要なのは、SSHだけでなくGUIへ戻れる経路を最初から確保することです。
判定表:修復を続けるか、構成を見直すか
| 確認結果 | 主な原因 | 次の判断 |
|---|---|---|
| SSHもGUIも到達不可 | Mac本体、電源、ネットワーク | ホスト側の復旧を優先 |
| SSHは通るがGUI未ログイン | ユーザーセッション、FileVault、管理ポリシー | コンソール復旧手順を整備 |
| GUIはあるがLaunchAgentなし | サービスファイル、パス、権限 | 設定保存後にサービスを修復 |
| Runnerはオンライン、ジョブは待機 | タグ、保護設定、実行条件 | CI定義とRunner設定を照合 |
| Shellは成功、署名やSimulatorは失敗 | KeychainまたはGUI依存 | ユーザーセッション込みで再設計 |
| 毎回手動復旧が必要 | 運用経路と自動復旧条件の不一致 | 予備ノードまたは提供方式を再評価 |
既存のWindowsやLinuxホストからSSHでMacを呼び出す構成は、Mac本体の再起動、GUIログイン、FileVault解除を別管理しなければならず、署名ジョブでは手動介入が残りやすい点が弱点です。自前のMac mini運用も、電源・コンソール接続・保守担当・予備機の確保が必要になります。まずMACCOMEのようにSSHとグラフィカルな管理経路を併用できるレンタルMacで再起動試験を行い、Runner、署名、Simulatorが戻ることを確認してから本番移行や予備ノード追加を判断すると、復旧不能な構成を先に作らずに済みます。