Saltar al contenido principal
Tutorial Nube Seguridad

Cómo firmar y hacer el build de una app Capacitor en la nube

Firma y haz el build de tu app Capacitor en la nube: crea el keystore de Android y el certificado de iOS, guarda las credenciales de forma segura y ejecuta builds firmados desde CI.

Certificados de iOS y keystore de Android para firmar una app de Capacitor en un build en la nube

Para firmar y compilar una app de Capacitor en la nube, creas tu material de firma una sola vez (un keystore de Android, un certificado de distribución de iOS y un perfil de aprovisionamiento), lo proporcionas a un servicio de build en la nube y luego inicias los builds desde tu terminal o CI. El servicio compila el proyecto nativo, lo firma y puede subirlo directamente a TestFlight o Google Play. Esta guía cubre cada archivo de firma, cómo crearlo sin un Mac, cómo configurarlo con Capgo Build y cómo automatizar builds firmados de forma segura.

Qué significa “firmar en la nube”

Ambas tiendas solo aceptan binarios firmados. La firma demuestra que el build viene de ti y que nadie lo ha modificado después. Localmente, Xcode y Android Studio ocultan casi todo esto. En la nube, nada es implícito, así que debes saber exactamente qué archivos intervienen:

Plataforma Archivo Qué es Para qué sirve
Android .jks / .keystore Keystore que contiene tu upload key Firmar el AAB o APK
Android Cuenta de servicio .json Credenciales de Google Cloud Subir a Google Play
iOS .p12 Certificado Apple Distribution y clave privada Firma del IPA
iOS .mobileprovision Provisioning profile que vincula bundle ID, certificado y capabilities Permite que la app se ejecute y se distribuya
iOS .p8 + ID de clave + ID de emisor Clave API de App Store Connect Subida a TestFlight y lectura de números de build

No los subas a Git. Todo lo que sigue los guarda en tu archivo de credenciales local o en el secret store de tu CI.

Firma de Android

Crear el keystore de upload

Si la app ya está en Google Play, reutiliza el keystore existente. Firmar una actualización con una clave diferente se rechaza a menos que realices el reset de la clave de upload en Play Console.

Para una app nueva:

keytool -genkeypair -v \
  -storetype PKCS12 \
  -keystore release.jks \
  -alias upload \
  -keyalg RSA -keysize 2048 \
  -validity 10000

Notas:

  • Google Play exige que la clave sea válida al menos hasta el 22 de octubre de 2033. -validity 10000 (unos 27 años) cubre ese requisito.
  • Con el tipo de almacén PKCS12, la contraseña de la clave es la misma que la del almacén.
  • ¿No tienes un JDK a mano? El Generador de keystore para Android genera el mismo archivo en el navegador.

Play App Signing y la clave de carga

Las nuevas apps en Google Play usan Play App Signing. Google guarda la clave de firma de la app y vuelve a firmar lo que los usuarios descargan. Tu keystore es el subir clave. Si lo pierdes, el soporte de Play Console puede registrar una nueva clave de carga, por eso perderla es un retraso, no un desastre. Aun así, haz una copia de seguridad.

Cuenta de servicio para subidas

Para subir desde la nube, crea una cuenta de servicio en Google Cloud, habilita la API de Google Play Android Developer, descarga su clave JSON e invita a la cuenta de servicio en Play Console, en Usuarios y permisos con permisos de lanzamiento para tu app. El onboarding de Capgo puede hacerlo mediante Google sign-in, como se muestra abajo.

Firma de iOS

Los tres elementos de Apple

  • Certificado de Apple Distribution. Con uno por equipo es suficiente, válido por un año. Apple limita cuántos puedes tener, así que no crees uno por cada desarrollador.
  • Perfil de aprovisionamiento. Vincula el bundle ID, el certificado y las capacidades, como las notificaciones push. Usa un App Store Connect perfil para TestFlight y la App Store, y un Ad Hoc perfil para instalaciones en dispositivos registrados. Cada extensión de la app (widget, extensión de compartir, servicio de notificaciones) necesita su propio perfil.
  • clave de App Store Connect API. Creada bajo Usuarios y acceso > Integraciones con acceso de App Manager. El .p8 archivo solo se descarga una vez.

Necesitas permisos de administrador o titular de la cuenta en el equipo de Apple Developer para crearlos.

Crear un certificado sin un Mac

El flujo de Keychain Access requiere macOS, pero OpenSSL funciona en cualquier lugar:

# 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

El -legacy el flag importa con OpenSSL 3: sin él, las máquinas de build de macOS pueden fallar al importar el .p12 con “MAC verification failed”. El basado en navegador generador de certificados iOS hace los mismos pasos si prefieres no usar una terminal.

Luego crea el perfil de aprovisionamiento en el portal de desarrollador (Perfiles > + > App Store Connect), selecciona tu app ID y el nuevo certificado, y descárgalo.

Configura la firma con Capgo Build

Build de Capgo compila y firma apps de Capacitor en máquinas gestionadas por Capgo, para que puedas hacer build de iOS desde Windows o Linux. Comienza iniciando sesión y registrando la app:

bunx @capgo/cli@latest login
bunx @capgo/cli@latest app add
bunx @capgo/cli@latest build init --platform ios
bunx @capgo/cli@latest build init --platform android

En iOS, el onboarding crea o reutiliza el certificado de distribución y el perfil de aprovisionamiento de App Store con tu clave de App Store Connect API. En macOS también puede guiarte para crear esa clave API. En Android, crea o importa el keystore y puede aprovisionar la cuenta de servicio de Google Cloud y la invitación de Play Console mediante el inicio de sesión de Google. Al final, ofrece iniciar el primer build.

Opción B: guardar archivos existentes

