Symptom: Der Mac ist per SSH erreichbar, aber GitLab zeigt den Runner weiterhin als offline an.
Schnellste Lösung: Prüfen Sie zuerst Host, grafische Benutzersitzung, macOS LaunchAgent, Runner-Prozess, Registrierung und Netzwerk in dieser Reihenfolge. Installieren Sie den GitLab Runner erst neu, wenn die Beweislage auf beschädigte Dienstdateien oder eine fehlerhafte Installation zeigt.

Dieser Leitfaden ist für Sie gedacht, wenn Sie einen einzelnen Remote Mac als CI-Knoten betreiben, mehrere Projekte über GitLab Runner versorgen oder signierte Xcode- und Simulator-Aufgaben nach einem Neustart zuverlässig wieder aufnehmen müssen. Er hilft auch Plattformteams, die eine belastbare Abnahme für Mac-CI-Knoten definieren wollen.

Beginnen Sie mit der richtigen Fehlergrenze

Ein „offline“-Status beschreibt nicht automatisch denselben Fehler. In der Praxis müssen Sie mindestens vier Zustände auseinanderhalten:

  • Der Mac selbst ist nicht erreichbar.
  • Der Benutzer ist nicht in einer geeigneten grafischen Sitzung angemeldet.
  • Der macOS LaunchAgent wurde nicht geladen oder der Runner-Prozess ist beendet.
  • Der Runner ist online, kann aber wegen Netzwerk-, Registrierungs- oder Tag-Problemen keine Aufgabe übernehmen.

Daneben gibt es einen fünften, häufig übersehenen Zustand: Der Runner ist in GitLab online, aber ein Auftrag bleibt in der Warteschlange, weil seine Tags nicht zu diesem Runner passen. Die offizielle Dokumentation beschreibt die Tag-Zuordnung als Voraussetzung dafür, dass ein Runner einen Auftrag auswählen darf. Prüfen Sie deshalb die GitLab-Regeln für Runner-Tags, bevor Sie den Dienst neu starten.

Ein typischer Fehlschlag als Diagnoseeinstieg

Angenommen, Sie erreichen den Mac wieder per SSH. hostname und whoami liefern erwartete Werte, doch die GitLab-Oberfläche meldet den Runner als offline. Ein Neustart des Prozesses über SSH bringt keine Verbesserung.

Das ist kein ausreichender Beleg für eine defekte Installation. Die SSH-Verbindung beweist nur, dass der Host und der SSH-Dienst funktionieren. Sie sagt nichts darüber aus, ob die richtige grafische Benutzersitzung gebootstrapped wurde, ob der LaunchAgent in dieser Sitzung geladen ist oder ob der Runner sein GitLab-Backend erreicht.

Arbeiten Sie daher von außen nach innen:

Prüfebene Nachweis Wenn der Nachweis fehlschlägt
Host SSH, VNC oder Webkonsole erreichbar Stromversorgung, Netzwerk und Remote-Zugang prüfen
Benutzersitzung Erwarteter Benutzer ist grafisch angemeldet Sitzung über VNC oder Webkonsole wiederherstellen
LaunchAgent Dienststatus und Prozess sind vorhanden LaunchAgent-Domain und plist prüfen
Runner-Verbindung Logs zeigen erfolgreiche Verbindung Proxy, Zertifikat und Registrierung untersuchen
Auftrag Tags und Executor passen Projekt-Tags und Runner-Zuweisung korrigieren

Halten Sie an jeder Ebene an, sobald der Fehler eindeutig gefunden ist. Wenn der Host nicht erreichbar ist, bringt eine Untersuchung der Runner-Registrierung keinen Erkenntnisgewinn. Wenn der Runner-Prozess läuft, sollten Sie nicht vorschnell den Dienst neu installieren.

Erklären Sie den Neustartfehler über die Benutzersitzung

