Pour signer et compiler une application Capacitor dans le cloud, vous créez vos éléments de signature une seule fois (un keystore Android, un certificat de distribution iOS et un profil de provisionnement), vous les transmettez à un service de build cloud, puis vous déclenchez les builds depuis votre terminal ou votre CI. Le service compile le projet natif, le signe et peut l'envoyer directement sur TestFlight ou Google Play. Ce guide détaille chaque fichier de signature, comment les créer sans Mac, comment les configurer avec Capgo Build et comment automatiser les builds signés en toute sécurité.
Ce que signifie la « signature dans le cloud »
Les deux stores n'acceptent que des binaires signés. La signature prouve que le build provient bien de vous et que personne ne l'a modifié par la suite. En local, Xcode et Android Studio masquent la majeure partie de ce processus. Dans le cloud, rien n'est implicite : vous devez donc savoir exactement quels fichiers sont impliqués :
| Plateforme | Fichier | Description | Usage |
|---|---|---|---|
| Android | .jks / .keystore |
Keystore contenant votre clé d'upload | Signature de l'AAB ou de l'APK |
| Android | Compte de service .json |
Identifiants Google Cloud | Upload vers Google Play |
| iOS | .p12 |
Certificat Apple Distribution et clé privée | Signature de l’IPA |
| iOS | .mobileprovision |
Profil de provisionnement liant l’identifiant de bundle, le certificat et les capacités | Permet à l’app de s’exécuter et d’être distribuée |
| iOS | .p8 + ID de clé + ID d’émetteur |
Clé API App Store Connect | Upload sur TestFlight, lecture des numéros de build |
Gardez-les hors de Git. Tout ce qui suit les stocke dans votre fichier de credentials local ou dans le secret store de votre CI.
Signature Android
Créer le keystore d’upload
Si l’app est déjà sur Google Play, réutilisez le keystore existant. La signature d’une mise à jour avec une clé différente est refusée, sauf si vous passez par la réinitialisation de la clé d’upload dans Play Console.
Pour une nouvelle application :
keytool -genkeypair -v \
-storetype PKCS12 \
-keystore release.jks \
-alias upload \
-keyalg RSA -keysize 2048 \
-validity 10000
Notes :
- Google Play exige que la clé soit valide jusqu’au 22 octobre 2033 au minimum.
-validity 10000(environ 27 ans) couvre cette exigence. - Avec le type de store PKCS12, le mot de passe de la clé est identique au mot de passe du store.
- Pas de JDK sous la main ? Le générateur de keystore Android en ligne génère le même fichier dans le navigateur.
Play App Signing et la clé d’upload
Les nouvelles applications sur Google Play utilisent Play App Signing. Google détient la clé de signature de l’application et re-signe ce que les utilisateurs téléchargent. Votre keystore est la clé d'upload. Si vous la perdez, le support de Play Console peut enregistrer une nouvelle clé d’upload : sa perte est donc un retard, pas une catastrophe. Sauvegardez-la quand même.
Compte de service pour les uploads
Pour uploader depuis le cloud, créez un compte de service dans Google Cloud, activez l’API Google Play Android Developer API, téléchargez sa clé JSON et invitez le compte de service dans Play Console sous Utilisateurs et permissions avec les permissions de release pour votre application. L’onboarding de Capgo peut le faire via la connexion Google, comme indiqué ci-dessous.
Signature iOS
Les trois éléments Apple
- Certificat Apple Distribution. Un par équipe suffit, valable un an. Apple en limite le nombre, donc n’en créez pas un par développeur.
- Profil de provisionnement. Il associe le bundle ID, le certificat et les capacités comme les notifications push. Utilisez un App Store Connect profil pour TestFlight et l'App Store, et un Ad Hoc profil pour les installations sur les appareils enregistrés. Chaque extension d'app (widget, share extension, service de notification) nécessite son propre profil.
- Clé API App Store Connect. Créée dans Utilisateurs et accès > Intégrations avec un accès App Manager. Le
.p8fichier ne se télécharge qu'une seule fois.
Vous devez avoir les droits admin ou de titulaire du compte sur l'équipe Apple Developer pour les créer.
Créer un certificat sans Mac
La procédure Keychain Access nécessite macOS, mais OpenSSL fonctionne partout :
# 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
Le -legacy le flag est crucial avec OpenSSL 3 : sans lui, les machines de build macOS peuvent échouer à importer le .p12 avec « MAC verification failed ». L'interface basée sur le navigateur Générateur de certificats iOS effectue les mêmes étapes si vous préférez ne pas utiliser le terminal.
Ensuite, créez le profil de provisionnement dans le portail développeur (Profils > + > App Store Connect), sélectionnez votre App ID et le nouveau certificat, puis téléchargez-le.
Configurer la signature avec Capgo Build
Build Capgo compile et signe les apps Capacitor sur des machines gérées par Capgo, ce qui vous permet de compiler iOS depuis Windows ou Linux. Commencez par vous connecter et enregistrer l'app :
bunx @capgo/cli@latest login
bunx @capgo/cli@latest app add
Option A : onboarding guidé (recommandé)
bunx @capgo/cli@latest build init --platform ios
bunx @capgo/cli@latest build init --platform android
Sur iOS, l'onboarding crée ou réutilise le certificat de distribution et le profil de provisionnement App Store avec votre clé API App Store Connect. Sur macOS, il peut également vous guider dans la création de cette clé API. Sur Android, il crée ou importe le keystore et peut provisionner le compte de service Google Cloud et l'invitation Play Console via la connexion Google. À la fin, il propose de lancer le premier build.
Option B : conserver les fichiers existants
Si vous avez déjà les fichiers des sections précédentes :
# 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
Pour les apps avec des extensions, répétez --ios-provisioning-profile avec un bundleId=path le mapping pour chaque cible :
--ios-provisioning-profile com.example.app=./App.mobileprovision \
--ios-provisioning-profile com.example.app.widget=./Widget.mobileprovision
Les identifiants sont stockés dans ~/.capgo-credentials/credentials.json, indexés par ID d'app et plateforme. Ajoutez --local pour les stocker dans .capgo-credentials.json dans le projet à la place, et ajoutez ce fichier à .gitignore. Vérifiez ce qui est enregistré avec bunx @capgo/cli@latest build credentials list.
Déclencher un build signé
Préparez le projet natif, puis lancez le build :
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
Les logs s’affichent dans votre terminal. Un scan pré-build vérifie l’expiration des certificats, les mots de passe et l’appariement des profils avant tout upload, ce qui permet de détecter la plupart des erreurs de signature en quelques secondes plutôt qu’en minutes. Lancez-le seul avec bunx @capgo/cli@latest build prescan --platform ios.
Variantes utiles :
| Objectif | Options |
|---|---|
| Build de test sur des iPhones enregistrés | --ios-distribution ad_hoc --ios-provisioning-profile ./adhoc.mobileprovision --output-upload |
| APK pour appareils MDM ou kiosque | --platform android --no-playstore-upload --output-upload |
| Soumettre directement à l’App Review | --submit-to-store-review --store-release-name 2.4.0 |
| Conserver votre propre numéro de build | --skip-build-number-bump |
| Build propre sans cache | --no-cache |
Pour les builds ad hoc, collectez d’abord les UDIDs des appareils avec le Recherche d'UDID iOS et ajoutez-les au profil.
Automatiser les builds signés en CI
En CI, passez les identifiants via des variables d’environnement plutôt qu’un fichier d’identifiants. Le CLI exporte exactement ce dont vous avez besoin :
bunx @capgo/cli@latest build credentials manage --appId com.example.app
# choose "Export to .env"
Sur GitHub, envoyez chaque ligne dans les secrets du dépôt en une seule commande, puis supprimez le fichier :
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
Un workflow de release qui signe et publie les deux plateformes sur un tag :
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 }}
Le job s’exécute sur Linux. Aucun runner macOS, aucune commande keychain, pas de fastlane. Les mêmes variables d’environnement fonctionnent dans n’importe quel CI : variables GitLab CI/CD, variables sécurisées Bitbucket, secrets Gitea ou groupes de variables Azure DevOps. Tutoriels par plateforme : Bitbucket Pipelines, Gitea Actions, et le Docs GitHub Actions.
Gestion de vos clés
Une question légitime avant de confier vos clés de signature à un service cloud. Avec Capgo Build :
- Les identifiants restent sur votre machine (
~/.capgo-credentials/) ou dans le coffre-fort de secrets de votre CI. Capgo ne conserve pas de coffre de vos clés. - Pour chaque build, le CLI les transmet via HTTPS. Elles ne sont utilisées que pendant ce build et supprimées à sa fin.
- Seul le projet natif préparé est envoyé. Votre code source web,
.git, et.envLes fichiers ne le sont pas. - Les apps compilées sont envoyées directement à App Store Connect ou Google Play, ou vers un lien de téléchargement à durée limitée si vous en demandez un.
Le compromis : la rotation d’un identifiant exige de mettre à jour vos secrets CI vous-même. Réexportez avec build credentials manage et poussez à nouveau le fichier.
Expiration et rotation
| Élément | À vie | Que faire |
|---|---|---|
| Certificat Apple Distribution | 1 an | Créer un nouveau, régénérer les profils, réenregistrer, mettre à jour la CI |
| Profil de provisionnement | 1 an, ou jusqu’à révocation du certificat | Régénérer et réenregistrer |
| Clé API App Store Connect | Jusqu’à révocation | Révoquer quand quelqu’un ayant accès quitte l’équipe |
| Keystore d’upload Android | Tant que sa validité le permet (fixez-l’à plusieurs décennies) | Back it up; reset via Play Console if lost |
| Clé du compte de service Play | Jusqu'à suppression | À faire chaque année ou en cas de changement d’accès |
Notez les dates Apple dans un calendrier partagé. Un certificat expiré n'affecte pas les apps déjà sur les appareils des utilisateurs, mais bloque tout nouveau build.
Troubleshooting
| Erreur | Cause et solution |
|---|---|
Provisioning profile doesn't include signing certificate |
Le profil a été généré pour un autre certificat. Régénérez-l’avec le certificat actuel. |
Provisioning profile doesn't match bundle ID |
Profil créé pour un autre app ID ou manquant une cible d'extension. Ajoutez un bundleId=path mapping pour chaque cible. |
MAC verification failed |
Incorrect .p12 mot de passe, ou export OpenSSL 3 sans -legacy. |
Keystore was tampered with, or password was incorrect |
Mauvais mot de passe du store, ou fichier corrompu par des sauts de ligne base64. |
Key alias not found |
L’alias diffère de celui du keystore. Listez-l’avec keytool -list -keystore release.jks. |
| Échec de l'authentification App Store Connect | ID de clé ou ID d’émetteur incorrect, clé révoquée, ou horloge système déréglée sur la machine qui signe le token. |
| Upload Play : l’appelant n’a pas la permission | Compte de service non invité dans Play Console, ou le développeur Android API n’est pas activé. |
D’autres correctifs sont dans Guide de dépannage des builds Capgo et CI/CD pour Capacitor : les pièges courants.
Après le premier build signé
Les builds natifs signés ne sont nécessaires que lorsque le code natif change. Pour les modifications JavaScript, CSS et HTML, déployez un live update pour installer les apps à la place et réserver les builds du store aux releases touchant aux plugins ou à la configuration native. Si vous venez d'une configuration sur Mac, Compilez une app iOS depuis Windows avec Capgo Build présente le workflow complet sans macOS.