Qué significa distribuir directamente con Developer ID
Hay básicamente dos caminos para hacer llegar una app de macOS a los usuarios. Uno es a través de la Mac App Store (MAS), y el otro es la distribución directa (direct distribution), en la que el desarrollador permite descargar un archivo .dmg (o .app) creado por él mismo desde una web o desde un sitio como GitHub.
La distribución directa tiene ventajas claras. No hay que esperar a la revisión de la App Store, no hay comisiones de pago y puedes publicar las actualizaciones en el momento y de la forma que quieras. A cambio, las tareas que la App Store gestionaba por ti — la firma de código, la notarización (notarization) y las actualizaciones automáticas — tienes que prepararlas tú mismo.
Si no preparas estas tareas, el mecanismo de seguridad de macOS, Gatekeeper, impedirá que la app se ejecute. Cuando el usuario abra la app por primera vez verá un aviso del tipo “no se puede abrir porque es una app distribuida por un desarrollador no verificado”, y la mayoría de los usuarios abandonará la instalación ahí mismo. Para que la app se abra con un simple doble clic, como cualquier app distribuida correctamente, tienes que firmar la app con un certificado Developer ID y conseguir la notarización de Apple.
Esta serie trata ese proceso de configuración inicial. Una buena noticia es que la mayor parte de la configuración que veremos aquí solo hay que hacerla una vez y luego se reutiliza en todas las versiones.
Qué vamos a construir en esta serie
A lo largo de 3 partes tendrás listo lo siguiente.
- (Parte 1, este artículo) Certificado Developer ID Application + credenciales para la notarización
- (Parte 2) Clave de firma EdDSA para las actualizaciones automáticas con Sparkle
- (Parte 3) Repositorio público para alojar el feed de actualizaciones + ajustes de compilación finales
Al terminar la serie deberías tener en mano lo siguiente. Por ahora basta con echar un vistazo a la lista; los iremos completando uno a uno en cada parte.
- Certificado
Developer ID Applicationen el Keychain de macOS - Perfil de credenciales para la notarización guardado en el Keychain
- Par de claves EdDSA para firmar las actualizaciones de Sparkle (clave pública + clave privada)
- Copia de seguridad de la clave privada en un lugar seguro
- Repositorio público de GitHub + GitHub Pages para subir el feed de actualizaciones (appcast)
- Archivo de ajustes de compilación (
ExportOptions.plist) y configuración del lado de la app
App de ejemplo — FocusTimer
Esta serie usa como ejemplo una app de macOS ficticia, FocusTimer (una app de temporizador sencilla para gestionar el tiempo de concentración). Los valores que aparecen en los comandos y rutas como FocusTimer, el identificador de paquete com.example.FocusTimer, el dominio example.com, el nombre del certificado, el Team ID, etc. son todos valores de ejemplo. Cuando lo apliques de verdad, sustitúyelos por el nombre de tu app y los datos de tu cuenta.
Este artículo está escrito tomando como referencia Xcode 26 y Sparkle 2.x (el framework de actualizaciones automáticas, que aparecerá en la Parte 2). Apple cambia con frecuencia la disposición de las pantallas y la ubicación de los menús, así que aunque el nombre de algún botón sea un poco distinto, puedes dar por hecho que el flujo es el mismo.
Preparativos previos — herramientas de línea de comandos
Primero instalamos dos herramientas de línea de comandos necesarias para automatizar la compilación y la publicación. Partimos de que ya tienes instalado el gestor de paquetes de macOS Homebrew.
brew install gh create-dmg
gh— el CLI oficial de GitHub. Lo usaremos más adelante para crear un GitHub Release.create-dmg— una herramienta para crear la imagen de disco.dmgde distribución. También genera la pantalla que indica al usuario que arrastre la app a la carpetaApplications.
Aunque no las usemos ahora mismo, conviene instalarlas con antelación, ya que muchas veces los scripts de automatización de publicación están diseñados para comprobar primero que estas herramientas existen y detenerse de inmediato si faltan.
Paso 1 — Verificar el Apple Developer Program
Para emitir un certificado Developer ID y notarizar la app necesitas una membresía del Apple Developer Program. Es un programa de pago de 99 $ al año para una cuenta personal.
Si ya estás suscrito, solo tienes que comprobar que está activa.
- Entra en developer.apple.com/account
- En la sección Membership details, comprueba que el estado sea Active
- En esa misma pantalla, anota tu Team ID (en el ejemplo,
ABCDE12345). Lo usarás continuamente en los pasos siguientes.
Si aún no estás suscrito, la membresía suele tardar alrededor de un día en aprobarse. No es posible emitir el certificado antes de la aprobación, así que conviene resolver esto lo primero de todo.
Paso 2 — Emitir el certificado Developer ID Application
El certificado Developer ID Application es el certificado que se usa para firmar el .app y el .dmg que vas a distribuir. Gatekeeper de macOS reconoce las apps firmadas con este certificado como “apps creadas por un desarrollador conocido”.
Apple tiene también, por separado, un certificado Developer ID Installer para firmar paquetes de instalación
.pkg. Como esta serie distribuye con.dmg, solo trataremos el certificado Application.
Procedimiento de emisión
La forma más sencilla es hacerlo a través de Xcode.
- Abre Xcode → menú Xcode → Settings… (
⌘,) - Selecciona la pestaña Accounts → haz clic en tu Apple ID en la lista de la izquierda
- Haz clic en el botón Manage Certificates… abajo a la derecha
- Haz clic en el botón
+abajo a la izquierda de la ventana que se abre - Selecciona Developer ID Application en el menú
- Cuando, tras 1 o 2 segundos, aparezca el nuevo certificado en la lista, pulsa Done
El certificado emitido de esta forma se guarda automáticamente en el Keychain de macOS. El certificado y la clave privada que le corresponde se guardan como un par, y necesitas esa clave privada para poder firmar.
Comprobar la emisión
En la terminal, comprueba con el siguiente comando que el certificado ha entrado correctamente.
security find-identity -v -p codesigning | grep "Developer ID Application"
Si aparece una línea como la siguiente, ha funcionado.
1) A1B2C3D4E5F6... "Developer ID Application: Gildong Hong (ABCDE12345)"
La cadena entre comillas es el nombre oficial del certificado. Gildong Hong es el nombre registrado en la cuenta de Apple, y ABCDE12345 entre paréntesis es el Team ID que anotaste en el Paso 1. Este nombre se usará tal cual más adelante al automatizar la firma de código, así que conviene verificarlo una vez más.
Renovar el certificado
El periodo de validez del certificado Developer ID es de 5 años. Cuando se acerque la caducidad, aparecerá marcado como Expired en la lista Manage Certificates de Xcode. En ese momento basta con emitir un nuevo certificado siguiendo exactamente el mismo procedimiento de arriba.
La buena noticia es que las apps ya firmadas y distribuidas con el certificado anterior no quedan invalidadas en el instante en que este caduca. Solo tienes que firmar con el nuevo certificado las compilaciones que crees a partir de ese momento. Así que no hace falta preocuparse en exceso por la caducidad.
Paso 3 — Registrar una contraseña específica de la app para la notarización
Qué es la notarización (notarization)
La notarización es el procedimiento de subir la app a los servidores de Apple antes de distribuirla para que se someta a un análisis de malware. Si pasa el análisis, Apple emite un “ticket de notarización”, y ese ticket debe estar adjunto a la app para que Gatekeeper la abra sin avisos. Si la firma demuestra “quién la creó”, la notarización es un procedimiento aparte que demuestra “que Apple la ha analizado una vez”.
Para enviar la notarización se usa el comando notarytool de Apple, que pide la contraseña del Apple ID cada vez que envías. Para no tener que escribirla cada vez, se crea una contraseña específica de la app (App-Specific Password) y se guarda de antemano en el Keychain.
3-1. Emitir la contraseña específica de la app
La contraseña específica de la app es una contraseña de 16 caracteres que se usa solo para un fin concreto, en lugar de la contraseña principal del Apple ID.
- Entra en appleid.apple.com → inicia sesión con el Apple ID suscrito al Apple Developer Program (en el ejemplo,
[email protected]) - Selecciona Inicio de sesión y seguridad (Sign-In and Security) → Contraseñas de aplicación (App-Specific Passwords)
- Botón
+→ escribe un nombre para la contraseña (por ejemplo,focustimer-notarize) - Crear (Create) → vuelve a escribir la contraseña del Apple ID
- En la pantalla se muestra una contraseña de 16 caracteres con el formato
abcd-efgh-ijkl-mnop.
Una vez que cierres esta pantalla no podrás volver a ver la contraseña. Antes de pasar al siguiente paso, cópiala un momento en un gestor de contraseñas o similar.
3-2. Guardarla en un perfil de notarytool
Guardamos la contraseña emitida como un perfil del Keychain. En el comando de abajo, sustituye el valor de --password por la contraseña real que acabas de recibir antes de ejecutarlo.
xcrun notarytool store-credentials "focustimer-notarize" \
--apple-id "[email protected]" \
--team-id "ABCDE12345" \
--password "abcd-efgh-ijkl-mnop"
- Primer argumento
"focustimer-notarize"— el nombre que le pondrás a este perfil. A partir de ahora cargarás las credenciales con este nombre al notarizar. --apple-id— el correo electrónico de la cuenta del Apple Developer Program--team-id— el Team ID del Paso 1--password— la contraseña específica de la app emitida en 3-1
Si aparece la siguiente salida, ha funcionado.
Credentials saved to Keychain.
Ahora que las credenciales están guardadas en el Keychain, ya no necesitas la contraseña específica de la app original. (Eso sí, si tienes pensado compilar también desde otro ordenador, es más cómodo conservarla en un gestor de contraseñas.)
3-3. Comprobación
Comprobamos que el perfil guardado funciona realmente.
xcrun notarytool history --keychain-profile "focustimer-notarize"
Si aparece el mensaje Successfully received submission history., todo está correcto. El historial de envíos que aparece debajo puede estar vacío (es normal, porque aún no has notarizado nada) o puede contener registros anteriores.
Un escollo clave — la cuenta de Apple ID y la de GitHub son distintas
Es el punto donde más a menudo se atasca quien configura la distribución directa por primera vez.
- Cuenta del Apple Developer Program — se usa para emitir certificados y para la notarización (ejemplo:
[email protected]) - Cuenta de GitHub — se usa en la Parte 3 para alojar los archivos de actualización (ejemplo:
[email protected])
Es habitual que estas dos sean correos electrónicos distintos. En particular, en --apple-id de notarytool store-credentials debes poner sí o sí el correo de la cuenta de Apple Developer. Si pones el correo de la cuenta de GitHub, la autenticación falla, y como el mensaje de error no es muy claro, cuesta encontrar la causa.
Si te resulta fácil confundir los correos de las dos cuentas, te recomendamos anotar cuál es para Apple y cuál para GitHub. Esta distinción aparece repetidamente a lo largo de toda la serie.
Resumen de la Parte 1
Si has seguido hasta aquí, ahora ya tienes lo siguiente.
- ✅ Herramientas de línea de comandos para automatizar la publicación (
gh,create-dmg) - ✅ Membresía activa del Apple Developer Program
- ✅ Certificado Developer ID Application guardado en el Keychain
- ✅ Perfil de credenciales para la notarización guardado en el Keychain (
focustimer-notarize)
Con esto ya tienes todo listo para firmar y notarizar la app. Pero casi ninguna app se entrega una sola vez al usuario y se acabó. Hay que seguir publicando nuevas versiones que corrigen errores y añaden funciones. En la App Store las actualizaciones automáticas se gestionan solas, pero en la distribución directa esto también hay que prepararlo uno mismo.
En la siguiente parte crearemos la clave de firma EdDSA para Sparkle, el framework de actualizaciones automáticas que es prácticamente el estándar de las apps de macOS. Es un mecanismo de verificación específico para los archivos de actualización, distinto del certificado.