Auf macOS wird GitLab Runner laut GitLab-Installationsdokumentation für macOS als Benutzer-Dienst über einen LaunchAgent betrieben. Das ist eine andere Betriebsform als ein systemweiter LaunchDaemon. Der Agent gehört zur angemeldeten Benutzerumgebung. Wird diese Umgebung nach einem Neustart nicht korrekt hergestellt, kann der Mac per SSH funktionieren, während der Runner offline bleibt.

Das erklärt auch, warum ein manuell gestarteter Prozess manchmal nur scheinbar hilft. Er kann in einer ungeeigneten Sitzung laufen, beim Abmelden beendet werden oder nicht auf die Keychain und Simulator-Dienste zugreifen, die Ihre eigentliche Pipeline benötigt.

Wann eine grafische Anmeldung erforderlich ist

Für reine Shell-Aufgaben reicht häufig eine funktionierende Benutzerumgebung mit Dateisystem- und Netzwerkzugriff. Bei folgenden Aufgaben müssen Sie genauer prüfen:

  • Code-Signing mit Zertifikaten aus der Keychain.
  • Zugriff auf geschützte private Schlüssel.
  • iOS- oder macOS-Simulator-Aufgaben.
  • Xcode-Builds, die eine interaktive oder grafisch initialisierte Apple-Entwicklungsumgebung erwarten.
  • Tests, die Benutzerfreigaben oder entperrte Schlüsselbundobjekte benötigen.

Apple beschreibt in der Dokumentation zu Service Management, dass benutzerbezogene Hintergrunddienste an die Benutzerumgebung gebunden sind. Daraus folgt für Ihre Abnahme: Ein Runner, der nur einfache Shell-Kommandos ausführt, ist nicht automatisch für Signatur- oder Simulator-Pipelines geeignet.

Automatische Anmeldung ist kein universeller Reparaturschritt. Apple weist auf Einschränkungen durch FileVault und Organisationsrichtlinien hin; die Apple-Hinweise zur automatischen Anmeldung sollten Sie vor einer Änderung der Sicherheitskonfiguration prüfen. Deaktivieren Sie FileVault oder zentrale Richtlinien nicht nur deshalb, weil ein Runner nach dem Neustart offline ist.

Aufgabentyp Sitzungsanforderung Abnahmekriterium
Shell-Build ohne Schlüsselbund Benutzerumgebung und Dateirechte Auftrag läuft nach Neustart ohne Handarbeit
Xcode-Build ohne Signatur Xcode, Pfade und Abhängigkeiten verfügbar Kompilierung endet erfolgreich
Code-Signing Richtiger Benutzer, entsperrte Keychain, Zertifikate Signatur und Export funktionieren
Simulator-Test Grafische Benutzersitzung und Simulator verfügbar Simulator startet und Testbericht wird erzeugt

Prüfen Sie den LaunchAgent nicht aus der falschen Sitzung

Ein häufiger Hinweis lautet:

launchctl failed: Could not find domain for ...

Dieser Fehler passt zu einer Situation, in der der Dienst aus einer reinen SSH-Sitzung heraus installiert oder gestartet wurde, obwohl der benötigte Benutzerbereich der grafischen Anmeldung nicht vorhanden war. GitLab verlangt für die macOS-Serviceeinrichtung eine Terminal-Sitzung innerhalb der grafischen Benutzerumgebung.

Verbinden Sie sich deshalb für die Korrektur über VNC oder die Webkonsole mit dem Mac. Öffnen Sie dort ein Terminal unter dem vorgesehenen Benutzer. Führen Sie erst dann die von GitLab dokumentierten Dienstbefehle aus. Die GitLab-Befehlsreferenz hilft Ihnen dabei, die tatsächlich verwendeten Konfigurations- und Dienstpfade zu identifizieren.

Bevor Sie etwas entfernen, sichern Sie die vorhandene Konfiguration. Verwenden Sie Platzhalter statt produktiver Werte:

cp /PFAD/ZUR/config.toml /PFAD/ZUR/config.toml.backup
launchctl print gui/$(id -u)
ps aux | grep '[g]itlab-runner'

