Self-hosted macOS runner for GitHub Actions and Xcode CI.

Hosted macOS runners bill by the minute at a premium, start every job from a cold image, and queue at the worst possible moment. A self-hosted runner on a dedicated Mac mini turns your iOS pipeline into a flat monthly cost with warm caches and no queue. This guide covers when that trade wins and how to set it up.

Updated September 26, 2026

When a self-hosted Mac runner pays off

GitHub and other CI providers charge several times more per minute for macOS runners than for Linux ones. A team shipping daily with a 15-25 minute pipeline can spend hundreds of dollars a month on Mac minutes alone, before retries.

A dedicated Mac mini is a flat monthly cost however many builds you run. It is also faster in practice: DerivedData, Swift package caches and simulator runtimes stay on disk between jobs instead of being rebuilt from a clean image every time.

What you need

  • A Mac with admin rights. An M4 with 16GB runs one iOS build job comfortably; 24GB handles two jobs or very large projects.
  • 512GB of storage if you can. Xcode plus a couple of simulator runtimes and caches quickly passes 100GB.
  • Admin access to the GitHub repository or organization, to register the runner.
  • Your Apple Developer signing certificates and an App Store Connect API key for uploads.

Install the GitHub Actions runner

In GitHub, open Settings → Actions → Runners → New self-hosted runner, choose macOS and ARM64, and keep the page open for the download link and registration token. Then on the Mac:

mkdir actions-runner && cd actions-runner
# download and extract the macOS ARM64 package from the GitHub page, then:
./config.sh --url https://github.com/YOUR-ORG/YOUR-REPO \
  --token YOUR-TOKEN --labels m4,xcode
./svc.sh install
./svc.sh start

svc.sh installs the runner as a launchd service. Turn on automatic login for the runner’s user account so the service starts again after a reboot.

In your workflow, target the machine with runs-on: [self-hosted, macOS, ARM64], or with your own labels such as m4. GitLab Runner, Buildkite and Jenkins agents follow the same pattern: install the agent, register it, run it under launchd.

Code signing and uploads

Keep CI signing separate from your personal keychain. Create a dedicated keychain for the runner, import your distribution certificate into it, and unlock it at the start of each job with a password stored in your CI secrets.

For TestFlight and App Store uploads, use an App Store Connect API key rather than a personal Apple Account password. fastlane and Xcode’s command-line tools both support API keys, so no one has to sign in interactively.

Keep builds fast

  • Leave DerivedData and the Swift Package Manager cache in place between runs. That warm cache is the biggest speed win over hosted runners.
  • Install exactly the Xcode versions you build with, and switch between them with xcode-select or the xcodes tool.
  • Clear out old simulators now and then with xcrun simctl delete unavailable.
  • Need more capacity for release week? Order another Mac from your pipeline with the Vantix API.

Security: keep it to private repositories

GitHub recommends only using self-hosted runners with private repositories. On a public repository, a pull request from a fork could run code on your machine. Keep the runner on private repos, give its account only the access it needs, and keep signing keys in the CI keychain.

Common questions

Can I run more than one runner on one Mac mini?

Yes. An M4 with 16GB comfortably runs one or two concurrent iOS build jobs. Beyond that, simulator start-ups begin to compete for memory, so add a second machine instead.

Is a self-hosted macOS runner cheaper than GitHub-hosted runners?

For teams that build every day, usually yes: a dedicated Mac is a flat monthly cost however many minutes you use. Check GitHub’s current pricing for hosted macOS minutes and any platform fees before you compare.

Do I get full admin on the machine?

Yes. It is a dedicated physical Mac with your own admin account, so you can install any Xcode version, toolchain or CI agent.

How do reboots and macOS updates work?

The machine never sleeps and restarts itself after power events. You decide when to install macOS updates, so there are no surprise restarts in the middle of a pipeline.

Skip the setup - rent the machine.

Dedicated M4 Mac hosting. Private VLAN, fixed IP, online 24/7. From $139/mo, billed 3 months at a time.

See pricing →