ヘッドレスMacの自動ログインと、macOS 27がそれをスキップする理由
レンタルするMacは、再起動を自力で乗り切らなければなりません。マシンの前に立ってパスワードを入力する人はいません。お客様のブラウザのデスクトップはグラフィカルなログインセッションに接続するので、マシンはログインした状態で戻ってくる必要があります。Apple Siliconでのヘッドレス自動ログインは、細かな設定の小さな寄せ集めで、そのうち4つは黙って失敗します。そのひとつはmacOS 27で新しく加わったものです。順に説明します。
自動ログインを有効にする2つの設定
自動ログインは2つの要素でできています。ユーザーを指定する設定と、ログイン画面が読める場所に保存したパスワードです。
# who logs in automatically defaults write /Library/Preferences/com.apple.loginwindow autoLoginUser runner # the password, XOR-obfuscated, in /etc/kcpassword # (padded to a multiple of 12 bytes, keyed with a fixed vector)
/etc/kcpasswordは固定のキーで難読化されているだけで、暗号化されてはいません。このファイルを読める人なら誰でも、パスワードを復元できます。それが許容できるのは、マシンにプライベートなネットワーク経由でしかアクセスできず、パブリックなインターネットからは決して届かないからです。ポートが開いたマシンなら、認証情報がむき出しで置いてあるのと同じです。
黙って止まる4つの要因
| 確認項目 | 正常時の出力 | 異常時の出力 | 判定 |
|---|---|---|---|
| FileVaultがオン | ディスクのロックが解除され、macOSがログインする | 起動前のロック解除で止まる | オフにする |
| ログイン時の画面ロックのフラグ | ロックされていない状態でセッションが起動する | セッションは解除済みだが画面はロック、真っ黒 | 消去する |
| lastLoginPanicのフラグ | 自動ログインが進む | 自動ログインがスキップされ、ログイン画面が表示される | 消去する |
| /LibraryにあるLaunchAgent(macOS 27) | ログイン後に読み込まれる | 起動のたびにpanicのフラグをセットする | 後で読み込む |
FileVault
FileVaultはディスクを暗号化します。macOSが誰かをログインさせる前に、ディスクのロックを解除する必要があります。キーボードのあるマシンなら、人がロック解除のパスワードを入力します。ヘッドレスでは入力する人がいないので、触れることのできないマシンでは自動ログインとFileVaultは両立しません。当社はFileVaultをオフにして運用し、プライベートなネットワークを境界として頼りにしています。
画面ロックのフラグ
自動ログインのあとでも画面を再びロックする設定があります。ディスプレイのスリープでロックするマシン向けのものです。これがセットされていると、セッションは起動しますが画面はロックされ、リモートで見ている人には真っ黒に見えます。当社は自動ログインを有効にするたびにautoLoginUserScreenLockedを消去しています。
1日を失ったpanicのフラグ
わかりにくいのがこれです。ログインセッションが失敗すると、macOSはログイン画面の設定にlastLoginPanicを記録します。そして次の起動では意図的に自動ログインをスキップし、代わりにログイン画面を表示します。ログイン時にクラッシュするマシンがループしないようにするための安全機能です。
登録したばかりのMacでは、最初の起動時に大きなXcodeのコピーのインデックス作成が走り、ロードアベレージは160を超えていました。ログインが時間内に終わらず、フラグがセットされました。それ以降の起動ではすべて自動ログインがスキップされました。設定は完全に正しいマシンだったのにです。
sudo defaults delete /Library/Preferences/com.apple.loginwindow lastLoginPanic sudo shutdown -r now
負荷が落ち着いたマシンでフラグを消すと、自動ログインはすぐに動きました。パスワードも設定も、ずっと同じままでした。危うく、新しいmacOSリリースのバグとして報告するところでした。このときは、そうではありませんでした。証明したのは対照実験です。マシンが過負荷でなくなると同じ症状は消え、根本の設定は一度も間違っていませんでした。この話は、ほかの話と一緒に失敗しようがない確認処理に書いています。
macOS 27:起動のたびにセットされるフラグ
その後、macOS 27を入れた最初のM6 miniを登録したところ、フラグが戻ってきました。今回のマシンはアイドル状態で、負荷も落ち着いていました。それでも再起動のたびにログイン画面で止まり、毎回lastLoginPanicが再びセットされていました。
当社のイメージには、/Library/LaunchAgentsにLaunchAgentが1つ入っています。お客様のセッションでAIコーディングエージェントを動かし続けるためのものです。その中のスクリプトは、もともとデスクトップが起動していなければ何もしません。そこで、スクリプトではなくファイルそのものを疑いました。
確かめる方法は対照実験でした。同じ状態のM6を2台用意しました。1台にはplistがあり、もう1台にはありません。3秒差で両方を再起動しました。plistのないほうはログインしました。plistのあるほうはpanicを起こし、ログイン画面で止まりました。問題なくログインしていたマシンにplistを戻すと、次の起動でまた止まりました。つまり最初の起動だけでなく、毎回の起動で起きます。
macOS 27では、ログイン画面が自動ログインの処理中に/Library/LaunchAgentsからLaunchAgentを読み込みます。当社のマシンでは、その読み込みだけでログインが失敗し、フラグがセットされました。キーを消しても効果はありません。次の起動でまたセットされるからです。
# the fix: keep the plist out of the auto-load path sudo mv /Library/LaunchAgents/dev.example.agent.plist /opt/example/launchd/ # then load it into the user's session after login, from a root daemon launchctl bootstrap gui/$(id -u runner) /opt/example/launchd/dev.example.agent.plist
plistを/Library/LaunchAgentsの外に移しました。現在は、rootで動く小さなLaunchDaemonが、ユーザーのセッションができてDockが動き出すのを待ちます。それから、エージェントをそのセッションに読み込みます。自動ログインは毎回の起動で動き、エージェントは約1分後に起動します。
その過程で、macOS 27のほかの細かい点にも2つつまずきました。1つめに、macOS 27は自動ログインの数秒後に画面をロックします。ロックされていると/dev/consoleの所有者はrootになるので、誰かがログインしているかの確認には使わないでください。代わりに、ユーザーのgui/UIDドメインと、Dockが動いているかを確認します。2つめに、初回起動時の設定アシスタントがまだセッションに結びついています。これを強制終了すると、セッション全体がログイン画面に落ち、フラグが再びセットされます。設定キーで表示を抑え、決して強制終了しないでください。
動く手順
よくある質問
- macOSの自動ログインはパスワードをどう保存していますか?
- /etc/kcpasswordに、固定のXORキーで難読化して保存します。加えて、loginwindowの設定にautoLoginUserを書き込みます。これは暗号化ではなく難読化です。だからこそ、マシンにはプライベートなネットワーク経由でしかアクセスできないようにする必要があります。
- FileVaultを有効にすると自動ログインは使えなくなりますか?
- はい。FileVaultがオンだと、macOSが自動ログインする前にディスクのロック解除が必要です。そのためヘッドレスのマシンは、起動前の画面を自力で通過できません。自動ログインにはFileVaultをオフにする必要があります。
- 自動ログインが一度は動いたのに、その後止まったのはなぜですか?
- ログインに失敗すると、loginwindowの設定にlastLoginPanicがセットされます。するとmacOSは、それ以降の起動で自動ログインをスキップします。負荷が落ち着いたマシンでそのキーを消して、再起動してください。
- macOS 26では動いた自動ログインが、macOS 27で失敗するのはなぜですか?
- macOS 27では、/Library/LaunchAgentsにあるLaunchAgentのplistが、自動ログインの処理中に読み込まれます。当社のマシンでは、この読み込みのせいで起動のたびにlastLoginPanicがセットされ、Macはログイン画面で止まりました。plistを/Library/LaunchAgentsの外に移し、ログイン後に読み込むようにして解決しました。