Команды на Windows или Linux, которые выпускают пайплайны iOS / macOS, в 2026 году снова упираются в развилку: платить за хостинговые macOS runner GitHub (поминутная оплата, эфемерные окружения), или зарегистрировать self-hosted runner на выделенном удалённом Mac mini (постоянный диск, предсказуемая помесячная аренда). Эта статья — про второй путь, собственные macOS runner для GitHub Actions, а не про OpenClaw и долгоживущих агентов. Разберём экономику хостинга и self-hosted, выбор из шести регионов, память M4 и параллельные слоты, DerivedData и диск, шардирование по labels, HowTo регистрации, посуточную и помесячную TCO и FAQ. Сравните тарифы на странице цен и заметки по Runner/SSH в разделе помощи. Если вы также крутите агентов автоматизации, см. руководство по OpenClaw на удалённом Mac — но здесь фокус на CI/CD.
Если у вас нет локального Mac, а релизный календарь уже завязан на Xcode, имеет смысл заранее зафиксировать один узел runner, политику кэша и срок аренды (день для A/B региона, месяц для main). Так вы не будете каждый спринт пересчитывать минуты hosted macOS с нуля — достаточно обновлять таблицу TCO раз в квартал по фактическому биллингу Actions.
1) Хостинговые macOS runner против self-hosted на удалённом Mac: минуты, очереди и когда выигрывает bare metal
GitHub тарифицирует хостинговые macOS runner по минутам Actions; тарифы и бесплатные квоты описаны в документации по биллингу GitHub (в 2026 году цены на hosted runner менялись — сверьте актуальную стоимость минуты перед бюджетом). Хостинг силён в нулевой эксплуатации: каждый job стартует с чистого образа — нормально для редких PR или архивов. Минусы те же: DerivedData и кэши SwiftPM редко переживают job, очереди растут в пик, а счёт по минутам скачет с релизным ритмом.
На выделенном Mac mini M4 у Nuvcloud (или аналогичном bare-metal Mac cloud) self-hosted runner покупает фиксированный слот и постоянный SSD: один процесс actions-runner под launchd, с переиспользованием ~/Library/Developer/Xcode/DerivedData между PR. Инкрементальные сборки часто быстрее «холодных» hosted job (точная дельта зависит от репозитория — цифры ниже шаблоны, не SLA).
| Путь | Лучше, когда | Основная стоимость |
|---|---|---|
| GitHub-hosted macOS | < нескольких сотен macOS-минут в месяц, кэш не нужен, не хотите возиться с машиной. | Минуты + время в очереди; DerivedData не держится. |
| Self-hosted на удалённом Mac | Ежедневные сборки main, несколько схем, быстрый Archive/TestFlight. | Обновления runner, гигиена диска, mutex подписи; аренда предсказуема. |
| Офисный Mac mini | Один офис, мультирегион не нужен, принимаете риски питания и доступа. | CapEx + электричество + люди; масштаб = ещё коробки. |
Шаблон TCO на 12 месяцев (примерные допущения — подставьте свои цифры): пусть hosted macOS стоит P за минуту, а месячный объём M минут; год hosted ≈ 12 × M × P. Аренда удалённого Mac R в месяц; год аренды ≈ 12 × R. Когда M × P стабильно выше R и нужен тёплый DerivedData, self-hosted обычно выигрывает; при крошечном и рваном M оставайтесь на hosted или арендуйте посуточно, чтобы проверить workflow перед помесячным контрактом.
Практичный компромисс 2026 года: lint и unit-тесты на Linux hosted (дёшевые минуты), а xcodebuild, Archive и нотаризацию — на один self-hosted Mac. Так вы жжёте меньше macOS-минут и сохраняете кэш там, где он важен. Зафиксируйте разделение в README workflow, чтобы при рефакторинге тяжёлые compile job не уехали обратно на hosted macOS.
2) Сингапур, Япония, Корея, Гонконг, восток и запад США: ставьте runner рядом с Git, registry и артефактами
У Nuvcloud в APAC — Сингапур, Япония, Корея, Гонконг, в Северной Америке — восток и запад США (SKU уточняйте в мастере заказа). Не спрашивайте «что ближе к моей квартире»; смотрите, где сходятся Git remote, container registry, TestFlight/подпись и часовые пояса дежурных. Оформление по регионам: Сингапур, Япония, Корея, Гонконг, восток США, запад США.
Сравните финалистов одним скриптом: git clone --depth=1, скачайте артефакт ~1 ГБ, сравните cold vs warm xcodebuild -showBuildSettings. RTT SSH для админов — метрика комфорта, не доминирующая в wall time CI.
При корпоративном proxy или split-tunnel VPN гоняйте бенчмарки с хоста runner, а не с ноутбука в гостевой Wi‑Fi. Политика egress на Mac (registry, Apple, GitHub API) — часть выбора региона: «быстрая» география бесполезна, если HTTPS к вашему bucket режется. Зафиксируйте базовые цифры в общей таблице, чтобы при следующем апгрейде железа не спорить снова только про ping.
| Регион | Типичный сценарий | Заметка команде |
|---|---|---|
| Сингапур | Сборки для SEA, зеркала GitHub APAC, команды SG/MY. | Выбор против Гонконга — где живёт основной репозиторий. |
| Япония | Комплаенс JP, коллеги у Токио, ночные релизы JP. | Удобно для смен «APAC dev + Japan QA». |
| Корея | Приложения для KR, локальные CDN, дежурный SSH из Сеула. | Решайте по data plane, не только по ping. |
| Гонконг | Смешанные команды Greater China / HK, Git на юге Китая. | Офисы на материке часто чувствуют SSH лучше, чем с западом США. |
| Восток США | Пути GitHub по умолчанию на восток, SaaS East Coast, кэш npm/Actions смещён на восток. | Оптимизируйте маршруты артефактов, не расстояние на карте. |
| Запад США | Коллаборация West Coast, зеркала на западе, ночные сборки US Pacific. | SSH из APAC может быть медленнее; pull зависимостей всё равно быстрее. |
3) M4 16 ГБ/256 ГБ против 24 ГБ/512 ГБ и M4 Pro: параллельные слоты runner и лимиты симулятора
На Apple Silicon один физический actions-runner — цель runs-on: self-hosted; сколько job можно наложить, зависит от concurrency runner и пиков RAM Xcode/Симулятора. M4 16 ГБ — одна тяжёлая сборка или два лёгких job; 24 ГБ — один Archive плюс один UI-тест на одном симуляторе; M4 Pro — матрицы из нескольких симуляторов или очень крупные monorepo.
| Конфигурация | Рекомендуемая параллельность (правила большого пальца) | Сигналы OOM / зависания |
|---|---|---|
| M4 16 ГБ / 256 ГБ | 1× полный xcodebuild или 2× lint/unit-only. |
Частый Yellow в memory_pressure; симулятор не стартует. |
| M4 24 ГБ / 512 ГБ | 1× Archive + 1× UI-тест или 2× средние сборки с разными корнями DerivedData. | Параллельные UI-тесты бьют по WindowServer; swap ухудшает хвост latency. |
| M4 Pro (старший tier) | Матрица симуляторов на разных ОС; две минорные версии Xcode. | Упираетесь в IOPS диска раньше CPU на огромных деревьях DerivedData. |
В workflow лучше runs-on: [self-hosted, macOS, compile] и runs-on: [self-hosted, macOS, ui-test], чем крутить concurrency на одной коробке.
Приложение runner GitHub даёт настройку concurrency на машину; значение 2 на хосте 16 ГБ — частый путь к OOM при одновременном запуске Simulator. Считайте concurrency планом ёмкости: начните с 1 для Archive, измерьте пик RSS на крупнейшей схеме, повышайте только когда memory_pressure неделю релиза остаётся Normal. M4 Pro нужен, если одновременно держите две минорные Xcode из‑за окон App Store — сначала бюджет диска, потом ядра.
4) Расширение 1 ТБ/2 ТБ и DerivedData: параллельные worktree, хранение и drain
Hosted job обычно стартуют с нуля — DerivedData не накапливается. Self-hosted выигрывает, когда ~/Library/Developer/Xcode/DerivedData живёт между PR. При параллельных job никогда не делите один каталог DerivedData — задайте на job DERIVED_DATA_PATH (или -derivedDataPath) и при необходимости Git worktree.
- На диске: DerivedData, кэш SwiftPM, деревья CocoaPods при зафиксированных версиях.
- В Actions cache: воспроизводимые zip toolchain, кэши lint, крупные скачиваемые зависимости.
- Алерты: <20% свободного места — LRU, обрезать 30% старейшего DerivedData; <10% — drain runner (новые job не принимать).
| Диск | Типичное CI-использование | Когда апгрейдить |
|---|---|---|
| 256–512 ГБ базово | Один Xcode + DerivedData одного репо; регулярно чистить Archives. | DerivedData одного репо >40 ГБ или нужны две версии Xcode. |
| 1 ТБ | 2–3 активных кэша веток + runtime симуляторов; два параллельных worktree. | Ночная полная матрица monorepo по схемам. |
| 2 ТБ | Несколько минорных Xcode, архивы символов, крупные бинарные кэши SPM. | Не хотите rm -rf DerivedData после каждого job. |
5) Параллельная ёмкость: labels на нескольких Mac, шарды и путь посуточно → помесячно
Когда одна машина упирается в память, добавьте второй удалённый Mac и шардируйте по label:
mac-ci-compile— толькоxcodebuild build; держите DerivedData тёплым.mac-ci-archive— подпись и загрузка; в workflowconcurrency, чтобы два job не дрались за keychain.mac-ci-ui— тесты на симуляторе на коробке 24 ГБ или Pro.
Цепочка: посуточно проверить workflow → понедельно закалить политику кэша → помесячно для стабильного IP и identity runner → добавить машины под шард. GitHub actions/cache по-прежнему делит воспроизводимые blob; DerivedData остаётся локально на хосте.
При шардировании выравнивайте matrix workflow с labels, а не вешайте несовместимые job на один runner. Пример: ночная матрица iOS 17 и 18 — на Pro с mac-ci-ui, per-PR compile — на 16 ГБ только под compile. Задокументируйте, на каком label какие секреты, чтобы PR из fork не зависали в ожидании подписи, доступной только на archive-машине.
На практике удобно завести в репозитории короткий RUNNERS.md: имя runner в GitHub, регион Nuvcloud, объём RAM/SSD, список labels и «запрещённые» job (например, тяжёлый UI на 16 ГБ). Когда команда растёт, новый инженер не будет гадать, почему workflow «висит в очереди» — в логе Actions сразу видно, что не хватает машины с нужным label, а не «сломался CI».
6) HowTo: регистрация self-hosted runner на удалённом Mac
Следуйте руководству GitHub: добавить self-hosted runner (токены в UI могут меняться по версии). На хосте Nuvcloud:
- SSH; установите Xcode CLT / нужный Xcode; примите лицензии.
- Отдельный Unix-пользователь или каталог
actions-runner— не подписывайте продакшен IPA личным Apple ID на этом аккаунте. - В Settings репозитория → Actions → Runners запустите
config.sh; labels вродеmacos,m4, код региона. - Установите как сервис (
svc.sh installчерезlaunchd), чтобы job переживали разрыв SSH. - В workflow задайте
DERIVED_DATA_PATH; на этапе подписиconcurrency: { group: codesign, cancel-in-progress: false }.
env:
DERIVED_DATA_PATH: ${{ github.workspace }}/DerivedData/${{ github.run_id }}
RUNNER_TOOL_CACHE: /Users/runner/actions-toolcache
xcodebuild \
-scheme "YourApp" \
-derivedDataPath "$DERIVED_DATA_PATH" \
build
7) Посуточная, понедельная и помесячная TCO — и когда менять конфигурацию
Разделяйте траты на «эксперимент» и «продакшен runner»:
| Период | Лучше для | Осторожно в CI |
|---|---|---|
| Посуточно | A/B шести регионов, доказать ускорение DerivedData, пробная регистрация runner. | Экспортируйте заметки по подписи и инвентарь кэша перед сносом; без прод-секретов на короткоживущих хостах. |
| Понедельно | Релизный аврал, миграция с hosted macOS, нагрузочный тест перед второй машиной. | Заморозьте patch Xcode; логируйте экономию минут против hosted. |
| Помесячно | Ежедневные сборки main, фиксированное имя runner, allow-list IP, стабильная политика кэша. | Планируйте апгрейды: 16→24 ГБ, диск, второй шард по label. |
Грубое сравнение на 36 месяцев (пример): свой Mac mini + электричество + труд ops = C_cap; облачная аренда = 36 × R. Команды без выделенных Mac-админов часто недооценивают C_cap. Сравнивая hosted-минуты, учитывайте задержку очереди как упущенную выгоду, не только ценник.
Для финансового согласования сохраните скриншот или CSV из GitHub Billing за последний квартал рядом с предложением по аренде: так проще объяснить, почему фиксированная R в месяц дешевле растущего M × P, даже если «мы и так редко собираем macOS». Отдельно зафиксируйте, кто в команде отвечает за обновление Xcode и очистку диска — это скрытая строка в TCO self-hosted.
Подберите SKU и срок на странице цен; продление и resize — в панели. Ещё заметки в индексе блога.
8) FAQ
В1: Разрешает ли GitHub self-hosting?
Да на своём или арендованном железе; не перепродавайте ёмкость runner посторонним (см. Terms GitHub).
В2: Можно смешивать hosted и self-hosted macOS?
Да — например PR на hosted, main на self-hosted. Ветвите workflow, когда секреты/подпись только на вашем Mac.
В3: Когда чистить DerivedData?
После апгрейда Xcode, крупного ответвления ветки или при <20% диска — LRU, не rm -rf при работающих job.
В4: Остановит ли разрыв SSH job?
Нет — job идут под сервисом runner. Используйте launchd; SSH для вас, не для worker.
В5: Что с кэшем при смене региона?
DerivedData привязан к пути; смена региона требует прогрева. Actions cache для SPM/toolchain, затем одна полная сборка локального DerivedData.
В6: Сколько симуляторов на 16 ГБ?
Избегайте нескольких тяжёлых UI-тестов на 16 ГБ — направляйте на runner mac-ci-ui.
В7: Зачем сериализовать подпись?
Параллельный keychain и дубли Archive могут заблокировать сертификаты или перезаписать IPA — concurrency на этапе подписи.
В8: Как безопасно вывести посуточный хост?
Удалите runner в GitHub, ротируйте registration token/PAT, очистите keychain и временные ключи в ~/.ssh, когда ничто больше не зависит от них.
На облачном Mac mini CI остаётся «тёплым», а счета — предсказуемыми
Собственные GitHub Actions macOS Runner — это постоянный DerivedData, предсказуемая помесячная аренда и выделенная ёмкость в нескольких регионах под вашим контролем. Bare-metal Mac mini M4 на Nuvcloud даёт нативный Unix, базовую линию Gatekeeper/SIP/FileVault и энергопрофиль для круглосуточных сборок — от посуточных тестов региона до помесячного парка Runner, с 24 ГБ ОЗУ, большим SSD или второй машиной для шардирования по labels, когда пайплайн растёт.
Если вы уходите с нестабильных минут хостинга macOS, облачный Mac mini M4 на Nuvcloud — удачная отправная точка — смотрите тарифы и регионы, чтобы узел, память и стратегия кэша были выбраны один раз, а не переделывались каждый релиз.