Self-hosted Runner GitHub Actions на Mac в 2026

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)

Есть и скрытые ограничения:

  1. Постоянное состояние. В отличие от чистой временной среды, self-hosted Runner может сохранить файлы, кэш, процессы, авторизационные данные и остатки предыдущей сборки.
  2. Сетевые зависимости. Рабочий процесс может требовать доступ к GitHub, пакетным реестрам, внутреннему Git, хранилищу артефактов, API подписи или корпоративным адресам.
  3. Права на хосте. Команды workflow выполняются на реальной машине, поэтому неправильно выданные права превращают ошибку в проблему всего узла.
  4. Ресурсные конфликты. Одновременные задания могут конкурировать за CPU, память, дисковый кэш и симуляторы, если вы не разделили Runner по группам и не ограничили параллельность.
  5. Отсутствие автоматической чистоты. Среда не становится безопасной только потому, что задание завершилось со статусом 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. Выберите область регистрации

Для одного проекта откройте настройки репозитория: SettingsActionsRunnersNew 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, проверяйте проблему по слоям:

  1. Процесс: запущен ли сервис и существует ли процесс launchd.
  2. Регистрация: совпадает ли имя Runner и его регистрация с текущей организацией или репозиторием.
  3. Сеть: доступны ли GitHub и необходимые домены, не блокируется ли исходящий TLS.
  4. Сертификаты: не было ли перехвата TLS корпоративным прокси.
  5. Ресурсы: не закончились ли диск, память или доступные файловые дескрипторы.
  6. Обновление: не остановился ли Runner во время обновления приложения или macOS.
  7. Питание и сон: не переводится ли удалённый 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 в соответствии с требованиями проекта.

Mac Mini M4 · 16GB / 256GB
Сутки$19.3 /сутки
Неделя$52.2 /нед.
Месяц$96.7 /мес.
Квартал$263 /квартал