Linux es un entorno ideal para desarrollar apps con Capacitor, y Android funciona sin problemas. iOS es la excepción: Xcode y las herramientas de firma de Apple solo corren en macOS. La solución no es tener un Mac mini bajo el escritorio, sino generar el proyecto iOS localmente y compilarlo en la nube sobre macOS.
Esta guía es la versión para Linux de Crea una app iOS desde Windows con Capacitor y Capgo Build. Cubre los aspectos que varían en Linux: certificados OpenSSL, el shell de Linux y el CI desde runners de Linux.
La división del trabajo
Una app Capacitor tiene dos builds:
- Build web: el output de tu framework en
dist/. Hecho en Linux. - Native Build: archive de Xcode, firma y subida. Hecho por Build de Capgo en máquinas con Apple Silicon que ejecuten la versión actual de macOS y Xcode.
CLI sube el preparado ios/ proyecto desde tu máquina. No hace falta subir nada a un host de Git, y ninguna credencial de registro privado sale de tu equipo, ya que las instalaciones de dependencias y cap sync ocurre localmente antes de la subida.
Requisitos
- Una app Capacitor que compila localmente (cualquier framework).
- Node 20+ o Bun en Linux.
- Una membresía de Apple Developer Program.
- OpenSSL (instalado por defecto en casi todas las distros).
- Una cuenta de Capgo y la app registrada en
bunx @capgo/cli@latest app add.
1) Generar el proyecto iOS en Linux
bun add @capacitor/core @capacitor/ios
bun add -d @capacitor/cli
bunx cap init
bun run build
bunx cap add ios
Verás algo como esto Skipping pod install because CocoaPods is not installed. Es normal. La ios/ carpeta existe y debe subirse al repo; contiene tu bundle ID, Info.plist, iconos y ajustes nativos.
2) Sincronizar assets web antes de cada build
bun run build
bunx cap sync ios
cap sync copia dist/ en ios/App/App/public y actualiza las referencias de los plugins. Capgo compila lo que hay en ios/, por lo que un proyecto sin sincronizar enviará tu UI anterior.
3) Crear material de firma sin un Mac
Necesitas tres cosas: un certificado de Apple Distribution como .p12, un perfil de provisioning de App Store y una clave API de App Store Connect. Ninguno requiere Keychain Access.
Certificado de Distribution con OpenSSL
openssl genrsa -out ios_distribution.key 2048
openssl req -new -key ios_distribution.key -out ios_distribution.csr \
-subj "/emailAddress=you@example.com/CN=Your Name/C=US"
Subir ios_distribution.csr en Certificates, Identifiers & Profiles, elige Apple Distribution y descarga distribution.cer. Convertir y empaquetar:
openssl x509 -in distribution.cer -inform DER -out distribution.pem -outform PEM
openssl pkcs12 -export -inkey ios_distribution.key -in distribution.pem \
-out ios_distribution.p12 -legacy
El -legacy flag es importante con OpenSSL 3. Sin ella, las herramientas de Apple rechazan el .p12 con un error de contraseña inválida incluso cuando la contraseña es correcta. Si prefieres no tocar OpenSSL, el generador de certificados iOS hace lo mismo en el navegador.
Perfil de aprovisionamiento y clave API
En el portal de Apple Developer, crea un perfil de App Store para tu bundle ID usando el nuevo certificado y descarga el .mobileprovision. En App Store Connect, crea una clave API con el rol App Manager y descarga la .p8; anota el Key ID y el Issuer ID. El guía de build de iOS muestra cada pantalla.
¿Quieres inspeccionar un perfil en Linux? openssl smime -inform der -verify -noverify -in profile.mobileprovision imprime el plist embebido.
4) Guarda las credenciales en Capgo
bunx @capgo/cli@latest login
bunx @capgo/cli@latest build credentials save \
--platform ios \
--apple-team-id "TEAMID" \
--apple-key ./AuthKey_KEYID.p8 \
--apple-key-id "KEYID" \
--apple-issuer-id "issuer-uuid" \
--certificate ./ios_distribution.p12 \
--ios-provisioning-profile ./App_Store.mobileprovision
O ejecuta bunx @capgo/cli@latest build init --platform ios para la versión guiada. En Linux, el paso de la clave de App Store Connect es manual; todo lo demás se solicita mediante prompts.
Si Apple rechaza la clave con un error de autenticación, sincroniza tu reloj. El JWT se firma con la hora local y Apple rechaza tokens con mucha deriva:
timedatectl status
sudo timedatectl set-ntp true
5) Solicitar el build
bun run build
bunx cap sync ios
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
El preparado ios/ proyecto se sube, Capgo ejecuta pod install, archiva con Xcode, firma con tu certificado y envía los logs a tu terminal. Con la clave API configurada, el build se envía a TestFlight al terminar. Instala la app TestFlight en un iPhone para ejecutarlo.
Los builds que fallan pueden diagnosticarse automáticamente añadiendo --ai-analytics; el diagnóstico de build con IA lee el log de Xcode y explica la solución.
6) Builds ad hoc para testers sin TestFlight
Para un dispositivo de QA registrado por UDID, usa un perfil Ad Hoc y guarda el IPA como un artifact:
bunx @capgo/cli@latest build request com.example.app \
--platform ios \
--ios-distribution ad_hoc \
--output-upload
El CLI genera un enlace de descarga con tiempo limitado. Añade --output-record build.json para guardar el enlace y un code QR para un tester.
7) Automatiza desde un runner de CI en Linux
Los mismos comandos funcionan en cualquier CI de Linux. Un ejemplo de GitHub Actions:
name: iOS build
on:
workflow_dispatch:
jobs:
ios:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun run build
- run: bunx cap sync ios
- run: bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
Las credenciales del paso 4 se guardan en Capgo, así que el runner solo necesita el token. Alternativamente, exporta un CI .env con bunx @capgo/cli@latest build credentials manage y pasa los valores como secrets; consulta la gestión de credenciales.
8) Iteración diaria sin Native Build
Una vez que el build de TestFlight existe, la mayoría de los cambios son web. Súbelos con Live Updates de Capgo:
bun run build
bunx @capgo/cli@latest bundle upload --channel production
Reserva build request para añadir plugins, cambiar permisos, iconos o Capacitor.
Problemas en Linux
- Olvidaste
cap sync ios: el IPA muestra la UI antigua. Haz sync antes de cada petición. ios/en.gitignore: CLI sube desde el disco y compila, pero tu equipo y la CI no tendrán el proyecto nativo. Haz commit..p12contraseña rechazada: regenera con-legacy.- Error de autenticación de Apple: desincronización de reloj. Activa NTP.
- Plugin añadido, pero olvidaste el rebuild nativo: añadir un plugin Capacitor cambia el binario nativo. Ejecuta un nuevo cloud build y envíalo a la tienda antes de lanzar cambios web que lo utilicen.
Resumen
Linux no puede ejecutar Xcode, pero no lo necesita. Genera ios/ con Capacitor, crea certificados con OpenSSL y deja que Capgo Build compile, firme y envíe a TestFlight. Con Live Updates para la capa web, un equipo que solo usa Linux lanza iOS con la misma rutina que Android. Para la configuración completa del entorno, lee desarrollo con Capacitor en Linux.