Um eine Capacitor-App in der Cloud zu signieren und zu bauen, erstellst du dein Signing-Material einmalig (Android-Keystore, iOS-Distributionszertifikat und Provisioning-Profil), übergibst es einem Cloud-Build-Dienst und löst Builds dann aus deinem Terminal oder CI aus. Der Dienst kompiliert das Native-Projekt, signiert es und kann es direkt auf TestFlight oder Google Play hochladen. Dieser Guide behandelt jede Signing-Datei, wie du sie ohne Mac erstellst, wie du sie mit Capgo Build einrichtest und wie du signierte Builds sicher automatisierst.
Was „Signing in der Cloud“ bedeutet
Beide Stores akzeptieren nur signierte Binärdateien. Die Signierung beweist, dass der Build von dir stammt und dass ihn danach niemand verändert hat. Lokal verbergen Xcode und Android Studio das meiste davon. In der Cloud ist nichts implizit, daher musst du genau wissen, welche Dateien beteiligt sind:
| Plattform | Datei | Was es ist | Verwendung |
|---|---|---|---|
| Android | .jks / .keystore |
Keystore für deinen Upload-Key | Signierung der AAB oder APK |
| Android | Service Account .json |
Google Cloud Credentials | Upload zu Google Play |
| iOS | .p12 |
Apple Distribution-Zertifikat plus privater Schlüssel | IPA signieren |
| iOS | .mobileprovision |
Provisioning Profile, das Bundle ID, Zertifikat und Capabilities verknüpft | Die App ausführbar machen und verteilen |
| iOS | .p8 + Key-ID + Issuer-ID |
App Store Connect API Key | Upload zu TestFlight, Build-Nummern auslesen |
Halte diese Informationen aus Git heraus. Alles Folgende speichert sie in deiner lokalen Credential-Datei oder im Secret Store deiner CI.
Android-Signierung
Upload-Keystore erstellen
Falls die App bereits bei Google Play ist, verwende den vorhandenen Keystore. Ein Update mit einem anderen Key zu signieren, wird abgelehnt, es sei denn, du führst den Upload-Key-Reset in der Play Console durch.
Für eine neue App:
keytool -genkeypair -v \
-storetype PKCS12 \
-keystore release.jks \
-alias upload \
-keyalg RSA -keysize 2048 \
-validity 10000
Hinweise:
- Google Play setzt voraus, dass der Key mindestens bis zum 22. Oktober 2033 gültig ist.
-validity 10000(ca. 27 Jahre) deckt das ab. - Beim PKCS12-Store-Typ ist das Key-Passwort identisch mit dem Store-Passwort.
- Kein JDK zur Hand? Die Android Keystore Generator erzeugt im Browser dieselbe Datei.
Play App Signing und der Upload-Key
Neue Apps auf Google Play nutzen Play App Signing. Google verwaltet den App-Signing-Key und signiert das, was Nutzer herunterladen, neu. Dein Keystore ist der Upload-Key. Wenn du ihn verlierst, kann der Play-Console-Support einen neuen Upload-Key registrieren – ein Verlust ist also eine Verzögerung, kein Desaster. Mach trotzdem ein Backup.
Service-Account für Uploads
Um aus der Cloud hochzuladen, erstelle einen Service-Account in Google Cloud, aktiviere die Google Play Android Developer API, lade den JSON-Key herunter und gib dem Service-Account in der Play Console unter Nutzer und Berechtigungen die Release-Berechtigungen für deine App. Das Onboarding von Capgo erledigt das per Google Sign-in, wie unten gezeigt.
iOS-Signing
Die drei Apple-Komponenten
- Apple-Distribution-Zertifikat. Eines pro Team reicht und ist ein Jahr gültig. Apple begrenzt die Anzahl, erstelle also nicht für jeden Entwickler ein eigenes.
- Provisionierungsprofil. Verknüpft die Bundle-ID, das Zertifikat und Funktionen wie Push-Benachrichtigungen. Verwenden Sie ein App Store Connect Profil für TestFlight und den App Store sowie ein Ad Hoc Profil für Installationen auf registrierten Geräten. Jede App-Erweiterung (Widget, Share-Erweiterung, Benachrichtigungsdienst) benötigt ihr eigenes Profil.
- App Store Connect API Schlüssel. Erstellt unter Benutzer und Zugriff > Integrationen mit App-Manager-Zugriff. Die
.p8Datei wird nur einmal heruntergeladen.
Du benötigst Admin- oder Account-Holder-Rechte im Apple Developer Team, um diese zu erstellen.
Zertifikat ohne Mac erstellen
Der Keychain-Access-Flow braucht macOS, aber OpenSSL funktioniert überall:
# 1. Private key and certificate signing request
openssl req -new -newkey rsa:2048 -nodes \
-keyout dist.key -out dist.csr \
-subj "/emailAddress=dev@example.com/CN=Example Inc/C=US"
# 2. Upload dist.csr at developer.apple.com > Certificates > + > Apple Distribution
# and download distribution.cer
# 3. Convert and bundle into a .p12
openssl x509 -inform DER -in distribution.cer -out distribution.pem
openssl pkcs12 -export -legacy \
-inkey dist.key -in distribution.pem \
-out distribution.p12 -passout pass:choose-a-password
Der -legacy Das Flag ist bei OpenSSL 3 wichtig: Ohne es können macOS-Build-Maschinen den Import der .p12 mit „MAC verification failed“ fehlschlagen. Der browserbasierte iOS-Zertifikatsgenerator führt dieselben Schritte aus, falls du kein Terminal nutzen möchtest.
Erstelle dann das Provisioning Profile im Developer Portal (Profile > + > App Store Connect), wähle deine App ID sowie das neue Zertifikat aus und lade es herunter.
Richte das Signing mit Capgo Build ein
Capgo Build kompiliert und signiert Capacitor Apps auf Capgo-verwalteten Maschinen, sodass du iOS von Windows oder Linux aus builden kannst. Melde dich zuerst an und registriere die App:
bunx @capgo/cli@latest login
bunx @capgo/cli@latest app add
Option A: geführtes Onboarding (empfohlen)
bunx @capgo/cli@latest build init --platform ios
bunx @capgo/cli@latest build init --platform android
Auf iOS erstellt oder nutzt das Onboarding das Distribution-Zertifikat und das App Store Provisioning Profile mit deinem App Store Connect API Key. Auf macOS kann es dich auch durch das Erstellen dieses API Keys führen. Auf Android erstellt oder importiert es den Keystore und kann das Google Cloud Service Account und die Play Console Einladung per Google Sign-in einrichten. Am Ende bietet es den ersten Build an.
Option B: vorhandene Dateien speichern
Falls du die Dateien aus den vorherigen Abschnitten bereits hast:
# iOS
bunx @capgo/cli@latest build credentials save \
--platform ios \
--certificate ./distribution.p12 \
--p12-password "choose-a-password" \
--ios-provisioning-profile ./AppStore.mobileprovision \
--apple-key ./AuthKey_ABC1234567.p8 \
--apple-key-id ABC1234567 \
--apple-issuer-id 00000000-0000-0000-0000-000000000000 \
--apple-team-id TEAM123456
# Android
bunx @capgo/cli@latest build credentials save \
--platform android \
--keystore ./release.jks \
--keystore-alias upload \
--keystore-key-password "store-password" \
--keystore-store-password "store-password" \
--play-config ./play-service-account.json
Für Apps mit Extensions wiederhole dies --ios-provisioning-profile mit einem bundleId=path Mapping für jedes Target:
--ios-provisioning-profile com.example.app=./App.mobileprovision \
--ios-provisioning-profile com.example.app.widget=./Widget.mobileprovision
Credentials werden gespeichert in ~/.capgo-credentials/credentials.json, mit App-ID und Plattform als Schlüssel. Füge --local hinzu, um sie in .capgo-credentials.json stattdessen im Projekt zu speichern, und füge diese Datei zu .gitignore. Prüfe, was mitgespeichert wird bunx @capgo/cli@latest build credentials list.
Einen signierten Build triggern
Bereite das native Projekt vor und fordere dann den Build an:
bun run build
bunx cap sync
# iOS: sign with the App Store profile and upload to TestFlight
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
# Android: sign the AAB and upload to the internal track
bunx @capgo/cli@latest build request com.example.app --platform android --build-mode release --android-track internal
Die Logs werden direkt in dein Terminal gestreamt. Ein Pre-Build-Scan prüft Zertifikatsablauf, Passwörter und Profil-Pairing, bevor etwas hochgeladen wird. So schlagen die meisten Signing-Fehler in Sekunden statt Minuten fehl. Starte es separat mit bunx @capgo/cli@latest build prescan --platform ios.
Nützliche Varianten:
| Ziel | Flags |
|---|---|
| Test-Build auf registrierten iPhones | --ios-distribution ad_hoc --ios-provisioning-profile ./adhoc.mobileprovision --output-upload |
| APK für MDM oder Kiosk-Geräte | --platform android --no-playstore-upload --output-upload |
| Direkt zur App Review einreichen | --submit-to-store-review --store-release-name 2.4.0 |
| Eigene Build-Nummer beibehalten | --skip-build-number-bump |
| Clean Build ohne Cache | --no-cache |
Sammle für Ad-hoc-Builds zuerst die Geräte-UDIDs mit dem iOS UDID Finder und füge sie dem Profil hinzu.
Signierte Builds in CI automatisieren
Übergib in CI die Anmeldedaten als Umgebungsvariablen statt als Credentials-Datei. CLI exportiert genau das, was du brauchst:
bunx @capgo/cli@latest build credentials manage --appId com.example.app
# choose "Export to .env"
Auf GitHub schiebst du jede Zeile mit einem Befehl in die Repository-Secrets und löschst dann die Datei:
gh secret set -f .env.capgo.com.example.app
gh secret set CAPGO_TOKEN --body "your-capgo-api-key"
rm .env.capgo.com.example.app
Ein Release-Workflow, der beide Plattformen bei einem Tag signiert und ausliefert:
name: Signed release
on:
push:
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform: [ios, android]
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run build
- run: bunx cap sync ${{ matrix.platform }}
- run: bunx @capgo/cli@latest build request com.example.app --platform ${{ matrix.platform }} --build-mode release
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }}
Der Job läuft auf Linux. Kein macOS-Runner, keine Keychain-Befehle, kein fastlane. Dieselben Umgebungsvariablen funktionieren in jeder CI: GitLab CI/CD-Variablen, Bitbucket Secured Variables, Gitea Secrets oder Azure DevOps Variable Groups. Plattformspezifische Anleitungen: Bitbucket Pipelines, Gitea Actions, und die GitHub Actions-Dokumentation.
Umgang mit deinen Keys
Eine berechtigte Frage, bevor man Signing-Keys einem Cloud-Service anvertraut. Mit Capgo Build:
- Credentials liegen auf deinem Rechner (
~/.capgo-credentials/) oder in deinem CI-Secret-Store. Capgo speichert deine Keys nicht in einem Vault. - Für jeden Build sendet CLI sie über HTTPS. Sie werden nur während dieses Builds verwendet und nach Abschluss gelöscht.
- Nur das vorbereitete native Projekt wird hochgeladen. Deine Web-Source-
.git, und.envDateien werden nicht hochgeladen. - Gebaute Apps gehen direkt zu App Store Connect oder Google Play – oder auf Wunsch zu einem zeitlich begrenzten Download-Link.
Der Trade-off: Wenn du ein Credential rotierst, musst du deine CI-Secrets selbst aktualisieren. Neu exportieren mit build credentials manage und die Datei erneut pushen.
Ablauf und Rotation
| Punkt | Gesamt | Was zu tun ist |
|---|---|---|
| Apple-Distribution-Zertifikat | 1 Jahr | Neues erstellen, Profile neu generieren, erneut speichern, CI aktualisieren |
| Provisioning-Profil | 1 Jahr oder bis das Zertifikat widerrufen wird | Neu generieren und erneut speichern |
| App Store Connect API Key | Bis zum Widerruf | Widerrufen, wenn jemand mit Zugriff geht |
| Android-Upload-Keystore | Solang die Gültigkeit anhält (auf Jahrzehnte setzen) | Sichern; bei Verlust über Play Console zurücksetzen |
| Play-Service-Account-Key | Bis zur Löschung | Jährlich rotieren oder bei Zugriffsänderung |
Apple-Daten in einen geteilten Kalender eintragen. Ein abgelaufenes Zertifikat betrifft keine Apps, die bereits auf den Geräten der Nutzer sind, blockiert aber jeden neuen Build.
Fehlerbehebung
| Fehler | Ursache und Lösung |
|---|---|
Provisioning profile doesn't include signing certificate |
Das Profil wurde für ein anderes Zertifikat erstellt. Erstellen Sie es mit dem aktuellen Zertifikat neu. |
Provisioning profile doesn't match bundle ID |
Profil für eine andere App-ID erstellt oder fehlendes Extension-Target. Fügen Sie hinzu: bundleId=path Mapping für jedes Ziel. |
MAC verification failed |
Falsch .p12 Passwort oder OpenSSL-3-Export ohne -legacy. |
Keystore was tampered with, or password was incorrect |
Falsches Store-Passwort oder die Datei wurde durch Base64-Zeilenumbrüche beschädigt. |
Key alias not found |
Alias weicht von dem im Keystore ab. Liste ihn mit keytool -list -keystore release.jks. |
| App Store Connect-Authentifizierung fehlgeschlagen | Falsche Key ID oder Issuer ID, widerrufener Key oder eine falsch gehende Systemuhr auf dem Rechner, der das Token signiert. |
| Play-Upload: Aufrufer hat keine Berechtigung | Service Account nicht in der Play Console eingeladen oder Android Developer API nicht aktiviert. |
Weitere Fixes findest du im Capgo Build-Troubleshooting-Leitfaden und CI/CD für Capacitor: häufige Fallstricke.
Nach dem ersten signierten Build
Signierte Native Builds werden nur bei Änderungen am nativen code benötigt. Für JavaScript-, CSS- und HTML-Änderungen kannst du einfach einen live update statt installierte Apps zu nutzen und Store-Builds für Releases mit Plugins oder nativen Konfigurationen aufzusparen. Wenn du von einem Mac-basierten Setup kommst, iOS-App unter Windows mit Capgo Build erstellen zeigt den kompletten Workflow ohne macOS.