Si ya tienes los archivos de las secciones anteriores:

# 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

Para apps con extensiones, repite --ios-provisioning-profile con un bundleId=path mapping para cada target:

  --ios-provisioning-profile com.example.app=./App.mobileprovision \
  --ios-provisioning-profile com.example.app.widget=./Widget.mobileprovision

Las credenciales se almacenan en ~/.capgo-credentials/credentials.json, indexadas por app ID y plataforma. Añade --local para almacenarlas en .capgo-credentials.json en el proyecto en su lugar, y añade ese archivo a .gitignore. Revisa lo que se guarda con bunx @capgo/cli@latest build credentials list.

Lanzar un build firmado

Prepara el proyecto nativo y luego solicita el 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

Los logs llegan a tu terminal. Un escaneo previo al build comprueba la caducidad de los certificados, las contraseñas y el emparejamiento de perfiles antes de subir nada, así que la mayoría de los errores de firma fallan en segundos en lugar de minutos. Ejecútalo por separado con bunx @capgo/cli@latest build prescan --platform ios.

Variaciones útiles:

Objetivo Flags
Build de prueba en iPhones registrados --ios-distribution ad_hoc --ios-provisioning-profile ./adhoc.mobileprovision --output-upload
APK para MDM o dispositivos kiosk --platform android --no-playstore-upload --output-upload
Enviar directamente a App Review --submit-to-store-review --store-release-name 2.4.0
Conservar tu propio número de build --skip-build-number-bump
Build limpio sin caché --no-cache

Para builds ad hoc, recopila primero los UDIDs de los dispositivos con el Buscador de UDID de iOS y añádelos al perfil.

Automatizar builds firmados en CI

En CI, pasa las credenciales como variables de entorno en lugar de un archivo de credenciales. CLI exporta exactamente lo que necesitas:

bunx @capgo/cli@latest build credentials manage --appId com.example.app
# choose "Export to .env"

En GitHub, sube cada línea a los secrets del repositorio con un solo comando y luego elimina el archivo:

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 que firma y publica ambas plataformas al crear una 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 }}

El job se ejecuta en Linux. Sin runner de macOS, sin comandos de keychain, sin fastlane. Las mismas variables de entorno funcionan en cualquier CI: variables de GitLab CI/CD, variables seguras de Bitbucket, secrets de Gitea o grupos de variables de Azure DevOps. Guías específicas por plataforma: Bitbucket Pipelines, Gitea Actions, y la Docs de GitHub Actions.

Cómo se gestionan tus claves

Una pregunta justa antes de entregar tus claves de firma a cualquier servicio cloud. Con Capgo Build:

  • Las credenciales residen en tu máquina (~/.capgo-credentials/) o en tu almacén de secretos de CI. Capgo no guarda tus claves en un vault.
  • En cada build, CLI las envía por HTTPS. Solo se usan durante ese build y se borran al terminar.
  • Solo se sube el proyecto nativo preparado. Tu código web, .git, y .env los archivos no.
  • Las apps compiladas van directamente a App Store Connect o Google Play, o a un enlace de descarga temporal si lo solicitas.

La contrapartida: rotar una credencial implica actualizar tus secretos de CI manualmente. Re-exporta con build credentials manage y vuelve a subir el archivo.

Expiración y rotación

Elemento De por vida Qué hacer
Certificado Apple Distribution 1 año Crear uno nuevo, regenerar perfiles, volver a guardar, actualizar CI
Perfil de aprovisionamiento 1 año, o hasta que se revoque su certificado Regenerar y volver a guardar
Clave API de App Store Connect Hasta que se revoque Revocar cuando alguien con acceso se vaya
Keystore de subida de Android Mientras sea válido (configúralo en décadas) Haz backup; si se pierde, resetéalo desde Play Console
Clave de cuenta de servicio de Play Hasta que se elimine Rótala cada año o cuando cambie el acceso

Anota las fechas de Apple en un calendario compartido. Un certificado expirado no afecta a las apps ya instaladas, pero bloquea cada nuevo build.

Solución de problemas

Error Causa y solución
Provisioning profile doesn't include signing certificate El perfil se generó para otro certificado. Regenéralo con el actual.
Provisioning profile doesn't match bundle ID Perfil creado para otro ID de app o falta un target de extensión. Añade un bundleId=path mapeo para cada destino.
MAC verification failed Incorrecto .p12 contraseña, o exportación de OpenSSL 3 sin -legacy.
Keystore was tampered with, or password was incorrect Contraseña del keystore incorrecta, o el archivo se corrompió por saltos de línea en base64.
Key alias not found El alias difiere del que hay en el keystore. Liéstalo con keytool -list -keystore release.jks.
Error de autenticación en App Store Connect Key ID o issuer ID incorrectos, clave revocada o el reloj del sistema desincronizado en la máquina que firma el token.
Play upload: el usuario que llama no tiene permisos La cuenta de servicio no está invitada en Play Console, o el API de Android Developer no está habilitado.

Más soluciones están en la guía de resolución de problemas de Capgo Build y CI/CD para Capacitor: errores comunes.

Tras el primer build firmado

Solo necesitas builds nativos firmados cuando cambian los code nativos. Para cambios en JavaScript, CSS y HTML, envía un live update a las apps instaladas y reserva los builds de tienda para releases que toquen plugins o configuración nativa. Si vienes de un setup con Mac, Compila una app iOS desde Windows con Capgo Build muestra el workflow completo sin macOS.

Live updates para apps Capacitor

Cuando un bug de la capa web está en producción, publica el fix a través de Capgo en lugar de esperar días a la aprobación de la app store. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen el flujo de revisión habitual.

Lo último de nuestro blog

Capgo te da la información clave que necesitas para crear una app móvil realmente profesional.