Die Ausgabe von id -u ist dabei kein fixer Wert, sondern die Kennung des aktuell angemeldeten Benutzers. Prüfen Sie, ob der Prozess unter demselben Konto läuft, dem die Konfigurationsdatei und das Arbeitsverzeichnis gehören.

Wann eine Neuinstallation vertretbar ist

Eine Neuinstallation ist erst dann angemessen, wenn mindestens einer dieser Befunde vorliegt:

  • Die plist-Datei fehlt oder verweist auf einen nicht mehr vorhandenen Runner-Pfad.
  • Die Binärdatei wurde gelöscht oder ist nicht ausführbar.
  • Die Konfiguration wurde gesichert und lässt sich nicht mehr sinnvoll laden.
  • Die Logausgabe belegt beschädigte Dienstdateien.
  • Der Dienst wird in der korrekten grafischen Sitzung geladen, beendet sich aber reproduzierbar wegen einer beschädigten Installation.

Sichern Sie vor dem Entfernen mindestens config.toml, den Pfad zur Runner-Binärdatei und relevante Logs. Eine erneute Registrierung ohne Plan kann zusätzliche Bereinigung verursachen und erschwert die Unterscheidung zwischen einem Dienstfehler und einem Registrierungsfehler.

Wichtig: Ersetzen Sie den Benutzer-LaunchAgent nicht eigenmächtig durch einen LaunchDaemon. Für macOS bestätigt GitLab den LaunchAgent als unterstützte Dienstform und nicht den systemweiten LaunchDaemon als gleichwertige Alternative. Das ist besonders kritisch, wenn Keychain oder Simulator beteiligt sind.

Sammeln Sie Beweise aus plist, Pfaden und Logs

Nach der grafischen Anmeldung prüfen Sie zuerst die Dateikette. Die plist muss auf eine existierende Runner-Binärdatei zeigen. Die Konfiguration muss dem erwarteten Konto gehören. Das Logverzeichnis muss vorhanden und beschreibbar sein.

Beispielhafte Prüfungen mit Platzhaltern:

ls -la ~/Library/LaunchAgents
ls -la /PFAD/ZUM/RUNNER
ls -la /PFAD/ZUR/config.toml
ls -la /PFAD/ZUM/LOGVERZEICHNIS
test -x /PFAD/ZUM/RUNNER && echo "Runner ausführbar"
test -w /PFAD/ZUM/LOGVERZEICHNIS && echo "Logpfad beschreibbar"

Achten Sie auf folgende Fehlerbilder:

Meldung oder Status Wahrscheinliche Richtung Benötigter Beleg
killed: 9 Prozess wurde beendet, etwa durch System- oder Sicherheitsbedingungen Prozess- und Systemlog, Binärdatei sowie Signaturpfad
exit status 134 Prozessabbruch oder inkompatibler Laufzeitpfad Vollständige Runner-Logzeilen vor dem Abbruch
Load failed: 5 LaunchAgent konnte nicht korrekt geladen werden plist-Inhalt, Benutzer-Domain und Dateirechte
Kein Prozess nach Anmeldung Agent nicht geladen oder sofort beendet Launchctl-Ausgabe und Runner-Log
Prozess läuft ohne Verbindung Netzwerk, Proxy, Zertifikat oder Registrierung Verbindungsfehler und GitLab-Zeitlinie

Die Fehlercodes allein beweisen noch keine Ursache. Ein Status wie killed: 9 darf nicht automatisch als Berechtigungsfehler interpretiert werden. Sichern Sie den vollständigen Kontext aus den Logs und vergleichen Sie den Startzeitpunkt mit dem Neustart.

Die offizielle Dokumentation zur erweiterten Runner-Konfiguration ist relevant, wenn der Prozess läuft, aber Verbindungs- oder Polling-Probleme zeigt. Prüfen Sie dabei nicht nur die GitLab-Seite, sondern auch lokale Proxyvariablen, Zertifikatspfade und DNS-Auflösung.

Trennen Sie Online-Status, Registrierung und Auftragswarteschlange

