Use case · CI/CD and build runners

    Self-hosted macOS build runners for Xcode projects

    For development teams that need unattended, repeatable iOS and macOS builds. You register a dedicated Mac mini as a runner in your CI system, and every push produces a signed build or test result on hardware nobody else uses.

    Illustrative workflow
    1. Repository

      Push or pull request

      01
    2. Dedicated Mac runner

      Self-hosted agent

      02
    3. Build & test

      xcodebuild, simulators

      03
    4. Artifact

      .ipa, logs, reports

      04

    What this solves

    Queue time on hosted macOS runners

    Shared macOS runners can be slow to start and are billed per minute. A dedicated runner is always on and picks up jobs immediately.

    Cold caches on every job

    Ephemeral runners start empty. A persistent Mac keeps DerivedData, SwiftPM, CocoaPods and Homebrew caches between builds.

    Control over Xcode versions

    You decide when to install a new Xcode or macOS release, instead of following the image schedule of a CI vendor.

    Example workflow

    From pull request to TestFlight

    1. 1

      A developer opens a pull request on GitHub.

    2. 2

      The workflow targets the label self-hosted, macOS, ARM64 and lands on your vBoxx Mac.

    3. 3

      xcodebuild resolves packages from the warm local cache, builds and runs unit tests.

    4. 4

      On merge to main, fastlane signs the app with certificates from the runner keychain and uploads the build to App Store Connect.

    5. 5

      Logs and the .ipa are stored as artifacts in your CI system.

    What runs on the Mac, and what does not

    Keep the Mac runner for Apple-only steps. Everything else can stay on the Linux runners you already have.

    Xcode build, unit tests and UI testsRuns onMac runnerWhyxcodebuild and the iOS Simulator need macOS.
    Code signing, notarisation and upload to App Store ConnectRuns onMac runnerWhyUses the runner keychain and Apple tools such as notarytool or fastlane.
    Docker builds, container actions and service containersRuns onLinux runnerWhyDocker container actions do not run natively on a macOS runner.
    Linting, backend tests and web buildsRuns onEitherWhyRunning them on Linux keeps the Mac free for Apple jobs.

    How to set it up and run it

    1. 1

      Order a Mac and choose the macOS version in the configurator

      You get full admin access over SSH.

    2. 2

      Install Xcode, the command line tools and your toolchain (Homebrew, fastlane, Ruby or Node as needed).

    3. 3

      Create a dedicated, non-admin macOS user for the runner and install the GitHub Actions runner or GitLab Runner (shell executor) as a launch service so it starts after a reboot.

    4. 4

      Import signing certificates into a separate keychain for that user, or fetch them per job with fastlane match.

    5. 5

      Decide concurrency

      One runner process per Mac is the safest default for Xcode builds. Add a second runner only after you have measured CPU, memory and disk headroom.

    6. 6

      Plan maintenance

      Clean old DerivedData and simulators on a schedule, and test new Xcode releases on a branch before switching the default.

    Which configuration fits

    Pricing

    Good fit for

    A single runner for small to medium apps with one build at a time.

    Mac mini M6

    • 12-core CPU · 12-core GPU
    • Memory: 16 GB
    • Storage: 512 GB SSD

    Good fit for

    Larger projects, UI tests with several simulators, or two carefully measured concurrent jobs.

    Mac mini M6

    • 12-core CPU · 12-core GPU
    • Memory: 32 GB
    • Storage: 512 GB SSD

    Good fit for

    Big monorepos, many Xcode versions side by side and large build caches.

    Mac mini M5 Pro

    • 15-core CPU · 16-core GPU
    • Memory: 48 GB
    • Storage: 1 TB SSD

    Who does what

    vBoxx provides

    • A dedicated Mac mini M6 or M5 Pro used only by your runner, with the macOS version you choose
    • Persistent SSD storage, so build caches survive between jobs and reboots
    • Network: 10 Gigabit Ethernet port · 1 Gbit/s unmetered · public IPv4 + IPv6
    • Remote APC power control to hard-reboot a runner that hangs, included
    • Optional JetKVM console for when macOS no longer responds over SSH

    You manage

    • Installing and updating Xcode, macOS and the runner agent
    • Runner registration, labels, tokens and job concurrency
    • Signing certificates, provisioning profiles and secrets
    • Firewall rules, SSH keys and access for your team
    • Backups of anything that is not stored in Git or your CI system

    Before you choose this setup

    • Self-hosted runners on public repositories can execute code from forked pull requests. Use them for private repositories, or require approval for outside contributors.
    • One Mac is one runner pool. If you need many short parallel jobs with clean machines every time, a hosted ephemeral runner service may fit better.
    • There is no managed CI service or automatic Xcode updating included. The Mac is yours to configure.

    Frequently asked questions

    Yes, you can install both agents, but they then compete for the same CPU and memory. Most teams keep one agent per Mac so build times stay predictable.

    No. GitHub Docker container actions and service containers need a Linux runner. Run them on a Linux machine and keep the Xcode jobs on the Mac.

    Use a dedicated macOS user and keychain for the runner, restrict who can change workflows, and prefer fetching certificates per job with a tool such as fastlane match over storing them permanently.

    You can hard-reboot the Mac through the APC power control. With the optional JetKVM you also see the screen and can recover without SSH. Configure the runner as a launch service so it starts again automatically.

    Yes. You can upgrade macOS yourself, or reinstall a clean version with the optional JetKVM and virtual media. Check that your Xcode version supports it first.

    Not sure which Mac fits your workload?

    Configure a Mac mini M6 or M5 Pro yourself, or describe your workload and an engineer will suggest a configuration.