Um zwei Uhr morgens führte das dritte Teammitglied einen fastlane build auf demselben Cloud-Mac aus, und die CI schlug sofort fehl: Zertifikat ungültig. Alle drei hatten zuvor lokal match ausgeführt, ohne zu merken, dass ihre jeweilige Aktion das gerade importierte Signaturzertifikat eines Kollegen aus der Standard-Login-Keychain verdrängt hatte. Solche Zwischenfälle sind fast unvermeidlich, wenn mehrere Personen sich einen Cloud-Mac zum Bauen von Paketen teilen. Dieser Artikel dokumentiert, wie wir Zertifikate mit fastlane match zentral verwaltet und das Problem der ständig nach Passwörtern fragenden Keychain in Headless-Remote-Sessions gelöst haben.
Das Problem: Warum ein gemeinsamer Cloud-Mac ständig Zertifikatsärger verursacht
Bei lokaler Entwicklung dient ein Mac meist nur einer Person, sodass die Zertifikate in der Standard-Keychain niemandem in die Quere kommen. Ein tageweise gemieteter Cloud-Mac wird jedoch oft im Team geteilt: Heute loggst du dich ein, um zu bauen, morgen meldet sich ein Kollege remote an, um eine Konfiguration zu ändern und erneut zu bauen. Führt jeder für sich fastlane match development aus oder importiert manuell eine p12-Datei, werden die Zertifikatseinträge in der Standard-Keychain immer wieder überschrieben, gelöscht und neu erstellt — am Ende erscheint der typische Fehler „Zertifikat vorhanden, aber privater Schlüssel beim Signieren nicht auffindbar".
Die eigentliche Ursache ist die Vermischung zweier unterschiedlicher Dinge: Speicherung und Verteilung von Zertifikaten einerseits und temporäre Autorisierung des Zertifikats in der lokalen Keychain andererseits. Ersteres sollte zentral verwaltet werden, Letzteres muss dagegen pro Session isoliert erfolgen.
Das Kernprinzip von fastlane match
match verschlüsselt Entwicklungs- und Verteilungszertifikate samt zugehöriger Provisioning-Profile und speichert sie zentral in einem separaten Git-Repository. Alle Teammitglieder — sowie der Automatisierungs-User auf dem Cloud-Mac — ziehen dieselben Zertifikate aus diesem Repository, statt jeweils eigene im Apple Developer Portal neu zu erzeugen. So bleibt das Signaturergebnis für dieselbe Bundle-ID auf jeder Maschine identisch, und das alte Problem „Zertifikatsanzahl überschreitet Apple-Limit" entfällt.
Der Wert von match liegt nicht darin, „Zertifikate automatisch zu erzeugen", sondern darin, dass „niemand mehr eigene Zertifikate erzeugen muss" — dieser Satz bestimmt die richtige Nutzung: Nur eine Person (oder ein einmaliger CI-Initialisierungsjob) sollte Schreibvorgänge ausführen, alle anderen Szenarien sollten ausschließlich im Read-only-Modus abrufen.
Zertifikats-Repository auf dem Cloud-Mac einrichten
Stelle im Projektverzeichnis auf deinem Cloud-Mac zunächst sicher, dass die Matchfile auf ein privates Repository verweist, nicht auf eine öffentliche Adresse:
git_url("git@github.com:your-org/certs-private.git")
storage_mode("git")
type("appstore")
Die Erstinitialisierung wird nur einmal auf einer vertrauenswürdigen Maschine ausgeführt:
fastlane match appstore --readonly false
Danach sollten alle Abruf-Vorgänge auf Cloud-Macs mit --readonly true versehen werden, damit sie nur vorhandene Zertifikate lesen und keine Neuerzeugung anstoßen:
fastlane match appstore --readonly true
Vergib dem Deployment-User einen separaten, nur lesenden Git-Deploy-Key, statt die persönlichen SSH-Keys aller Teammitglieder auf den Cloud-Mac zu packen — das schafft klarere Berechtigungsgrenzen und erspart bei Personalwechseln einzelne Widerrufsschritte.
Passwortloses Keychain-Entsperren in Headless-Remote-Sessions
Cloud-Macs werden meist per SSH oder VNC fernbedient, niemand sitzt physisch vor dem Bildschirm und tippt ein Passwort ein. Die Standard-Login-Keychain befindet sich zwischen Sessions daher häufig im gesperrten Zustand, und sobald codesign ausgeführt wird, erscheint ein Autorisierungsdialog — was in unbeaufsichtigten CI-Trigger-Szenarien zu einem sofortigen Stillstand führt.
Die Lösung: eine dedizierte Signatur-Keychain anlegen, getrennt von der Login-Keychain:
security create-keychain -p "$KEYCHAIN_PWD" signing.keychain
security set-keychain-settings -lut 21600 signing.keychain
security unlock-keychain -p "$KEYCHAIN_PWD" signing.keychain
security import cert.p12 -k signing.keychain -P "$P12_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PWD" signing.keychain
list=$(security list-keychains -d user | tr -d '"')
security list-keychains -d user -s signing.keychain $list
Der Schritt set-key-partition-list wird leicht übersehen — fehlt er, fragt codesign weiterhin per Dialog nach Autorisierung, selbst wenn die Keychain bereits entsperrt ist. Diese dedizierte Keychain sollte ausschließlich die für die Signierung nötigen Zertifikate enthalten und nicht mit alltäglichen Passwörtern vermischt werden — beim Rückgeben der Mietinstanz oder der Übergabe des Projekts lässt sie sich damit viel saubereer löschen als eine bereinigte Standard-Keychain.
Zertifikatsabruf und Cleanup nach CI-Auslösern
Für automatisierte Abläufe empfiehlt sich folgende Reihenfolge, wobei jeder fehlgeschlagene Schritt die Pipeline sofort anhalten sollte, statt stillschweigend fortzufahren:
| Schritt | Befehl/Aktion | Vorgehen bei Fehler |
|---|---|---|
| Dedizierte Keychain entsperren | security unlock-keychain |
Sofort abbrechen, Ticket melden statt still wiederholen |
| Zertifikate read-only abrufen | fastlane match … --readonly true |
Abbrechen, Hinweis auf vorherige Schreibausführung auf der Hauptmaschine |
| Build ausführen | xcodebuild archive |
Build-Logs zur Fehlersuche aufbewahren |
| Temporäre Keychain-Referenzen bereinigen | security delete-keychain signing.keychain (bei Bedarf) |
Erfolg der Bereinigung protokollieren |
Wird der Cloud-Mac tageweise gemietet und nach der Nutzung an eine andere Aufgabe weitergegeben oder zurückgegeben, ist dieser letzte Bereinigungsschritt besonders wichtig: die dedizierte Signatur-Keychain, temporär heruntergeladene p12-Dateien und die Provisioning-Profile unter ~/Library/MobileDevice/Provisioning Profiles sollten am Ende der Aufgabe vollständig gelöscht werden — verlass dich nicht darauf, dass die nächste Mietperiode automatisch eine saubere Umgebung erbt. Ob konkrete Modelle und Knoten dem gleichzeitigen Build-Bedarf deines Teams gerecht werden, solltest du vorab in der Konsole prüfen, bevor du die Planung fixierst — unterschiedliche Chip-Modelle unterscheiden sich in der Kompilierzeit erheblich, was sich direkt auf die Wartezeit bei mehreren parallelen Nutzern auswirkt.
Team-Zusammenarbeit und Berechtigungsgrenzen
Eine klare Aufgabentrennung erspart bei der späteren Fehlersuche viel Zeit:
- Schreibrecht für Zertifikate: nur an eine Person oder eine Initialisierungs-Pipeline vergeben; alle Teammitglieder und Automatisierungs-Accounts auf Cloud-Macs verwenden einheitlich
--readonly true. - Repository-Zugriffsrecht: Zertifikats-Repository über Deploy-Keys statt persönlicher Account-Keys anbinden, damit sich Rechte pro Person und Maschine gezielt widerrufen lassen.
- Isolation lokaler Keychains: jeder Nutzer bzw. jede parallele Build-Linie erhält eine eigene Keychain-Datei und ein eigenes Build-Verzeichnis, um gegenseitiges Überschreiben der Standard-Keychain zu vermeiden.
- Speicherung von Passwörtern und Tokens:
KEYCHAIN_PWD,P12_PWDund Git-Deploy-Keys werden über Umgebungsvariablen oder verschlüsselte CI-Variablen injiziert, nicht direkt in Skriptdateien geschrieben.
Checkliste vor dem Go-Live
- [ ] Die
Matchfileverweist auf ein privates Repository, und niemand im Team hat je Zertifikatshistorie in einem öffentlichen Repository abgelegt; - [ ] Alle match-Befehle auf Cloud-Macs werden mit
--readonly trueausgeführt; - [ ]
set-key-partition-listwurde auf der dedizierten Signatur-Keychain ausgeführt,codesignöffnet keinen Dialog mehr; - [ ] Jeder parallele Nutzer/jede Build-Linie hat eine eigene Keychain-Datei und ein eigenes Build-Verzeichnis;
- [ ] Vor Ablauf der Aufgabe oder Mietperiode existiert ein Cleanup-Skript, das die dedizierte Keychain und temporäre Provisioning-Profile entfernt.
Sobald Zertifikatsverwaltung und Keychain-Entsperrung getrennt behandelt werden, kommt es beim abwechselnden Bauen mehrerer Teammitglieder auf demselben Cloud-Mac praktisch nicht mehr zu gegenseitigen Konflikten. Neue Projektmitglieder müssen dann nur einmal das Repository klonen und den Read-only-Befehl ausführen, statt eigene Zertifikate neu zu beantragen.
Häufig gestellte Fragen
Kann das match-Zertifikatsrepo einfach ein öffentliches Git-Repo sein?
Nein. match verschlüsselt p12-Zertifikate und Provisioning-Profile vor der Speicherung, aber ein öffentliches Repo verrät trotzdem Struktur und Metadaten. Nutzen Sie ein privates Repo und geben Sie dem Deploy-Nutzer auf dem Cloud-Mac nur einen Read-only-Token.
Muss ich nach jedem Neustart des Cloud-Mac das Keychain-Passwort erneut eingeben?
Nein. Legen Sie mit security create-keychain eine dedizierte Signatur-Keychain mit festem Passwort an, deaktivieren Sie mit security set-keychain-settings die Auto-Sperre, gewähren Sie codesign mit -A Zugriff ohne Bestätigung, und führen Sie nach jedem neuen Session-Login einmal das Entsperr-Skript aus.
Kollidieren Zertifikate, wenn mehrere Personen auf demselben Cloud-Mac bauen?
Ja, wenn jeder match einzeln ausführt, wird die Standard-Keychain wiederholt importiert und exportiert, was Konflikte erzeugt. Geben Sie jeder Person ein eigenes Build-Verzeichnis und eine dedizierte Keychain-Datei, und nutzen Sie den readonly-Modus von match, damit nur vorhandene Zertifikate gelesen statt neu erzeugt werden.
HireVPS Cloud Mac
Testen Sie noch heute einen dedizierten Cloud Mac mini
Tagesweise mietbar, SSH/VNC-Zugangsdaten in nur 2 Minuten, Konfiguration jederzeit upgradbar.