Am Vorabend des Release-Tags mussten drei Targets im Projekt gleichzeitig als Full-Build kompiliert werden: die Haupt-App, ein Today-Widget und eine begleitende Apple-Watch-App. Auf einer einzelnen Maschine dauerte der komplette Durchlauf 38 Minuten. Für ein dauerhaft betriebenes CI-Cluster hatte das Team schlicht kein Budget – aber am Release-Tag konnte man auf diese Wartezeit nicht warten. Wir haben uns daher für einen Mittelweg entschieden: Am Release-Tag mieten wir kurzfristig drei Cloud-Mac-mini-Instanzen und bauen daraus eine "Ein-Tages-Build-Farm". Per SSH-Matrix werden die Jobs verteilt, nach dem Build signieren wir zentral und führen die Artefakte zusammen. Der gesamte Vorgang dauert unter 15 Minuten und liefert drei upload-fertige Pakete. Dieser Artikel beschreibt den kompletten Ablauf dieser Orchestrierung.
Wann sich Multi-Node überhaupt lohnt
Nicht jedes Projekt braucht diesen Aufwand. Die Faustregel ist einfach: Erst wenn ein einzelner Full-Build über 20 Minuten dauert oder ein Release mehrere Targets bzw. Architekturen gleichzeitig produzieren muss, lohnt sich das kurzfristige Hochfahren zusätzlicher Nodes. Für den normalen Alltag – Code schreiben, Unit-Tests laufen lassen – reicht ein Mini Standard (24 GB RAM) völlig aus; drei Nodes dauerhaft laufen zu lassen wäre reine Geldverschwendung.
Das Kernprinzip einer Multi-Node-Farm lautet: tageweise mieten, sofort wieder auflösen. Man bestellt die Instanzen am Vorabend des Release-Fensters und gibt sie unmittelbar nach Abschluss wieder frei – Kosten entstehen also nur an dem Tag, an dem parallele Rechenleistung tatsächlich gebraucht wird.
Farm-Topologie und Aufgabenverteilung
Die Rollenverteilung richtet sich nach den Netzwerkpfaden und Ressourcen der einzelnen Nodes. Vor der Verteilung lohnt ein Blick in die Konsole, welche Konfigurationsstufen an den einzelnen Standorten zur Auswahl stehen – die rechenintensive Rolle gehört auf einen Node, dessen Netzwerkpfad und Ressourcen zur Aufgabe passen.
| Node-Rolle | Paket | Chip/RAM | Standort | Preis/Tag | Aufgabe |
|---|---|---|---|---|---|
| Haupt-Build-Node | Mini Pro | M4 Pro / 64 GB | US-Westen | 59,3 $/Tag | Haupt-App-Target, zusätzlich Signierung und Zusammenführung |
| Build-Node A | Mini Standard | M4 / 24 GB | Tokio | 40,1 $/Tag | Today-Widget-Target |
| Build-Node B | Mini Standard | M4 / 24 GB | Seoul | 40,1 $/Tag | Watch-App-Target |
Zusammen ergibt das 139,5 $/Tag. Zum Vergleich: Würde man alle drei auf Mini Pro umstellen, kämen 177,9 $/Tag zusammen – die Build-Last von Widget und Watch-App ist von Haus aus gering, ein Standard-Paket reicht völlig aus. So bleibt das Budget für den wirklich RAM-hungrigen Build der Haupt-App reserviert.
Lektion aus der Praxis: Zunächst hatten wir alle drei Nodes in Tokio platziert. Nachdem wir Haupt-Build- und Signier-Node zu einer Instanz zusammengelegt hatten, war der interne rsync-Transfer zwar schnell – aber der US-West-Node übernahm anschließend den Upload zu App Store Connect und lag damit näher am eigentlichen Upload-Ziel. Fazit: Der Signier-Node sollte näher am Upload-Endpunkt liegen als am Standort der Entwickler.
Verteilungsskript und Ausführung
Als Koordinator dient meist der Haupt-Build-Node selbst. Ein einfaches Bash-Skript verteilt die Targets an die untergeordneten Nodes, führt sie im Hintergrund parallel aus und wartet am Ende auf alle Ergebnisse:
#!/bin/bash
set -e
NODES=("node-a.internal" "node-b.internal")
TARGETS=("WidgetExtension" "WatchApp")
for i in "${!NODES[@]}"; do
ssh "build@${NODES[$i]}" \
"cd ~/repo && xcodebuild -scheme ${TARGETS[$i]} \
-configuration Release -archivePath build/${TARGETS[$i]}.xcarchive \
archive CODE_SIGNING_ALLOWED=NO" &
done
xcodebuild -scheme MainApp -configuration Release \
-archivePath build/MainApp.xcarchive archive
wait
echo "all targets archived"
Entscheidend ist, dass die untergeordneten Nodes mit CODE_SIGNING_ALLOWED=NO laufen und nur unsignierte .xcarchive-Dateien erzeugen – Zertifikate müssen also gar nicht erst auf diese Maschinen synchronisiert werden. Der Haupt-Build-Node behält die Zertifikate selbst, kompiliert und signiert MainApp und wartet parallel auf die Artefakte der anderen Nodes.
Artefakte zusammenführen und zentral signieren
Sobald die untergeordneten Nodes fertig sind, schieben sie ihre .xcarchive-Dateien per rsync zurück zum Haupt-Node:
rsync -avz build@node-a.internal:~/repo/build/WidgetExtension.xcarchive ./build/
rsync -avz build@node-b.internal:~/repo/build/WatchApp.xcarchive ./build/
Sobald alle drei Archives vorliegen, führt man auf dem Haupt-Node mit demselben Provisioning-Profile und denselben Zertifikaten einmal xcodebuild -exportArchive aus und lädt anschließend mit fastlanes pilot upload alle drei Pakete in einem Schritt zu TestFlight hoch. Die Signierung findet damit ausschließlich auf einer einzigen Maschine statt, der private Schlüssel verlässt diese Instanz nie – ein Punkt, der bei jeder Sicherheitsüberprüfung immer wieder abgefragt wird.
Vor der Bestellung lohnt sich ein kurzer Check anhand dieser Liste:
- [ ] Stimmen macOS- und Xcode-Version auf allen drei Nodes exakt überein (verhindert Architektur-Abweichungen bei den Artefakten)
- [ ] Sind die SSH-Public-Keys der untergeordneten Nodes bereits vorab in
authorized_keyseingetragen - [ ] Liegt der Signier-Node möglichst nah am Upload-Endpunkt von App Store Connect
- [ ] Ist auf jedem Node noch genug kostenloses Reinstall-Kontingent vorhanden – kurz vor dem Release nicht mehr neu aufsetzen
Typische Fallstricke und Grenzen
Multi-Node-Orchestrierung lohnt sich nicht in jedem Fall. Hat ein Projekt nur ein einziges Target oder liegt der Full-Build ohnehin unter 10 Minuten, erzeugt die Aufteilung auf mehrere Nodes durch SSH-Koordination und rsync-Transfer nur zusätzliche Wartezeit – dann fährt man besser mit einem einzelnen Node durch. Außerdem gibt es in Seoul aktuell keine Pro/Max-Pakete: Wenn eines der drei Targets besonders RAM-hungrig ist (etwa ein Target mit ML-Modell-Inferenz), sollte man es von vornherein auf einen Pro/Max-Node in Tokio oder im US-Westen legen, statt es zwangsweise auf einen Standard-Node in Seoul zu pressen.
Häufig gestellte Fragen
Für welche Projektgröße lohnt sich eine Multi-Node-Build-Farm?
Es lohnt sich, wenn ein Vollbuild rund zwanzig Minuten überschreitet oder mehrere Targets (Haupt-App, Widget, Watch-App) und Architekturen gleichzeitig entstehen müssen. Für die tägliche Solo-Entwicklung reicht ein einzelner Standard-Node.
Wie bleiben Signaturzertifikate über mehrere Nodes hinweg konsistent, ohne zu leaken?
Zertifikate und Provisioning-Profile bleiben ausschließlich auf einem Node, meist dem Signier-Node in US West. Andere Nodes kompilieren nur unsignierte .app/.xcarchive-Artefakte und schicken sie per Rsync zum Signier-Node für einen einzigen Signier- und Upload-Durchgang, sodass private Schlüssel nie auf mehreren Maschinen liegen.
Wie entscheide ich, welcher Node die rechenintensive Compile-Rolle übernimmt?
Prüfe in der Konsole, welche Konfigurationsstufen an den einzelnen Standorten zur Auswahl stehen, und berücksichtige die Netzwerkpfade des Teams sowie das Upload-Ziel der Artefakte: Die rechenintensive Rolle gehört auf einen Node mit ausreichend Ressourcen und niedriger Latenz zu den wichtigsten Teammitgliedern, die Signier- und Upload-Rolle auf einen Node mit hoher Ausgangsbandbreite.
Brauchen Sie einen dedizierten Mac mini für Ihre Builds?
Physische Standorte in Singapur, Tokio, Seoul, Hongkong und US-West – Mietdauer ab einem Tag, VNC-/SSH-Zugangsdaten innerhalb von 10 Minuten.
Jetzt Mac mini mieten