Guide
Self-hosted GitHub Actions runner on a Mac mini
Set up a self-hosted GitHub Actions runner on a dedicated Mac mini. Install Xcode, register the runner, run it as a service and keep builds fast and private.
30 minutes, updated 2026-09-15
GitHub's hosted macOS runners are shared machines. They queue at busy hours, start cold every time and bill by the minute.
A self-hosted runner on your own Mac mini starts at once, keeps its caches between builds and costs the same every month.
This guide takes about thirty minutes. You need:
- A Mac mini with Apple silicon and SSH access
- Admin rights on the GitHub repository or organisation
- An Apple ID, to download Xcode
1. Prepare the Mac
Log in over SSH and stop the Mac from sleeping:
sudo pmset -a sleep 0 disksleep 0 displaysleep 0Install Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"We recommend a separate user for the runner, so builds never run as your admin account:
sudo sysadminctl -addUser runner -fullName "CI Runner" -password -Log in as that user for the steps below.
2. Install Xcode
The simplest way over SSH is `xcodes`:
brew install xcodesorg/made/xcodes
xcodes install --latest
xcodes selectAccept the licence and finish the first launch:
sudo xcodebuild -license accept
xcodebuild -runFirstLaunch
xcodebuild -downloadPlatform iOS3. Register the runner
In GitHub, open your repository, then Settings, Actions, Runners, New self-hosted runner. Choose macOS and ARM64.
GitHub shows the exact commands, with the current version and a token. They look like this:
mkdir actions-runner && cd actions-runner
curl -o actions-runner-osx-arm64.tar.gz -L <download URL from GitHub>
tar xzf ./actions-runner-osx-arm64.tar.gz
./config.sh --url https://github.com/<owner>/<repo> --token <token>The token expires after an hour, so register right away. When `config.sh` asks for labels, add ones you will use in workflows, such as `xcode` or `m4`.
4. Run it as a service
./svc.sh install
./svc.sh start
./svc.sh statusThe runner now starts with the user session. If your jobs run UI tests or need the login keychain, turn on automatic login for the runner user in System Settings, Users and Groups. You can do this through screen sharing. Automatic login is not available while FileVault is on.
5. Use it in a workflow
name: iOS build
on: [push]
jobs:
build:
runs-on: [self-hosted, macOS, ARM64]
steps:
- uses: actions/checkout@v4
- name: Build
run: xcodebuild -scheme MyApp -destination 'generic/platform=iOS Simulator' buildPush a commit. The job appears under Actions and starts on your Mac within seconds.
6. Keep it healthy
- Private repositories only. On a public repository, a pull request from a fork can run code on your Mac. GitHub advises against self-hosted runners on public repos.
- Clean up now and then. DerivedData and old simulators grow over time:
rm -rf ~/Library/Developer/Xcode/DerivedData
xcrun simctl delete unavailable- Signing. Keep certificates in a dedicated keychain, or use fastlane match.
- Updates. The runner updates itself by default. Update Xcode on your own schedule, not in the middle of a release.
Why a dedicated Mac mini
- Nobody else on it. Builds start the moment you push.
- Warm caches. DerivedData, Swift packages and CocoaPods stay on disk, so incremental builds are much faster.
- Real chips. Test on the same Apple silicon your users have.
- One flat month. No per-minute billing, no surprise at the end of a busy sprint.
MacDuty racks Mac minis from M1 to M6 in the EU, with macOS installed and your SSH key already in place.
Next