Ratgeber

Einen self-hosted CircleCI Runner auf einem Mac betreiben

CircleCI Machine Runner 3 wird unter macOS aus dem Homebrew-Tap von CircleCI installiert und läuft als LaunchAgent. Legen Sie einen Namespace und eine Resource Class an, kopieren Sie das Token, tragen Sie es in die config.yaml des Runners ein und starten Sie den Dienst. Jobs erreichen ihn mit machine: true und resource_class: namespace/name.

Was Sie vorher brauchen

  • Admin-Rechte für die Organisation in CircleCI. Ein Admin muss die Runner-Bedingungen unter Org und dann Runners akzeptieren, bevor das Menü erscheint.
  • Mindestens ein Credit auf dem Konto. Laut CircleCI verbrauchen Runner-Jobs keine Credits, Speicher und Datentransfer aber schon.
  • Einen Mac mit Apple Silicon, Admin-Zugriff, Homebrew und Xcode.
  • sha256sum, das CircleCI als Voraussetzung nennt. Sie bekommen es mit brew install coreutils.

1. Namespace und Resource Class anlegen

Öffnen Sie in der Web-App Runners und wählen Sie Create Resource Class. Jede Organisation bekommt einen Namespace. Wenn Sie Orbs veröffentlichen, haben Sie ihn schon. Nennen Sie die Resource Class etwa mac-mini-m6. Speichern Sie und kopieren Sie das Token. CircleCI zeigt es nur einmal an.

Die CLI macht dasselbe:

circleci namespace create <name> --org-id <your-organization-id>
circleci runner resource-class create <namespace>/<resource-class> <description> --generate-token

2. Den Runner mit Homebrew installieren

brew tap circleci-public/circleci
brew trust circleci-public/circleci
brew install circleci-runner

Die mittlere Zeile ist neu. Homebrew 7.0.7, die Version auf unserem Mac im Oktober 2026, lädt keine Pakete aus dem Tap eines Dritten, solange Sie ihm nicht vertrauen. Auf der Seite von CircleCI fehlt dieser Schritt noch. Der Runner kommt als Homebrew-Cask.

macOS meldet eventuell, dass ein Hintergrundobjekt von Circle Internet Services hinzugefügt wurde. Das ist normal. Homebrew schreibt außerdem die plist des LaunchAgent nach ~/Library/LaunchAgents/com.circleci.runner.plist.

3. Das Token in die config.yaml eintragen

nano $HOME/Library/Preferences/com.circleci.runner/config.yaml
runner:
  name: "mac-mini-m6"
  working_directory: "/Users/$USER/Library/com.circleci.runner/workdir"
  cleanup_working_directory: true
api:
  auth_token: "your-resource-class-token"

Mit cleanup_working_directory startet jeder Job mit einem sauberen Checkout. Die DerivedData von Xcode liegt standardmäßig in ~/Library/Developer/Xcode/DerivedData, die Build-Caches bleiben also erhalten. Übergeben Sie aber -derivedDataPath innerhalb des Arbeitsverzeichnisses, löscht die Bereinigung sie nach jedem Job.

Das Token schützen

Mit dem Token der Resource Class kann eine Maschine Jobs dieser Klasse übernehmen. Wer es liest, kann seine eigene Maschine anschließen und Ihre Jobs empfangen, samt Ihren Secrets. Beschränken Sie die Konfigurationsdatei auf Ihren Benutzer und tauschen Sie das Token aus, falls es je nach außen gelangt.

chmod 600 $HOME/Library/Preferences/com.circleci.runner/config.yaml
ls -l $HOME/Library/Preferences/com.circleci.runner/config.yaml

Für Jobs gilt dieselbe Logik. Sie laufen als der macOS-Benutzer, der den Runner gestartet hat, auf derselben Platte wie alles andere. Verweisen Sie nur vertrauenswürdige Projekte auf diese Resource Class.

4. Die Notarisierung akzeptieren

Das Binary kommt aus dem Internet, also muss macOS es freigeben. CircleCI beschreibt, zuerst die Signatur zu prüfen und dann das Quarantäne-Flag zu entfernen.

spctl -a -vvv -t install "$(brew --prefix)/bin/circleci-runner"
sudo xattr -r -d com.apple.quarantine "$(brew --prefix)/bin/circleci-runner"

Der erste Befehl sollte accepted melden, mit der Quelle Notarized Developer ID.

5. Den Runner in der GUI-Domain starten

Führen Sie diese Befehle im Terminal auf dem Desktop des Mac aus. Die GUI-Domain ist die angemeldete Desktop-Sitzung. Dort leben der Simulator und der Anmelde-Schlüsselbund.

launchctl bootstrap gui/$(id -u) $HOME/Library/LaunchAgents/com.circleci.runner.plist
launchctl enable gui/$(id -u)/com.circleci.runner
launchctl kickstart -k gui/$(id -u)/com.circleci.runner
launchctl print gui/$(id -u)/com.circleci.runner

