Runner внезапно становится Offline, задания зависают в очереди, а удалённый Mac после перезагрузки не возвращается в GitHub.
Самое быстрое решение — использовать постоянно доступный реальный Mac с Apple Silicon, административным доступом и исходящим соединением, зарегистрировать Runner на уровне приватного репозитория или организации, включить системный сервис и проверить не только статус Online, но и маршрутизацию, подпись, очистку рабочих каталогов и восстановление после перезагрузки.
Эта инструкция предназначена для трёх групп:
- разработчиков iOS и macOS, которым нужен собственный узел для сборки, тестирования, подписи или публикации;
- DevOps-инженеров, которые распределяют Runner между несколькими репозиториями и управляют группами, метками и секретами;
- команд, которым недостаточно временной среды из-за постоянного кэша, доступа к внутренним ресурсам или заранее установленного Apple-инструментария.
Подходит ли удалённый Mac для постоянного Runner
Да, но только если вы заранее подтверждаете четыре условия: хост может работать без перерыва, у вас есть права администратора, Runner разрешено установить и запустить как сервис, а машина может обращаться к GitHub и всем ресурсам, которые используются workflow. Само наличие macOS не делает узел производственным: вы отвечаете за операционную систему, инструменты и обслуживание собственного Runner. (Требования GitHub к self-hosted Runner)
Перед установкой зафиксируйте базовые параметры:
uname -m
sw_vers
whoami
df -h /
Для Apple Silicon команда uname -m обычно должна вернуть arm64. Версия macOS должна быть совместима с вашей версией Xcode и SDK, а свободное место нужно оценивать не только по размеру самого Runner, но и по исходникам, DerivedData, архивам, симуляторам, пакетным менеджерам и артефактам. Конкретную совместимость Xcode проверяйте в актуальной таблице Apple, потому что требования меняются вместе с версиями SDK и macOS. (Системные требования Xcode)
Есть и скрытые ограничения:
- Постоянное состояние. В отличие от чистой временной среды, self-hosted Runner может сохранить файлы, кэш, процессы, авторизационные данные и остатки предыдущей сборки.
- Сетевые зависимости. Рабочий процесс может требовать доступ к GitHub, пакетным реестрам, внутреннему Git, хранилищу артефактов, API подписи или корпоративным адресам.
- Права на хосте. Команды workflow выполняются на реальной машине, поэтому неправильно выданные права превращают ошибку в проблему всего узла.
- Ресурсные конфликты. Одновременные задания могут конкурировать за CPU, память, дисковый кэш и симуляторы, если вы не разделили Runner по группам и не ограничили параллельность.
- Отсутствие автоматической чистоты. Среда не становится безопасной только потому, что задание завершилось со статусом
success.
Для одного проекта разумно начать с Runner уровня репозитория. Если один узел должен обслуживать несколько доверенных репозиториев организации, регистрируйте его на уровне организации и сразу назначайте группу доступа. GitHub поддерживает добавление Runner на уровне репозитория, организации и предприятия. (Добавление self-hosted Runner)
| Сценарий | Рекомендуемый уровень | Преимущество | Риск или ограничение |
|---|---|---|---|
| Проверка одного проекта | Репозиторий | Минимальная область доступа и простой откат | Runner нельзя безопасно использовать для других проектов без пересмотра прав |
| Несколько приватных репозиториев одной команды | Организация + Runner group | Общая инфраструктура и единые метки | Ошибка в политике группы затрагивает несколько репозиториев |
| Публичный проект с внешними pull request | Не использовать постоянный Runner | Снижает риск компрометации хоста | Нужна одноразовая изолированная среда или отдельный защищённый контур |
| Подпись и публикация релизов | Отдельная группа | Можно ограничить доступ к секретам и веткам | Требуются строгая проверка workflow и аудит |
Как подготовить Mac и границы доступа
Создайте отдельную учётную запись для CI, если эксплуатационная модель это позволяет. Не смешивайте её с вашим повседневным профилем, личными SSH-ключами, браузерными сессиями, конфигурациями облачных CLI и каталогами разработки. Для системного сервиса особенно важно заранее определить, под каким пользователем запускается Runner и какие каталоги ему доступны.
Минимальная схема разделения выглядит так:
- каталог Runner — отдельно от исходного кода и личного домашнего каталога;
- рабочий каталог — только для задач CI;
- секреты — через GitHub Secrets или Environment Secrets, а не через файл в репозитории;
- сертификаты подписи — с минимальными правами и контролируемым сроком действия;
- production-группа — отдельно от обычных тестовых Runner;
- ветки публикации — под обязательным review и защищёнными правилами.
Не выдавайте Runner доступ ко всей инфраструктуре, если workflow нужен только для сборки и загрузки артефакта. Код, выполняющийся на self-hosted Runner, может получить доступ к содержимому машины, ключам, токенам и сетевым сервисам, доступным с этого хоста. Даже Environment Secrets не превращают выполнение на постоянном Runner в изолированный контейнер. (Рекомендации GitHub по безопасному использованию Actions)
Важно: не проверяйте безопасность постоянного Runner на непроверенной ветке, просто добавив ручное подтверждение окружения. Approval ограничивает выдачу секрета, но не стирает уже выполненный код и не очищает хост после job.
В начале также решите, нужен ли вам именно постоянный узел. Для сборки с большим кэшем, внутренними зависимостями и стабильным Apple-инструментарием он удобен. Для каждого внешнего pull request безопаснее использовать одноразовый Runner, который после одной задачи удаляется и очищается. Постоянный Runner не гарантирует чистую виртуальнуюную машину после каждого запуска.
Как выбрать архитектуру и модель маршрутизации
Для Apple-ориентированного проекта предпочтителен реальный Mac с Apple Silicon, если ваши зависимости, симуляторы, нативные пакеты или сценарии подписи должны проверяться именно в arm64-среде. Конкретная версия Xcode должна соответствовать поддерживаемой версии macOS, поэтому проверяйте совместимость непосредственно перед подготовкой узла.
Проверяйте архитектуру не по названию тарифа или удалённой панели, а на самой машине:
uname -m
system_profiler SPHardwareDataType
В workflow не полагайтесь только на метку self-hosted. GitHub автоматически добавляет метки операционной системы и архитектуры, включая macOS и ARM64, а пользовательские метки можно объединять: Runner подходит только тогда, когда совпадают все заданные условия. (Маршрутизация заданий по меткам)
| Вариант маршрутизации | Пример runs-on |
Когда использовать | Что проверить |
|---|---|---|---|
| Любой macOS Runner | [self-hosted, macOS] |
Только если архитектура несущественна | Не попал ли job на неподходящий Intel-узел |
| Apple Silicon | [self-hosted, macOS, ARM64] |
Нативная сборка, arm64-зависимости, visionOS | Совпадает ли фактический uname -m |
| Роль узла | [self-hosted, macOS, ARM64, ios-build] |
Разделение тестовой и production-сборки | Назначена ли метка только нужной группе |
| Группа организации | group: mac-builders |
Общий пул доверенных репозиториев | Какие репозитории разрешены группе |
Пример минимального задания для первичной проверки:
name: Проверка Mac Runner
on:
workflow_dispatch:
jobs:
inspect-runner:
runs-on: [self-hosted, macOS, ARM64]
steps:
- name: Архитектура
run: uname -m
- name: Система
run: sw_vers
- name: Версии инструментов
run: |
xcodebuild -version
git --version
Не называйте эту проверку полноценной сборкой. Она доказывает, что job попал на нужный macOS-сборочный узел и что базовые инструменты доступны. Она ещё не подтверждает корректность signing identity, provisioning profile, кэша, доступа к реестрам или загрузки артефактов.
Регистрация Runner по актуальным командам GitHub
Не фиксируйте в статье или внутренней инструкции номер пакета Runner, потому что GitHub использует обновляемые инструкции, а релизы распространяются постепенно. Источник истины — кнопка добавления Runner в вашем интерфейсе, а не скопированная команда из старого README. (Официальные релизы actions/runner)
1. Выберите область регистрации
Для одного проекта откройте настройки репозитория: Settings → Actions → Runners → New self-hosted runner. Для нескольких репозиториев используйте настройки организации и создайте Runner group с явным списком разрешённых репозиториев.
На странице GitHub выберите macOS и фактическую архитектуру машины. Интерфейс сгенерирует актуальные команды загрузки, распаковки и настройки. Токен регистрации временный: GitHub указывает, что он действует один час, поэтому не сохраняйте его в скриптах, тикетах или переменных общего доступа. (Инструкция по добавлению Runner)
2. Создайте отдельный каталог
Например:
mkdir -p ~/ci/actions-runner
cd ~/ci/actions-runner
Затем вставьте команды загрузки и распаковки, которые GitHub показал именно для выбранной архитектуры. Не заменяйте arm64 на x64, если uname -m вернул arm64, и не скачивайте пакет из случайного зеркала.
3. Запустите конфигурацию
Выполните сгенерированную команду config.sh. В обобщённом виде она выглядит так:
./config.sh \
--url https://github.com/ВАША-ОРГАНИЗАЦИЯ \
--token ВРЕМЕННЫЙ_ТОКЕН
В процессе задайте:
- понятное имя, например
mac-arm64-ci-01; - рабочую группу, если она уже создана;
- пользовательские метки
ios-build,signingилиinternal-network; - рабочий каталог, если стандартный вариант не соответствует вашей схеме хранения.
Не добавляйте --disableupdate, если у вас нет отдельного процесса регулярного обновления и проверки совместимости. При отключении автоматических обновлений ответственность за своевременное обновление Runner полностью переходит к вам. Устаревшее приложение может перестать принимать задания после достижения порога совместимости. (Справочник self-hosted runners)
4. Проверьте первое подключение
Временно запустите:
./run.sh
Ожидаемый результат — подключение к GitHub и состояние ожидания заданий. Одновременно откройте страницу Runners и убедитесь, что имя, архитектура и пользовательские метки отображаются корректно. Если Runner виден как Online, это подтверждает только канал связи и активность приложения, но не готовность к production-сборке.
5. Установите системный сервис
После остановки ручного процесса выполните:
./svc.sh install
./svc.sh start
./svc.sh status
На macOS используется launchd. GitHub документирует для macOS проверку через svc.sh status и launchctl; имя сервиса можно посмотреть в файле .service, который создаётся в каталоге Runner. (Настройка Runner как сервиса)
Проверьте запуск без активной SSH-сессии:
exit
Через некоторое время снова откройте GitHub и убедитесь, что Runner остаётся Online. После этого выполните фактическую перезагрузку Mac, а не только перезапуск терминала:
sudo shutdown -r now
Успешная проверка означает, что после загрузки системы сервис стартует самостоятельно, подключается к GitHub и снова принимает задания. Если после перезагрузки требуется ручной ./run.sh, установка не завершена.
Первичная проверка workflow и инструментов
После регистрации разделите проверку на два уровня.
Уровень связи и маршрутизации:
- job запускается на ожидаемой пользовательской метке;
- архитектура возвращает
arm64; - версия macOS записывается в лог;
- Runner остаётся Online после завершения job;
- задания от неподходящих меток остаются в очереди, а не выполняются на другом узле.
Уровень проекта:
- зависимости устанавливаются из разрешённых источников;
- кэш не содержит чужих секретов;
xcodebuildвидит нужную схему;- тесты проходят в требуемом окружении;
- signing identity и provisioning profile доступны только нужной job;
- артефакт загружается в ожидаемое хранилище.
Пример проверки окружения:
name: Проверка macOS-сборочного узла
on:
workflow_dispatch:
jobs:
verify:
runs-on: [self-hosted, macOS, ARM64, ios-build]
steps:
- uses: actions/checkout@v6
- name: Сведения о хосте
run: |
uname -m
sw_vers
xcodebuild -version
- name: Проверка свободного места
run: df -h /
- name: Базовая сборка
run: |
xcodebuild \
-scheme "ВАША_СХЕМА" \
-destination "generic/platform=iOS" \
build
Версию actions/checkout и остальные actions также сверяйте с политикой вашего проекта; приведённый фрагмент показывает структуру проверки, а не универсальную матрицу совместимости. Если проект использует Xcode или симуляторы, фиксируйте в артефактах версию Xcode, macOS и выбранный destination. Это позволит отличить проблему кода от изменения среды.
Не переносите в эту установку миграционные решения для конкретной версии Xcode без отдельной проверки. Требования Apple зависят от версии Xcode, macOS и SDK, поэтому production-узел должен иметь документированное окно обновления, а не случайно установленную последнюю версию.
Защита секретов и рабочего каталога
Постоянный Runner нужно считать компьютером, на котором может выполняться произвольный shell-код из разрешённого workflow. Поэтому настройте его как отдельный производственный ресурс, а не как второй рабочий стол разработчика.
Проверьте следующие пункты:
- [ ] CI-пользователь не использует личные SSH-ключи и браузерные токены.
- [ ] В Runner group разрешены только нужные приватные репозитории.
- [ ] Production-метка отсутствует на тестовых workflow.
- [ ] Секреты передаются через Secrets или Environment Secrets.
- [ ] Сертификаты подписи не лежат в репозитории и не попадают в общий домашний каталог.
- [ ] После job удаляются временные профили, ключи и экспортированные пароли.
- [ ] Рабочая директория очищается перед следующим доверенным запуском.
- [ ] Логи не содержат токены, содержимое сертификатов и приватные URL.
- [ ] Доступ к внутренним сервисам ограничен сетевыми правилами.
- [ ] Публичные pull request не направляются на этот узел.
Особое внимание уделите fork и pull request. Даже если ветка выглядит безобидно, workflow может изменить shell-скрипты, зависимости или команды сборки. Постоянный Runner для публичного репозитория следует считать небезопасным вариантом, поскольку внешний pull request способен изменить состояние хоста и получить доступ к доступным ему ресурсам.
Для подписи используйте отдельное окружение и контролируемое событие запуска, например защищённую ветку или ручной workflow с review. Успешная компиляция и успешная подпись — разные критерии. Тестовая job может завершиться успешно при полном отсутствии production-сертификата, поэтому проверяйте каждую операцию отдельно и сохраняйте только необходимые диагностические данные.
Эксплуатация, обновления и восстановление
Ежедневный контроль должен включать не только зелёный статус последнего workflow. Проверяйте:
- состояние Runner в GitHub;
- очередь заданий и длительность ожидания;
./svc.sh status;- содержимое
_diag; - свободное место;
- состояние кэша и каталогов DerivedData;
- доступ к пакетным реестрам;
- успешность автоматического обновления Runner;
- дату последнего тестового перезапуска.
Логи Runner хранятся в каталоге _diag, где создаются файлы запуска приложения и отдельные журналы выполнения job. На macOS для проверки launchd используйте:
./svc.sh status
cat .service
launchctl list | grep actions.runner
Если Runner отображается как Offline, проверяйте проблему по слоям:
- Процесс: запущен ли сервис и существует ли процесс launchd.
- Регистрация: совпадает ли имя Runner и его регистрация с текущей организацией или репозиторием.
- Сеть: доступны ли GitHub и необходимые домены, не блокируется ли исходящий TLS.
- Сертификаты: не было ли перехвата TLS корпоративным прокси.
- Ресурсы: не закончились ли диск, память или доступные файловые дескрипторы.
- Обновление: не остановился ли Runner во время обновления приложения или macOS.
- Питание и сон: не переводится ли удалённый Mac в состояние, при котором сервис недоступен.
Не отключайте проверку TLS как постоянное исправление. Переменная GITHUB_ACTIONS_RUNNER_TLS_NO_VERIFY предназначена только для диагностики и снижает защиту конфиденциальности и целостности соединения. Сначала установите корректный сертификат в системное хранилище и проверьте сетевую конфигурацию. (Диагностика self-hosted Runner)
Финальная приёмка должна включать четыре сценария:
- перезагрузка Mac и автоматическое возвращение Runner Online;
- повторный запуск неудачной job после исправления причины;
- очистка диска и проверка, что старые артефакты не мешают новой сборке;
- остановка и удаление Runner из GitHub без оставшихся секретов и сервисов.
Только после этих проверок узел можно считать рабочим macOS-сборочным узлом. Один успешно завершившийся build доказывает лишь то, что конкретный код собрался один раз.
Частые вопросы
Как установить GitHub Actions Runner на удалённый Mac?
Откройте в нужном репозитории или организации раздел Settings → Actions → Runners, выберите macOS и архитектуру Apple Silicon, затем скопируйте актуальные команды загрузки и настройки. Выполните их в отдельном каталоге на Mac, укажите имя и метки Runner, подтвердите подключение и только после этого установите системный сервис.
Как сделать так, чтобы macOS Runner запускался после перезагрузки?
После регистрации остановите запущенный вручную процесс и выполните в каталоге Runner команды ./svc.sh install, ./svc.sh start и ./svc.sh status. На macOS используется launchd. Проверяйте не только локальный статус сервиса, но и состояние Online в GitHub после выхода из SSH и после фактической перезагрузки хоста.
Как направить задачу GitHub Actions на Mac с Apple Silicon?
Используйте комбинацию стандартных меток self-hosted, macOS и ARM64, а для точного назначения добавьте собственную метку, например ios-signing или xcode-prod. В workflow укажите все необходимые метки в runs-on: Runner будет выбран только при полном совпадении набора условий.
Что проверить, если удалённый Mac Runner стал Offline?
Сначала проверьте ./svc.sh status, каталог _diag, доступ к GitHub и корректность системного пользователя. Затем исключите блокировку исходящих соединений, остановку после обновления macOS и нехватку диска. Если сервис запущен, но Runner Offline, сопоставьте имя сервиса из файла .service с процессом launchd и журналом запуска.
Подходит ли постоянный Runner для публичного репозитория?
Обычно нет. Код из внешнего pull request может выполняться на том же хосте и оставить файлы, процессы или ключи после завершения задания. Для публичных проектов используйте изолированные одноразовые среды либо отдельный безопасный контур без постоянных секретов; постоянный Mac Runner оставляйте для доверенных веток и приватных репозиториев.
Если у вас уже есть подходящий Mac, этот план позволяет превратить его в управляемый узел CI/CD без закрепления устаревшего токена или версии Runner. Если собственного оборудования нет, остаются реальные недостатки самостоятельной схемы: покупка Mac замораживает бюджет, обслуживание, обновления и восстановление ложатся на вашу команду, а домашний узел часто не даёт предсказуемой доступности и безопасного сетевого доступа.
В таком случае можно сначала изучить варианты удалённого использования Mac для разработки, затем сверить актуальные условия аренды Mac и выбрать подходящий способ заказа Mac-среды. После получения доступа применяйте ту же последовательность: отдельная учётная запись, регистрация Runner, метки Apple Silicon, системный запуск, изоляция секретов и обязательная проверка восстановления после перезагрузки.
Надёжный Mac-узел для GitHub Actions
KVMFLUX предоставляет удалённый Mac для постоянного запуска сборок, тестирования и публикации приложений в среде macOS. Выберите подходящую конфигурацию и используйте выделенный ресурс как self-hosted Runner для рабочих процессов вашей команды. Удалённый доступ помогает централизованно выполнять подпись приложений и управлять сборочными задачами без локального Mac. Оформите аренду Mac в KVMFLUX и подготовьте стабильный узел для автоматизации CI/CD в соответствии с требованиями проекта.