Ein GitLab Runner kann als online erscheinen und trotzdem keine Arbeit übernehmen. Prüfen Sie deshalb drei unabhängige Fragen:

  1. Meldet sich der Prozess erfolgreich bei GitLab?
  2. Ist die Registrierung noch gültig und dem richtigen Projekt oder der richtigen Gruppe zugeordnet?
  3. Stimmen Tags, Executor und Anforderungen des Auftrags überein?

Wenn der Auftrag ein Tag wie macos-signing verlangt, der Runner aber nur mit einem anderen Tag registriert ist, bleibt die Pipeline wartend. Das ist kein LaunchAgent-Problem. Lesen Sie die offiziellen Regeln zur Runner-Konfiguration und Tag-Auswahl, bevor Sie die macOS-Dienste verändern.

Netzwerk- und Zertifikatsprüfung

Vergleichen Sie den Zeitpunkt, zu dem der Prozess gestartet wird, mit der ersten erfolgreichen oder fehlgeschlagenen Verbindung. Typische Hinweise sind:

  • Zeitüberschreitung beim Zugriff auf GitLab.
  • Proxy wird nur in interaktiven Shells gesetzt, nicht im LaunchAgent.
  • Zertifikat ist nur in einer Benutzerumgebung verfügbar.
  • DNS funktioniert im Terminal, aber nicht beim automatischen Dienststart.
  • Registrierung oder Token wurde geändert.

Die Konfiguration eines LaunchAgents ist nicht identisch mit Ihrer persönlichen interaktiven Shell. Ein Eintrag in .zshrc beweist daher nicht, dass der Dienst dieselbe Variable erhält. Übernehmen Sie Proxy- und Zertifikatspfade nur bewusst und dokumentieren Sie ihre Eigentümer und Zugriffsrechte.

Der Shell executor führt Befehle mit den Rechten des Runner-Benutzers aus. GitLab warnt in der Sicherheitsdokumentation zum Shell executor deshalb vor nicht vertrauenswürdigen Projekten und gemeinsam genutzten Knoten. Prüfen Sie insbesondere, ob Arbeitsverzeichnisse, SSH-Schlüssel, Keychain-Zugänge oder Artefakte zwischen Projekten sichtbar werden können.

Zustand in GitLab Lokaler Befund Nächste Aktion
Offline Kein Runner-Prozess LaunchAgent, Sitzung und Binärpfad prüfen
Online, keine Aufträge Prozess und Verbindung funktionieren Tags und Projektzuordnung prüfen
Online, Aufträge schlagen sofort fehl Prozess startet Jobs, aber Umgebung ist falsch Shell-Rechte, Pfade und Abhängigkeiten prüfen
Online, Signatur scheitert Runner läuft, Keychain ist nicht verfügbar Grafische Sitzung und Schlüsselbund abnehmen
Online, Simulator scheitert Runner läuft, Simulator fehlt oder ist gesperrt Simulator- und Benutzerkontext separat testen

Führen Sie die Reparatur als kontrollierte Schrittfolge aus