CircleCI beschreibt auch eine Variante mit der User-Domain für Headless-Sitzungen. Dabei wandert die plist nach /Library/LaunchAgents. Unter macOS 27 haben wir gesehen, dass eine plist in diesem Ordner die automatische Anmeldung bei jedem Booten verhindert. Siehe automatische Anmeldung auf einem Headless-Mac. Für iOS-Arbeit empfehlen wir die GUI-Domain mit automatischer Anmeldung.

6. Neustarts überstehen

Eine plist in ~/Library/LaunchAgents wird geladen, wenn sich ihr Benutzer anmeldet. Schalten Sie für dieses Konto die automatische Anmeldung ein, in den Systemeinstellungen unter Benutzer:innen & Gruppen. Schalten Sie den Ruhezustand mit sudo pmset -a sleep 0 ab. Starten Sie einmal neu und prüfen Sie wieder mit launchctl print. Die Logs liegen in ~/Library/Logs/com.circleci.runner/runner.log.

7. Einen Job auf den Mac lenken

version: 2.1

jobs:
  ios-tests:
    machine: true
    resource_class: your-namespace/mac-mini-m6
    steps:
      - checkout
      - run:
          name: Run tests
          command: |
            rm -rf build/TestResults.xcresult
            xcodebuild test -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' -resultBundlePath build/TestResults.xcresult
      - run:
          name: Zip result bundle
          when: always
          command: ditto -c -k --keepParent build/TestResults.xcresult TestResults.xcresult.zip
      - store_artifacts:
          path: TestResults.xcresult.zip

workflows:
  ios:
    jobs:
      - ios-tests

Die Doku von CircleCI nennt zwei Felder, die ein Runner-Job haben muss: machine: true und die resource_class. Einen Schlüssel macos: xcode: gibt es hier nicht, weil Sie kein Image auswählen. Der Job nutzt das Xcode, das auf dem Mac ausgewählt ist. Auf einem MacRun-Mac ist das Xcode 26.6 mit der Simulator-Runtime für iOS 26.5.

Häufige Fehler und Lösungen

  • Refusing to load cask ... from untrusted tap. Führen Sie brew trust circleci-public/circleci aus und installieren Sie erneut.
  • macOS blockiert das Binary. Sie haben den Schritt zur Notarisierung übersprungen. Führen Sie den xattr-Befehl von oben aus.
  • Jobs stehen in der Warteschlange, starten aber nie. Prüfen Sie, ob die Resource Class in der config.yml zu der angelegten passt. Lesen Sie dann runner.log.
  • Docker Layer Caching funktioniert nicht. CircleCI führt es auf self-hosted Runnern als nicht unterstützt.
  • xcodebuild: error: Existing file at -resultBundlePath. Löschen Sie das alte Bundle vor dem Testschritt. Darauf sind wir mit Xcode 26.6 gestoßen.

Den Runner stoppen Sie mit launchctl bootout gui/$(id -u)/com.circleci.runner. Zum Entfernen führen Sie brew uninstall --cask circleci-public/homebrew-circleci/circleci-runner aus.

Warum ein dedizierter Mac hilft

Warme Caches sind der größte Gewinn. In unserem Benchmark haben wir die Wikipedia-iOS-App mit Xcode 26.6 gebaut. Ein typischer Job nach einer kleinen Änderung dauerte auf einem warmen M6 27 Sekunden. Auf einem frischen gehosteten macos-26-Runner von GitHub waren es 269 Sekunden. Ein sauberer Build dauerte 86 Sekunden statt 183.

Wann gehostetes macOS von CircleCI reicht

CircleCI betreibt eigene Mac-Executors. Laut der Doku, gelesen im Oktober 2026, gibt es m4pro.medium mit 6 vCPUs und 28 GB und m4pro.large mit 12 vCPUs und 56 GB. Beide haben mehr Arbeitsspeicher als unser M6 mit 16 GB. Braucht Ihre Suite so viel Speicher oder bauen Sie nur ein paar Mal pro Woche, bleiben Sie beim gehosteten Angebot. Lassen Sie MacRun auch weg, wenn Sie ein SLA, eine statische IP oder mehrere Regionen brauchen.

Unter andere CI-Systeme finden Sie die Einrichtung auf Seiten von MacRun. Oder vergleichen Sie die Kosten mit Ihren eigenen Minuten.

Häufige Fragen

Ist der self-hosted Runner von CircleCI kostenlos?

+

Laut CircleCI verbraucht die Ausführung auf Runnern keine Credits. Sie brauchen trotzdem mindestens ein Credit auf dem Konto, weil Speicher und Datentransfer weiterhin berechnet werden können.

Wo liegt die Konfiguration des CircleCI Runners unter macOS?

+

In $HOME/Library/Preferences/com.circleci.runner/config.yaml. Die Logs landen in $HOME/Library/Logs/com.circleci.runner/runner.log.

Sollte ich die GUI-Domain oder die User-Domain nutzen?

+

Für iOS-Builds die GUI-Domain mit automatischer Anmeldung. Sie läuft in der Desktop-Sitzung, die der Simulator und der Anmelde-Schlüsselbund brauchen.

Funktioniert Docker Layer Caching auf einem self-hosted CircleCI Runner?

+

Nein. CircleCI führt Docker Layer Caching auf self-hosted Runnern als nicht unterstützt.

Passende Ratgeber