Автовход на Mac без монитора и почему macOS 27 его пропускает
Арендованный Mac должен сам переживать перезагрузку. Рядом с машиной нет никого, кто введёт пароль. Рабочий стол клиента в браузере подключается к графической сессии входа, поэтому машина должна вернуться уже с выполненным входом. Автовход без монитора на Apple Silicon это небольшая куча конкретных деталей, и четыре из них ломаются молча. Одна появилась в macOS 27. Вот они.
Две настройки, которые его включают
Автовход состоит из двух частей. Настройка с именем пользователя и пароль, сохранённый там, где его может прочитать окно входа.
# 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 замаскирован фиксированным ключом, а не зашифрован. Любой, кто может прочитать файл, восстановит пароль. Это допустимо только потому, что машина доступна только через частную сеть и никогда через публичный интернет. На машине с открытым портом это были бы учётные данные на виду у всех.
Четыре тихие остановки
| Проверка | Вывод, когда всё работает | Вывод, когда что-то сломано | Вердикт |
|---|---|---|---|
| FileVault включён | диск разблокируется, macOS выполняет вход | зависает на разблокировке перед загрузкой | должен быть выключен |
| флаг блокировки экрана при входе | сессия поднимается разблокированной | сессия открыта, экран заблокирован, чёрный | сбросить |
| флаг lastLoginPanic | автовход выполняется | автовход пропущен, показано окно входа | сбросить |
| LaunchAgent в /Library (macOS 27) | загружается после входа | выставляет panic при каждой загрузке | загружать позже |
FileVault
FileVault шифрует диск, и диск нужно разблокировать, прежде чем macOS сможет кого-то впустить. На машине с клавиатурой это делает человек. Без монитора и клавиатуры вводить некому. Поэтому на машине, к которой нельзя прикоснуться, автовход и FileVault взаимоисключающие. Мы работаем с выключенным FileVault и опираемся на частную сеть как на границу.
Флаг блокировки экрана
Есть настройка, которая снова блокирует экран даже после автовхода. Она нужна для машин, которые блокируются при выключении дисплея. Если она включена, сессия поднимается, но экран заблокирован. Удалённый зритель видит это как чёрный экран. Мы сбрасываем autoLoginUserScreenLocked каждый раз, когда включаем автовход.
Флаг panic, который стоил нам дня
Самое коварное. Когда сессия входа завершается сбоем, macOS записывает lastLoginPanic в настройки окна входа. Затем она намеренно пропускает автовход при следующей загрузке и показывает экран входа. Это защитная функция, чтобы машина, которая падает при входе, не уходила в бесконечный цикл.
На только что зарегистрированном Mac самая первая загрузка была занята индексацией большой копии Xcode при средней нагрузке выше 160. Вход не успел завершиться, и флаг выставился. Каждая следующая загрузка пропускала автовход, хотя конфигурация машины была полностью правильной.
sudo defaults delete /Library/Preferences/com.apple.loginwindow lastLoginPanic sudo shutdown -r now
После сброса на успокоившейся машине автовход сразу заработал, с тем же паролем и теми же настройками, что были всё это время. Мы чуть не описали это как баг нового релиза macOS. В тот раз это был не он. Доказательством стал контрольный запуск. Тот же симптом исчез, как только машина перестала быть перегруженной, а исходная конфигурация ни разу не была неправильной. Эта история стоит рядом с другими в посте проверки, которые не могут упасть.
macOS 27: флаг при каждой загрузке
Потом мы зарегистрировали первые M6 mini на macOS 27, и флаг вернулся. На этот раз машины простаивали и были не нагружены. Но они всё равно останавливались на окне входа после каждой перезагрузки, и lastLoginPanic каждый раз выставлялся снова.
В нашем образе есть один LaunchAgent в /Library/LaunchAgents. Он поддерживает работу ИИ-агента для программирования в сессии клиента. Скрипт внутри уже ничего не делал, пока рабочий стол не поднят. Поэтому мы заподозрили сам файл, а не скрипт.
Проверкой стал контрольный запуск. Мы взяли две одинаковые машины на M6 в одном и том же состоянии. На одной был plist, на другой нет. Мы перезагрузили их с разницей в три секунды. Машина без plist выполнила вход. Машина с ним выставила panic и остановилась на окне входа. Когда мы вернули plist на машину, которая нормально входила, она снова застряла при следующей загрузке. Значит, это происходит при каждой загрузке, а не только при первой.
На macOS 27 окно входа загружает LaunchAgents из /Library/LaunchAgents во время процедуры автовхода. На наших машинах этой загрузки хватало, чтобы вход провалился и флаг выставился. Удаление ключа не помогает, потому что следующая загрузка выставляет его снова.
# 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. Теперь небольшой LaunchDaemon от root ждёт, пока появится сессия пользователя и запустится Dock. Потом он загружает агента в эту сессию. Автовход работает при каждой загрузке, а агент стартует примерно через минуту.
По пути нас укусили ещё две детали macOS 27. Во-первых, macOS 27 блокирует экран через несколько секунд после автовхода. Когда экран заблокирован, владелец /dev/console это root. Поэтому не используйте его, чтобы проверить, вошёл ли кто-то. Вместо этого проверяйте домен пользователя gui/UID и запущенный Dock. Во-вторых, Ассистент настройки первого запуска всё ещё привязан к сессии. Если его убить, вся сессия падает на окно входа, и флаг выставляется снова. Отключайте его через ключи настроек и никогда не убивайте.
Рабочий рецепт
Вопросы
- Как автовход macOS хранит пароль?
- В /etc/kcpassword, замаскированным фиксированным ключом XOR, плюс autoLoginUser в настройках loginwindow. Это маскировка, а не шифрование. Поэтому машина должна быть доступна только через частную сеть.
- Ломает ли FileVault автовход?
- Да. С включённым FileVault диск разблокируется до того, как macOS может выполнить автовход. Поэтому машина без монитора сама не пройдёт экран разблокировки перед загрузкой. Для автовхода FileVault должен быть выключен.
- Почему автовход сработал один раз, а потом перестал?
- Неудачный вход выставляет lastLoginPanic в настройках loginwindow, и macOS потом пропускает автовход при следующих загрузках. Удалите этот ключ и перезагрузите машину, когда она не нагружена.
- Почему автовход не работает на macOS 27, если на macOS 26 работал?
- На macOS 27 plist LaunchAgent из /Library/LaunchAgents загружается во время процедуры автовхода. На наших машинах эта загрузка выставляла lastLoginPanic при каждой загрузке, и Mac останавливался на окне входа. Помогло перенести plist из /Library/LaunchAgents и загружать его после входа.
Посчитайте свои цифры в калькуляторе или арендуйте раннер.