Arbeiten Sie die folgenden Schritte in der angegebenen Reihenfolge ab. Dokumentieren Sie jede Ausgabe mit Hostnamen, Benutzer-Platzhalter und Zeitstempel. Verwenden Sie keine echten Tokens oder Zertifikatsinhalte in Tickets oder Chatprotokollen.

  1. Erreichbarkeit feststellen. Prüfen Sie SSH und, falls verfügbar, VNC oder Webkonsole. Wenn nur SSH funktioniert, markieren Sie die grafische Sitzung als ungeprüft und springen Sie nicht direkt zur Neuinstallation.

  2. Benutzerkontext bestätigen. Melden Sie sich grafisch mit dem für den Runner vorgesehenen Konto an. Kontrollieren Sie mit whoami, id -u und dem Home-Verzeichnis, dass Sie nicht versehentlich ein Administratorkonto oder ein temporäres Konto verwenden.

  3. LaunchAgent-Domain prüfen. Führen Sie launchctl innerhalb dieser grafischen Sitzung aus. Erscheint weiterhin „Could not find domain“, sichern Sie die Ausgabe und prüfen Sie, ob Sie tatsächlich in der erwarteten Benutzer-Domain arbeiten.

  4. plist und Binärdatei abgleichen. Öffnen Sie die plist nur lesend. Vergleichen Sie den dort angegebenen Pfad mit der vorhandenen Runner-Binärdatei. Prüfen Sie Eigentümer, Ausführbarkeit und das Arbeitsverzeichnis.

  5. Konfiguration sichern. Kopieren Sie config.toml an einen geschützten Backup-Ort. Bewahren Sie die Registrierungseinstellungen so auf, dass Sie sie bei einer Reparatur nicht versehentlich verlieren.

  6. Logs mit dem Startversuch korrelieren. Starten oder laden Sie den Dienst gemäß der aktuellen GitLab-Anleitung und sammeln Sie die vollständigen Zeilen vom Start bis zum Abbruch. Notieren Sie, ob der Prozess endet, verbunden bleibt oder nur keine Aufgaben erhält.

  7. Verbindung und Registrierung isolieren. Wenn der Prozess aktiv ist, prüfen Sie nicht erneut nur den Dienststatus. Kontrollieren Sie Netzwerk, Proxy, Zertifikat, Runner-Zuordnung und Registrierung separat.

  8. Eine harmlose Testaufgabe ausführen. Verwenden Sie zunächst einen vertrauenswürdigen Auftrag ohne Code-Signing und ohne Simulator. Damit testen Sie die Basisausführung, ohne gleichzeitig Keychain- und GUI-Probleme einzuführen.

  9. Signatur und Simulator getrennt abnehmen. Führen Sie danach einen kleinen Signing-Test und einen Simulator-Test aus. Ein erfolgreicher Shell-Build ersetzt diese beiden Nachweise nicht.

  10. Erst jetzt über Neuinstallation entscheiden. Wenn plist, Binärdatei oder Dienstinstallation nachweislich beschädigt sind, reparieren Sie sie mit gesicherter Konfiguration. Wenn nur die Sitzung oder das Netzwerk fehlerhaft war, lassen Sie die Installation unverändert.

Machen Sie den Neustarttest zum Lieferkriterium

Ein Remote Mac ist für produktive CI nicht ausreichend geprüft, wenn nur ein manueller Start funktioniert. Der Test muss den Zustand nach einem echten Neustart abbilden.

Beenden Sie zunächst eine normale Pipeline sauber. Prüfen Sie anschließend, ob Arbeitsverzeichnisse und temporäre Dateien erwartungsgemäß behandelt wurden. Starten Sie den Mac neu und warten Sie nicht nur auf die SSH-Erreichbarkeit. Die Reihenfolge der Abnahme sollte lauten:

  • Host ist über den vorgesehenen Zugang erreichbar.
  • Grafische Sitzung ist wiederhergestellt oder die bewusste Einschränkung ist dokumentiert.
  • LaunchAgent ist geladen.
  • Runner-Prozess bleibt aktiv.
  • GitLab zeigt den Runner online.
  • Eine Shell-Aufgabe wird angenommen.
  • Ein Xcode-Build läuft durch.
  • Signing und Simulator werden getrennt bestätigt.

Für entfernte Systeme sollten Sie zwei Zugangswege einplanen. SSH ist effizient für Diagnose und Shell-Builds. VNC oder eine Webkonsole ist wichtig, wenn eine grafische Sitzung, Keychain oder Simulator wiederhergestellt werden muss. Informationen zu einer geeigneten Remote-Mac-Umgebung für Entwickler sollten Sie dabei nicht als Ersatz für die technische Abnahme verstehen, sondern als Voraussetzung für einen kontrollierbaren Wiederherstellungsweg.

Erstellen Sie für jeden Knoten ein kurzes Übergabeprotokoll. Es sollte den vorgesehenen Benutzer, den Runner-Namen, den Executor, erforderliche Tags, den Konfigurationspfad, den Logpfad und die erlaubten manuellen Eingriffe enthalten. Tokens, private Schlüssel und Zertifikatsmaterial gehören nicht in dieses Protokoll.

