macOS GitLab Runner Deployment ist für iOS- und macOS-Projekte dann sinnvoll, wenn Ihre Pipeline Xcode, Apple SDKs, Simulatoren oder Code-Signierung benötigt. Planen Sie den Knoten als echten Build-Server: eigener normaler Benutzer, Shell Executor, dokumentierter Benutzer-Login, geschützte Signierdaten und eine Abnahme mit einem realen Projekt. „Online“ im GitLab-Menü ist nur ein Verbindungscheck, kein Produktionsnachweis.
Diese Anleitung richtet sich an Sie, wenn Sie manuelle iOS-Builds in GitLab CI überführen, eine plattformübergreifende DevOps-Umgebung betreuen oder einen dauerhaft erreichbaren Remote Mac für Xcode-Aufgaben benötigen. Entscheidend sind nicht einzelne Installationsbefehle, sondern die Zustände nach Neustart, Netzwerkabbruch, Schlüsselbundzugriff und fehlgeschlagenem Build.
01Der richtige Einsatzbereich vor der Installation
Ein macOS Runner gehört nicht automatisch in jede Pipeline. Für reine Backend-, Frontend- oder Linux-Builds ist ein macOS-Host meist unnötig. Der Aufwand ist gerechtfertigt, wenn mindestens eine dieser Bedingungen erfüllt ist:
- Ihr Projekt verwendet Xcode oder
xcodebuild. - Sie benötigen Apple SDKs oder einen iOS-Simulator.
- Der Build erzeugt ein signiertes Archiv.
- Ein Release-Schritt muss auf einem realen macOS-System laufen.
- Ihr lokaler Mac ist nicht dauerhaft verfügbar oder nicht ausreichend isoliert.
GitLab dokumentiert für macOS einen Ablauf aus Shell-Konfiguration, Werkzeuginstallation, Xcode-Einrichtung, Runner-Registrierung und CI-Konfiguration. Für iOS- und macOS-Builds läuft der Shell Executor direkt auf dem Host. Dadurch erhalten die Jobs den Benutzerkontext des Runner-Kontos. Genau das macht den Zugriff auf Xcode und den Simulator einfach, erhöht aber gleichzeitig das Risiko für Host und Netzwerk. Die offizielle GitLab-Anleitung für macOS Runner beschreibt diese Voraussetzungen und den vorgesehenen Ablauf.
Drei Grenzen, die Sie vorab entscheiden müssen
Erstens: Vertrauensgrenze. Ein Shell Runner ist keine harte Sandbox. Ein Job kann Dateien des Runner-Benutzers lesen, Prozesse starten und Konfigurationsdateien verändern. GitLab bewertet die Sicherheitsrisiken des Shell Executors ausdrücklich als hoch und empfiehlt ihn nur für vertrauenswürdige Builds. Die GitLab-Sicherheitsdokumentation für selbstverwaltete Runner ist deshalb Teil Ihrer Architekturentscheidung, nicht nur eine optionale Lektüre.
Zweitens: Benutzerkontext. Xcode, Simulator, Schlüsselbund und grafische macOS-Komponenten hängen am angemeldeten Benutzer. Ein Dienst, der unter einem anderen Konto oder ohne Benutzeroberfläche startet, kann in der Weboberfläche erreichbar sein und trotzdem beim Signieren oder beim Simulator-Test scheitern.
Drittens: Zustandsverschmutzung. Arbeitsverzeichnisse, Derived Data, Paket-Caches und temporäre Archive bleiben auf dem Host liegen, wenn die Pipeline sie nicht bereinigt. Das kann den verfügbaren Speicher verringern, alte Zugangsdaten zurücklassen oder den nächsten Build durch lokale Altlasten beeinflussen.
02Achtung: Wenn externe Beiträge, Forks oder frei veränderbare
.gitlab-ci.yml-Dateien auf denselben Shell Runner gelangen können wie Release-Jobs, behandeln Sie den Runner als kompromittierbar. Trennen Sie Build- und Signierknoten oder beschränken Sie den Runner auf geschützte Branches und Tags.
Erste Stunde: Benutzer, Architektur und Runner-Registrierung
Schritt 1: Einen eigenen CI-Benutzer anlegen
Verwenden Sie nicht Ihr persönliches macOS-Konto. Der CI-Benutzer benötigt Zugriff auf Xcode, Git, die Projektabhängigkeiten und gegebenenfalls einen dedizierten Schlüsselbund. Er sollte jedoch kein unbeschränktes Administratorkonto sein.
Dokumentieren Sie vor der Installation:
- Benutzername des CI-Kontos.
- Prozessorarchitektur des Macs.
- macOS-Version und aktive Entwicklerumgebung.
- Speicherort von
Xcode.app. - Projekt- und Gruppenbereich des Runners.
- Vertrauensmodell für Branches, Tags und Merge Requests.
GitLab unterstützt die Registrierung eines Runners mit einem Authentifizierungstoken. Bei der Registrierung wird die Konfiguration in config.toml gespeichert. Verwenden Sie keine echten Tokens in Dokumentation, Tickets oder Beispielcode. Die aktuelle GitLab-Dokumentation zur Runner-Registrierung zeigt den vorgesehenen interaktiven und nicht interaktiven Ablauf.
Ein typischer manueller Start sieht sinngemäß so aus:
gitlab-runner register
Wählen Sie für einen Xcode-Host den Executor shell. Vergeben Sie ein eindeutiges Tag, etwa macos-xcode, und weisen Sie dieses Tag ausschließlich Jobs zu, die den macOS-Knoten benötigen. Die genaue Token- und URL-Eingabe sollte aus Ihrer GitLab-Oberfläche stammen, nicht aus einem alten Blogbeitrag.
Schritt 2: Shell und Werkzeuge kontrollieren
Die GitLab-Dokumentation weist darauf hin, dass macOS standardmäßig Zsh verwendet, während viele Shell-CI-Skripte Bash-Syntax erwarten. Prüfen Sie daher zuerst:
echo "$SHELL"
Wenn Ihr Projekt Bash voraussetzt, legen Sie den Shell-Kontext bewusst fest. Ändern Sie ihn nicht blind auf einem gemeinsam genutzten Entwicklungsrechner. Installieren Sie anschließend nur die Werkzeuge, die Ihr Projekt wirklich benötigt: Git, Homebrew-Pakete, Ruby, CocoaPods, Swift Package Manager oder weitere Abhängigkeiten.
Schritt 3: Xcode vor dem ersten Pipeline-Lauf vorbereiten
Installieren Sie Xcode über einen von Apple vorgesehenen Bezugskanal. Öffnen Sie Xcode einmal unter dem CI-Benutzer oder führen Sie die erforderliche Erstkonfiguration aus:
sudo xcodebuild -runFirstLaunch
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcodebuild -version
xcode-select -p
Die ersten beiden Befehle und die Prüfung des aktiven Entwicklerverzeichnisses entsprechen dem von GitLab beschriebenen macOS-Setup. Die GitLab-Anleitung zu Xcode und macOS Runnern sollte dabei gegen die zum Installationszeitpunkt gültige Dokumentation geprüft werden, weil Apple Werkzeuge, Systemanforderungen und Xcode-Versionen aktualisiert.
03macOS-Dienste: Warum der Neustart der kritische Test ist
Bei Linux denken viele Administratoren an einen Systemdienst, der bereits beim Booten verfügbar ist. Der dokumentierte GitLab-Runner-Betrieb auf macOS funktioniert anders: Der Runner wird als LaunchAgent im Benutzerkontext installiert. GitLab beschreibt, dass dieser Modus für UI-Interaktionen wie Simulator-Tests geeignet ist, während ein LaunchDaemon nicht als unterstützter Standardweg gilt. Die offizielle Installationsanleitung für GitLab Runner auf macOS nennt außerdem die Datei ~/Library/LaunchAgents/gitlab-runner.plist als Prüfpunkt.
Installieren und starten Sie den Dienst als der Benutzer, unter dem die Jobs später laufen:
su - <ci-benutzer>
cd ~
gitlab-runner install
gitlab-runner start
gitlab-runner status
Prüfen Sie danach:
ls -l ~/Library/LaunchAgents/gitlab-runner.plist
ls -l ~/.gitlab-runner/config.toml
Führen Sie die Tests in dieser Reihenfolge aus:
- Runner registrieren und einen kleinen Shell-Test starten.
- SSH-Verbindung beenden.
- Nach kurzer Netzwerkunterbrechung erneut einen Job starten.
- Den Mac vollständig neu starten.
- Prüfen, ob der CI-Benutzer angemeldet ist.
- Einen Job mit Xcode-Zugriff ausführen.
- Einen absichtlich fehlschlagenden Job bereinigen und erneut starten.
Eine automatische Anmeldung kann die technische Verfügbarkeit verbessern, senkt aber den physischen Schutz des Geräts. Entscheiden Sie daher nach Standort, Zugriffsschutz, Gerätekontrolle und dem benötigten Simulator- oder UI-Verhalten. Schreiben Sie eine solche Einstellung nicht als allgemeine Sicherheitsmaßnahme in Ihre Betriebsanleitung.
04Erfahrung aus der Fehlersuche: Ein Runner, der nach einem Neustart offline bleibt, ist häufig nicht „kaputt“. Oft fehlt die Benutzeranmeldung, der LaunchAgent wurde unter dem falschen Konto installiert oder der Dienst sieht eine andere
config.tomlals der interaktive Terminalprozess.
Die erste Pipeline: erst Build, dann Test, dann Archiv
Starten Sie mit einer möglichst kleinen Pipeline. Sie soll Fehlerquellen voneinander trennen. Ein sinnvoller Ablauf ist:
- Repository abrufen.
- Abhängigkeiten auflösen.
- Nicht signiert bauen.
- Tests ausführen.
- Archiv erzeugen.
- Nur für geschützte Veröffentlichungsjobs signieren und exportieren.
Ein minimales Beispiel:
stages:
- build
- test
- archive
variables:
LANG: "en_US.UTF-8"
LC_ALL: "en_US.UTF-8"
before_script:
- xcode-select -p
- xcodebuild -version
- git --version
build_ios:
stage: build
script:
- xcodebuild -workspace App.xcworkspace -scheme App -sdk iphoneos -configuration Release CODE_SIGNING_ALLOWED=NO build
tags:
- macos-xcode
test_ios:
stage: test
script:
- xcodebuild test -workspace App.xcworkspace -scheme App -destination 'platform=iOS Simulator,name=<SIMULATOR_NAME>'
tags:
- macos-xcode
archive_ios:
stage: archive
script:
- xcodebuild archive -workspace App.xcworkspace -scheme App -archivePath build/App.xcarchive
artifacts:
when: always
paths:
- build/
expire_in: 7 days
tags:
- macos-xcode
Ersetzen Sie Platzhalter durch Werte aus Ihrem Projekt. Verwenden Sie keinen konkreten Simulatornamen, ohne ihn auf dem Zielhost zu prüfen. Die Xcode-Buildsystem-Dokumentation erklärt, wie Build-Einstellungen, Targets und Kommandozeilenaktionen zusammenspielen. Apple beschreibt das Xcode-Buildsystem als zentrale Stelle für Kompilierung, Linken und Produkterzeugung.
Für die erste Abnahme benötigen Sie mehr als einen grünen Job:
- vollständiges Job-Protokoll,
- Exit-Code,
- erzeugtes Artefakt,
- verwendete Xcode-Version,
- aktive Entwicklerumgebung,
- Testziel,
- nachvollziehbaren Commit.
Apple sieht für automatisierte Archivierung und Exportierung die Aktionen archive und exportArchive von xcodebuild vor. Die Apple-Dokumentation zur Distribution mit Xcode beschreibt diesen grundsätzlichen Ablauf für signierte Produkte.
Signierung und Schlüsselbund getrennt behandeln
Nicht jeder CI-Job benötigt Zertifikate. Ein Pull-Request-Build kann oft ohne Signierung kompilieren und Tests ausführen. Ein Release-Job benötigt dagegen möglicherweise Zertifikate, Provisioning-Profile, einen Schlüsselbund und Zugangsdaten für Veröffentlichungsdienste.
Trennen Sie deshalb mindestens diese beiden Pfade:
- Vertrauenswürdiger Build: kein Signiermaterial, breiter nutzbar.
- Release-Build: geschützter Runner, geschützte Variablen, geschützter Branch oder Tag.
Verwenden Sie einen dedizierten Schlüsselbund für CI und öffnen Sie ihn nur für die Dauer des signierten Jobs. Importierte Zertifikate müssen mit einem Schutzmechanismus versehen werden, der nicht sämtliche lokalen Prozesse dauerhaft freischaltet. Der CI-Benutzer sollte keine Entwicklerdaten anderer Konten lesen können.
Apple unterscheidet Entwicklungs- und Distributionszertifikate. Zertifikate werden im Schlüsselbund des Macs verwendet; die benötigten Rollen und Typen hängen vom Veröffentlichungsweg ab. Die Apple-Übersicht zu Zertifikaten beschreibt diese Unterschiede und die Zuständigkeiten für die Erstellung.
Wichtige Regeln für GitLab CI:
- Zertifikate und Profile niemals committen.
- Geheimnisse nur als geschützte und maskierte Variablen speichern.
- Release-Jobs nicht für Merge Requests aus externen Forks freigeben.
- CI-Skripte auf geschützten Branches gegen unbefugte Änderungen absichern.
- Nach jedem signierten Job temporäre Dateien und Exporte entfernen.
- Zertifikate und App-Store-Zugangsdaten regelmäßig rotieren.
- Fehlerhafte Jobs auf ihren Zugriff auf den Schlüsselbund prüfen.
Für die Erstellung eines Certificate Signing Request beschreibt Apple die Arbeit mit dem macOS-Schlüsselbund und dem Certificate Assistant. Die offizielle Apple-Anleitung für CSRs ist der richtige Bezugspunkt; kopieren Sie keine Zertifikats- oder Schlüsseldateien aus fremden Anleitungen.
06Tabellen für die Abnahmeentscheidung
Die folgende Tabelle trennt die wichtigsten Betriebsmodelle. Sie ersetzt keine Sicherheitsprüfung, hilft aber bei der Auswahl des Runner-Scopes.
| Option | Geeignet für | Hauptvorteil | Kritischer Nachteil | Entscheidung |
|---|---|---|---|---|
| Projekt-Runner auf eigenem Mac | Ein iOS-Projekt mit kontrolliertem Team | Klare Zuständigkeit und einfache Tags | Weniger flexibel für mehrere Projekte | Gute Standardwahl für den ersten produktiven Knoten |
| Gruppen-Runner auf dediziertem Mac | Mehrere vertrauenswürdige Projekte | Gemeinsame Wartung und bessere Auslastung | Höheres Risiko durch gemeinsam genutzten Host | Nur mit gleicher Vertrauensstufe |
| Geteilter Runner | Unkritische, allgemeine Aufgaben | Geringer Verwaltungsaufwand | Ungeeignet für private Signierschlüssel | Nicht für Release-Signierung verwenden |
| Getrennter Release-Runner | Archivierung, Export und Veröffentlichung | Beste Kontrolle über Geheimnisse | Zusätzliche Wartung und mögliche Wartezeit | Bei regelmäßigen Releases empfehlenswert |
Auch die Hostentscheidung muss an der Aufgabe hängen. Ein eigener lokaler Mac bietet direkte Kontrolle, ist aber bei Urlaub, Stromausfall oder Teamwechsel nicht automatisch dauerhaft erreichbar. Ein Remote Mac kann als kontinuierlicher Knoten laufen und lässt sich für ein definiertes Projekt zeitweise mieten. Prüfen Sie dafür die verfügbaren Mac-Mietmodelle von VpsMesh anhand von Laufzeit, Zugriff und Konfigurationsfreiheit statt nur nach dem Monatsbetrag.
| Prüfkriterium | Mindestnachweis vor Produktion | Wenn der Nachweis fehlt |
|---|---|---|
| Runner-Verbindung | Job startet mit korrektem Tag | Registrierung erneut prüfen |
| Benutzerkontext | Job sieht erwarteten Pfad und Schlüsselbund | Dienst unter falschem Konto korrigieren |
| Xcode | Version und xcode-select stimmen |
Entwicklerverzeichnis reparieren |
| Build | Reales Projekt erzeugt Artefakt | Pipeline verkleinern und Fehler isolieren |
| Neustart | Runner nimmt Job nach Reboot wieder an | LaunchAgent und Anmeldung prüfen |
| Signierung | Nur geschützter Job kann Zertifikat verwenden | Release-Runner sperren |
| Bereinigung | Arbeitsordner und Exporte werden entfernt | Cleanup-Schritt ergänzen |
| Rückfall | Manuelle Veröffentlichung bleibt möglich | Betrieb noch nicht freigeben |
Die erste Betriebswoche entscheidet über die Zukunft
Nutzen Sie für die Abnahme kein leeres Beispielprojekt. Verwenden Sie echte, aber kontrollierte Aufgaben aus Ihrem Team. Beobachten Sie:
- Warteschlangen vor dem macOS Runner,
- Erfolgsquote von Build und Test,
- Dauer von Abhängigkeiten und Archivierung,
- Speicherwachstum durch Derived Data und Artefakte,
- Verhalten nach Neustarts,
- Konflikte bei parallelen Jobs,
- Zugriff auf Simulator und Schlüsselbund,
- Wiederholbarkeit desselben Commits.
Definieren Sie anschließend drei mögliche Entscheidungen:
Weiterbetreiben: Der Runner besteht reale Builds, startet nach einem Neustart selbstständig und hält Signierdaten getrennt.
Optimieren: Der Build funktioniert, aber Cache, Bereinigung, Tagging oder Parallelitätsgrenzen sind noch unklar.
Zurückrollen: Der Runner bleibt nach Neustart offline, kann fremde Jobs ausführen oder verliert die Signierumgebung. In diesem Fall bleiben manuelle Builds oder ein klar abgegrenzter temporärer Knoten die bessere Wahl.
Für mehrere Projekte sollten Sie nicht sofort parallele Jobs freigeben. Ein Shell Runner teilt sich denselben Hostzustand. Beginnen Sie mit einer Job-Queue und erhöhen Sie die Parallelität erst, wenn Arbeitsverzeichnisse, Simulatoren, Schlüsselbund und Ressourcen sauber getrennt sind.
08Wann ein Remote Mac die bessere Infrastruktur ist
Wenn Sie derzeit auf einem privaten Mac arbeiten, entstehen meist vier Nachteile: Der Rechner ist nicht garantiert rund um die Uhr erreichbar, persönliche Schlüssel und CI-Geheimnisse liegen im selben Benutzerkontext, Neustarts werden vom Entwickler abhängig und die Kapazität lässt sich bei mehr Releases nur schwer standardisieren.
Ein eigener Mac mini kann langfristig sinnvoll sein, wenn Sie dauerhaft hohe Last, physische Geräte, lokale Peripherie oder vollständige Hardwarekontrolle benötigen. Für ein Team mit wechselnden Projekten, zeitlich begrenzten Release-Zyklen oder fehlender Mac-Hardware ist ein gemieteter Remote Mac oft der risikoärmere nächste Schritt. Sie können zunächst die Mac-Optionen von VpsMesh prüfen und dabei ausdrücklich nach einem eigenständigen Benutzer, Root-Zugriff, Xcode-Konfiguration und Neustartverhalten fragen.
Der entscheidende Vergleich lautet nicht „Cloud oder eigener Rechner“, sondern: Können Sie den Knoten reproduzierbar betreiben? Wenn Sie die vier Nachweise — echter Build, Neustart-Wiederherstellung, geschützte Signierung und bereinigter Fehlschlag — nicht liefern können, ist der Host unabhängig vom Preis noch kein produktiver CI-Knoten.
09Häufige Fragen
Wie bleibt ein GitLab Runner auf einem Remote Mac dauerhaft aktiv?
Installieren Sie den Runner unter einem eigenen normalen macOS-Benutzer und verwenden Sie den von GitLab dokumentierten LaunchAgent-Service. Dieser Ansatz benötigt eine aktive Benutzeranmeldung und ist deshalb nicht mit einem Linux-Daemon gleichzusetzen. Prüfen Sie zusätzlich den Zustand nach SSH-Abbruch, Netzunterbrechung und vollständigem Neustart. Ein grüner Status allein beweist keine dauerhafte Einsatzfähigkeit.
Warum ist ein macOS GitLab Runner nach dem Neustart offline?
Typische Ursachen sind eine nicht wiederhergestellte Benutzeranmeldung, ein nicht geladener LaunchAgent, ein falscher Benutzerkontext oder ein beschädigtes Netzwerk. Der offiziell dokumentierte macOS-Service läuft im Benutzerkontext. Prüfen Sie daher zuerst die LaunchAgent-Datei, den angemeldeten Benutzer, die Runner-Konfiguration und den Dienststatus, bevor Sie unbelegte LaunchDaemon-Skripte einsetzen.
Wie ruft GitLab CI Xcode für einen iOS-Build auf?
Der Job läuft beim Shell Executor direkt auf dem Mac und kann deshalb Xcode-Befehle wie xcodebuild verwenden. Setzen Sie vor dem Build das korrekte Entwicklerverzeichnis, starten Sie die Xcode-Erstkonfiguration und testen Sie zunächst einen nicht signierten Build. Danach folgen Tests, Archivierung und erst zuletzt der signierte Export. Die Tags des Jobs müssen mit dem macOS Runner übereinstimmen.
Wie schützen Sie Zertifikate und Schlüsselbund auf einem Remote Mac Runner?
Verwenden Sie einen eigenen CI-Benutzer, einen separaten Schlüsselbund und geschützte GitLab-Variablen. Signierjobs dürfen nur auf geschützten Branches oder Tags laufen. Zertifikate, Profile und App-Store-Zugangsdaten gehören nicht in das Repository. Ein Runner mit Shell Executor darf keine nicht vertrauenswürdigen Forks oder frei veränderbare CI-Skripte ausführen.
Was muss ein macOS Runner vor dem produktiven Einsatz erfüllen?
Führen Sie einen echten Projekt-Build mit Test, Artefakt, Protokoll und Exit-Code aus. Prüfen Sie danach Neustart-Wiederherstellung, Bereinigung des Arbeitsverzeichnisses, parallele Job-Regeln, Zugriff auf Xcode und den Schutz der Signierdaten. Wenn nur die Runner-Oberfläche „online“ anzeigt, aber kein reproduzierbarer Build gelingt, ist der Knoten noch nicht abgenommen.
Wenn Sie diese Abnahmebedingungen erfüllen wollen, benötigen Sie zuerst eine dauerhaft erreichbare, echte Mac-Umgebung mit eigenem Benutzer und vollständiger Xcode-Konfiguration. Ein lokaler Mac bleibt für dauerhafte Hochlast, physische Testgeräte und maximale Hardwarekontrolle sinnvoll. Fehlen Ihnen jedoch die Hardware oder die Zeit für Wartung, verursacht ein eigener Rechner schnell Leerlauf, manuelle Neustarts und eine Vermischung privater sowie geschäftlicher Schlüssel. Ein Remote Mac von VpsMesh kann dann die flexiblere Lösung sein: Sie testen den GitLab-Runner-Betrieb für den tatsächlichen Release-Zyklus, statt sofort Hardware zu kaufen, die außerhalb der Build-Zeiten ungenutzt bleibt.