Cómo configurar GitLab Runner en un Mac para builds de iOS
Para ejecutar jobs de GitLab CI en un Mac, instala el binario oficial gitlab-runner y regístralo con el shell executor. Antes, crea el runner en la configuración de CI/CD de tu proyecto. Eso te da un token glrt-. Luego instálalo como LaunchAgent de usuario y activa el inicio de sesión automático, para que vuelva tras un reinicio. Haz la instalación desde una terminal en el escritorio del Mac, no por SSH, como exige la documentación de GitLab.
Lo que necesitas antes
- Un Mac con Apple silicon, acceso de administrador y Xcode instalado.
- El primer arranque de Xcode hecho. Ejecuta
sudo xcodebuild -runFirstLaunchuna vez si no estás seguro. - Permiso para gestionar runners en tu proyecto o grupo de GitLab.
- Una sesión de escritorio en el Mac, por compartir pantalla o con un monitor. La página de instalación de GitLab para macOS dice que uses una terminal gráfica local, no una sesión SSH.
- La cuenta de macOS que ejecutará los jobs. Inicia sesión en el escritorio con ese usuario.
1. Descarga el binario del runner
GitLab dice que no mantiene la fórmula de Homebrew y recomienda el binario oficial. En Apple silicon, usa la versión arm64. Puede que un Mac recién instalado aún no tenga /usr/local/bin, así que créalo primero.
sudo mkdir -p /usr/local/bin sudo curl --output /usr/local/bin/gitlab-runner \ "https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/latest/binaries/gitlab-runner-darwin-arm64" sudo chmod +x /usr/local/bin/gitlab-runner gitlab-runner --version
2. Crea el runner en GitLab
Los tokens de registro de runner están obsoletos. GitLab tiene previsto eliminarlos en GitLab 20.0. El flujo actual crea primero el runner en la interfaz y luego te da un token de autenticación del runner. Ese token empieza por glrt-.
- En tu proyecto, abre Settings, luego CI/CD, y despliega Runners.
- Selecciona Create project runner y elige macOS.
- En Tags, escribe
macos, xcode. Deja desactivado Run untagged jobs, para que aquí solo lleguen los jobs que piden un Mac. - Selecciona Create runner y copia el token. Solo se muestra un momento.
Ahora las etiquetas viven en el runner, dentro de GitLab. La documentación de GitLab dice que ajustes como --tag-list y --run-untagged solo se pueden fijar al crear el runner, en la interfaz o con la API. Si quieres cambiar las etiquetas después, hazlo desde la página Edit del runner.
3. Regístralo con el shell executor
La página de instalación de GitLab para macOS recomienda el shell executor para builds de iOS y macOS. Los jobs se ejecutan directamente en el Mac, con tu usuario, con Xcode y los simuladores. Regístralo sin preguntas interactivas así:
export RUNNER_TOKEN="glrt-paste-your-token-here" gitlab-runner register \ --non-interactive \ --url "https://gitlab.com/" \ --token "$RUNNER_TOKEN" \ --executor "shell" \ --description "mac-mini-m6"
En GitLab autogestionado, usa la URL de tu instancia. La configuración se guarda en ~/.gitlab-runner/config.toml. GitLab indica que el shell executor está en modo mantenimiento. Sigue recibiendo parches de seguridad, y sigue siendo lo que recomienda la página de macOS para trabajar con Xcode.
4. Instala e inicia el servicio
cd ~ gitlab-runner install gitlab-runner start gitlab-runner status
Esto crea ~/Library/LaunchAgents/gitlab-runner.plist. En macOS el runner es un LaunchAgent de usuario, y GitLab dice que es el único modo soportado. Se ejecuta con tu usuario, no como root. Puede acceder a tu llavero y a tu sesión, que es lo que necesitan el simulador de iOS y la firma de código. Los logs van a ~/Library/Logs/gitlab-runner.out.log y gitlab-runner.err.log.
5. Haz que sobreviva a un reinicio
Un LaunchAgent arranca cuando su usuario inicia sesión y se para al cerrarla. Así que el runner solo vuelve tras un reinicio si ese usuario inicia sesión solo. Por eso la documentación de GitLab dice que actives el inicio de sesión automático. Hazlo en Ajustes del Sistema, en Usuarios y grupos. Luego impide que el Mac se duerma y pruébalo con un reinicio real.
sudo pmset -a sleep 0 sudo shutdown -r now # after it comes back, over SSH: gitlab-runner status
El inicio de sesión automático en un Mac sin pantalla puede fallar sin avisar de varias formas, y una es nueva en macOS 27. Las explicamos en inicio de sesión automático en un Mac sin pantalla.
6. Un .gitlab-ci.yml para una app iOS
Un job solo se ejecuta en un runner si el runner tiene todas las etiquetas que pide el job. Este job pide macos, ejecuta los tests y conserva el result bundle aunque fallen los tests.
stages:
- test
ios_tests:
stage: test
tags:
- macos
script:
- xcodebuild -version
- rm -rf build/TestResults.xcresult
- xcodebuild test -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' -resultBundlePath build/TestResults.xcresult
artifacts:
when: always
paths:
- build/TestResults.xcresult
expire_in: 1 weekLa línea rm -rf importa en una máquina que conserva su copia de trabajo. xcodebuild se niega a sobrescribir un result bundle que ya existe. Lo comprobamos con Xcode 26.6.
Errores comunes y soluciones
Vienen de la sección de resolución de problemas de GitLab para macOS.
"launchctl" failed: Could not find domain for. Ejecutaste install o start por SSH. Abre Terminal en el escritorio del Mac y ejecútalos ahí.FATAL: Failed to start gitlab-runner: exit status 134. El servicio no está bien instalado. Ejecutagitlab-runner uninstall, luego install y luego start, desde el escritorio.killed: 9en Apple silicon. Las carpetas de logs que indica el plist tienen que existir y tu usuario tiene que poder escribir en ellas.Failed to authorize rights (0x1) with status: -60007. EjecutaDevToolsSecurity -enableysudo security authorizationdb remove system.privilege.taskport is-developer.- git fetch se cuelga. Un Git de Homebrew puede añadir un credential helper del llavero. Ejecuta
git config --global --add credential.helper ''con el usuario del runner. - Un job se queda atascado. Sus etiquetas no coinciden con las del runner, o el job no tiene etiquetas y el runner no acepta jobs sin etiquetar.
Por qué ayuda un Mac dedicado
El shell executor reutiliza la misma máquina para cada job. El DerivedData de Xcode, los checkouts de paquetes Swift y las cachés de CocoaPods se quedan en disco entre pipelines. Ahí es donde se va el tiempo. En nuestro benchmark con la app de Wikipedia para iOS en Xcode 26.6, medimos un job típico tras un cambio pequeño. Tardó 27 segundos en un M6 en caliente. El mismo job tardó 269 segundos en un runner macos-26 recién creado de GitHub. Un build limpio tardó 86 segundos frente a 183.
Cuándo bastan los runners de Mac alojados de GitLab
GitLab tiene sus propios runners de macOS. Su documentación, leída en octubre de 2026, los marca como beta. Son para clientes Premium y Ultimate y para programas de código abierto. Los tamaños son un M1 con 4 vCPU y 8 GB, y un M2 Pro con 6 vCPU y 16 GB. Si tienes uno de esos planes y ejecutas unos pocos pipelines al día, los runners alojados te ahorran todos los pasos anteriores.
No elijas un Mac dedicado con shell executor para un proyecto público que ejecuta merge requests no fiables. GitLab avisa de que los jobs de shell pueden leer el código de otros proyectos en la misma máquina. Tampoco elijas MacRun si necesitas una IP fija para listas de acceso, un SLA o más de una región. No ofrecemos nada de eso.
¿Quieres probarlo en nuestro hardware? Nuestra página de otros sistemas de CI explica la parte de MacRun, y en precios tienes todos los modelos.
Preguntas frecuentes
¿Debo instalar GitLab Runner en macOS con Homebrew?
+
GitLab recomienda el binario oficial. Su documentación dice que GitLab no mantiene la fórmula de Homebrew.
¿Por qué falla gitlab-runner install por SSH?
+
El runner es un LaunchAgent de usuario y necesita una sesión gráfica. Ejecuta install y start desde una terminal en el escritorio del Mac.
¿GitLab Runner puede ejecutarse como LaunchDaemon en macOS?
+
No. GitLab dice que el LaunchAgent en modo usuario es el único modo soportado, porque los jobs necesitan el llavero y la sesión del usuario para firmar y para el simulador.
¿Dónde pongo las etiquetas del runner con el nuevo flujo de tokens?
+
En GitLab, en la página de creación o edición del runner. La documentación de GitLab dice que las etiquetas solo se pueden fijar al crear el runner en la interfaz o con la API, no con el comando register.