Vor der Freigabe abhaken

  • [ ] SSH-Zugang nach einem echten Neustart geprüft.
  • [ ] Grafische Sitzung mit dem vorgesehenen Benutzer bestätigt.
  • [ ] LaunchAgent in der richtigen Benutzer-Domain geladen.
  • [ ] Runner-Binärdatei und plist-Pfad stimmen überein.
  • [ ] config.toml gesichert und Eigentümer geprüft.
  • [ ] Runner-Logs zeigen einen erfolgreichen Verbindungsaufbau.
  • [ ] GitLab-Status „online“ mit der lokalen Startzeit verglichen.
  • [ ] Eine Aufgabe ohne Keychain und Simulator erfolgreich ausgeführt.
  • [ ] Code-Signing mit dem vorgesehenen Zertifikat geprüft.
  • [ ] Simulator-Aufgabe separat ausgeführt.
  • [ ] Runner-Tags passen zu den produktiven Pipelines.
  • [ ] Shell-executor-Risiken für alle Projekte bewertet.
  • [ ] Wiederherstellung über SSH und grafische Konsole dokumentiert.
  • [ ] Entscheidung festgehalten: vollautomatische Wiederaufnahme, manuelle Sitzung oder anderer Bereitstellungsweg.

Wenn Sie mehrere Mac-Knoten betreiben, wiederholen Sie den Test nicht nur auf dem technisch stärksten Gerät. Ein Knoten mit anderem Benutzerkonto, anderer Keychain oder abweichendem MDM-Profil kann sich nach dem Neustart anders verhalten. Die Abnahme muss deshalb pro Bereitstellungsvariante erfolgen.

Wählen Sie die passende Wiederherstellungsstrategie

Die richtige Entscheidung hängt vom Auftragstyp ab. Für reine, nicht signierende Shell-Aufgaben kann eine eingeschränkte Wiederherstellung akzeptabel sein. Für Veröffentlichungsaufgaben mit Zertifikaten und Simulatoren ist eine korrekt wiederhergestellte grafische Sitzung ein Muss.

Ein eigener Mac mini kann sinnvoll sein, wenn Sie dauerhaft hohe Auslastung, physische USB-Geräte oder vollständig kontrollierte Hardware benötigen. Eine Mac-mini-Serverlösung ist dann langfristig planbarer, bindet aber Kapital, Wartung, Stromversorgung und Ersatzteilorganisation an Ihre Infrastruktur.

Für wechselnde Projekte, kurzfristige Release-Fenster oder eine zusätzliche Ausweichkapazität ist ein gemieteter Remote Mac oft flexibler. Bei MACCOME sollten Sie vor dem produktiven Einsatz gezielt prüfen, ob der Zugang sowohl über SSH als auch über eine grafische Konsole möglich ist. Entscheidend ist nicht die bloße Erreichbarkeit, sondern ob Sie den LaunchAgent, die Benutzeranmeldung und eine signierte Testpipeline nach einem Neustart selbst verifizieren können.

Ihre aktuelle Lösung ist langfristig problematisch, wenn sie nur über SSH administrierbar ist, keine grafische Wiederherstellung erlaubt oder jeden Neustart durch manuelle Prozessstarts repariert werden muss. Auch ein gemeinsam genutzter Shell-Runner ohne Projekttrennung kann Quellcode und Zugangsdaten gefährden. Wenn zusätzlich Hardwarekauf, Wartung und eine einzelne Fehlerdomäne zusammenfallen, bietet ein kontrolliert getesteter Remote Mac von MACCOME für temporäre CI-Kapazität oder einen Ersatzknoten den praktischeren Betriebsweg.

Entscheiden Sie nach dem Test: Übernehmen Sie die Umgebung erst in die Produktion, wenn Runner, Signierung und Simulator nach dem Neustart reproduzierbar funktionieren. Wenn nur Shell-Aufgaben stabil sind, kennzeichnen Sie den Knoten entsprechend und verschieben Sie releasekritische Jobs nicht ohne weitere Abnahme auf ihn.