GitLab Runner es el agente que ejecuta los jobs definidos en .gitlab-ci.yml. Tener un runner propio te da control sobre el hardware, la caché y las herramientas disponibles, y no consume los minutos de cómputo de GitLab.com. En este tutorial instalarás GitLab Runner en Ubuntu 24.04 desde el repositorio oficial, lo registrarás con el executor Docker, ajustarás la concurrencia y comprobarás que ejecuta un pipeline real.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 GB de RAM y 20 GB libres en disco para imágenes y caché.
- Un usuario no root con privilegios
sudo. - Docker Engine instalado desde el repositorio oficial de Docker (el executor Docker lo necesita).
- Un proyecto en GitLab.com o en tu propia instancia de GitLab, con rol Maintainer u Owner para crear runners.
El runner solo abre conexiones salientes hacia GitLab por HTTPS, así que no necesitas abrir puertos de entrada en el firewall.
Paso 1: Instalar GitLab Runner
GitLab publica un script que añade su repositorio APT y la clave de firma. Descárgalo primero para poder revisarlo antes de ejecutarlo:
curl -fsSL -o gitlab-runner-repo.sh https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh
less gitlab-runner-repo.sh
Ejecútalo e instala el paquete:
sudo bash gitlab-runner-repo.sh
sudo apt install gitlab-runner
El paquete crea el usuario de sistema gitlab-runner y el servicio gitlab-runner, que queda habilitado y en marcha. Compruébalo:
gitlab-runner --version
sudo systemctl status gitlab-runner --no-pager
Version: 18.x.x
...
● gitlab-runner.service - GitLab Runner
Loaded: loaded (/etc/systemd/system/gitlab-runner.service; enabled; preset: enabled)
Active: active (running)
Paso 2: Crear el runner en GitLab
Desde GitLab 16 los runners se crean primero en la interfaz, que genera un token de autenticación (empieza por glrt-). Los antiguos tokens de registro están obsoletos.
- En tu proyecto, ve a Settings > CI/CD y despliega Runners.
- Pulsa New project runner (en algunas versiones, Create project runner).
- En Tags escribe
docker,linux. Deja Run untagged jobs desmarcado si quieres que el runner solo acepte jobs con esas etiquetas. - Opcionalmente añade una descripción y un Maximum job timeout.
- Pulsa Create runner.
GitLab muestra el token glrt-... una sola vez. Cópialo; lo usarás en el siguiente paso.
Notasi administras una instancia propia, también puedes crear runners de grupo (Build > Runners en el grupo) o de instancia (Admin > CI/CD > Runners) con el mismo procedimiento.
Paso 3: Registrar el runner con el executor Docker
El executor Docker ejecuta cada job en un contenedor limpio a partir de la imagen indicada en .gitlab-ci.yml, lo que evita que los jobs se contaminen entre sí. Registra el runner sustituyendo your_runner_token por el token del paso anterior. Si usas una instancia propia, cambia también la URL:
sudo gitlab-runner register \
--non-interactive \
--url "https://gitlab.com" \
--token "your_runner_token" \
--name "ci-runner-01" \
--executor "docker" \
--docker-image "alpine:latest"
--name es el nombre local del runner en config.toml y --docker-image es la imagen por defecto para jobs que no declaran image:. Las etiquetas, la descripción y el tiempo máximo ya se definieron en la interfaz.
Runtime platform arch=amd64 os=linux ...
Verifying runner... is valid runner=AbCdEf12
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
Comprueba que el runner está registrado y que GitLab lo acepta:
sudo gitlab-runner list
sudo gitlab-runner verify
En GitLab, en Settings > CI/CD > Runners, el runner aparece con un punto verde (Online) al cabo de unos segundos.
Paso 4: Ajustar config.toml
El registro escribe la configuración en /etc/gitlab-runner/config.toml. Ábrelo:
sudo nano /etc/gitlab-runner/config.toml
Verás algo parecido a esto. Los cambios más útiles son concurrent (cuántos jobs puede ejecutar el servicio a la vez, por defecto 1) y los límites de recursos de los contenedores:
concurrent = 4
check_interval = 0
[[runners]]
name = "ci-runner-01"
url = "https://gitlab.com"
token = "glrt-..."
executor = "docker"
[runners.docker]
image = "alpine:latest"
privileged = false
pull_policy = ["if-not-present"]
memory = "2g"
cpus = "1.5"
volumes = ["/cache"]
shm_size = 0
concurrent = 4: hasta cuatro jobs en paralelo. Ajústalo a los núcleos y la RAM del servidor.pull_policy = ["if-not-present"]: reutiliza imágenes ya descargadas, lo que acelera mucho los jobs. Usaalwayssi necesitas garantizar siempre la última versión de una etiqueta.memoryycpus: límites por contenedor de job, para que un job descontrolado no tumbe el servidor.volumes = ["/cache"]: volumen donde el runner guarda la caché definida concache:en los jobs.
GitLab Runner detecta los cambios en config.toml y los recarga solo, pero reiniciar el servicio confirma que el archivo es válido:
sudo systemctl restart gitlab-runner
sudo journalctl -u gitlab-runner -n 20 --no-pager
Si hay un error de sintaxis, aparecerá en el log.
Paso 5: Ejecutar un pipeline de prueba
Crea o edita .gitlab-ci.yml en la raíz del proyecto. Las tags hacen que GitLab envíe los jobs a tu runner:
stages:
- test
default:
tags:
- docker
check-runner:
stage: test
image: python:3.12-slim
script:
- python --version
- echo "Ejecutado en $CI_RUNNER_DESCRIPTION"
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .cache/pip
Haz commit y push. En Build > Pipelines abre el job; el log debe empezar indicando tu runner y el executor:
Running with gitlab-runner 18.x.x (...)
on ci-runner-01 AbCdEf12, system ID: s_...
Preparing the "docker" executor
Using Docker executor with image python:3.12-slim ...
...
$ python --version
Python 3.12.x
Job succeeded
En el servidor puedes seguir la actividad del runner en tiempo real:
sudo journalctl -u gitlab-runner -f
Paso 6: Construir imágenes Docker desde los jobs (opcional)
Para ejecutar docker build dentro de un job hay que usar Docker-in-Docker, que necesita contenedores privilegiados. Actívalo solo en runners dedicados a proyectos de confianza, porque un job privilegiado puede tomar el control del servidor.
En /etc/gitlab-runner/config.toml, dentro de [runners.docker], cambia privileged y añade el volumen de certificados:
privileged = true
volumes = ["/certs/client", "/cache"]
Reinicia el servicio:
sudo systemctl restart gitlab-runner
Un job que construye y publica en el registro de contenedores de GitLab queda así:
build-image:
stage: build
image: docker:27
services:
- docker:27-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
tags:
- docker
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
- docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
Recuerda añadir build a la lista stages del archivo.
Alternativa: executor shell
Si prefieres que los jobs se ejecuten directamente en el servidor, con las herramientas instaladas en el sistema, registra el runner con --executor "shell" y sin --docker-image. Los jobs se ejecutan como el usuario gitlab-runner, en su directorio /home/gitlab-runner. Es más rápido, pero los jobs comparten estado y cualquier job puede leer lo que dejaron los anteriores.
Mantenimiento
Actualiza el runner junto con el resto del sistema; el servicio se reinicia solo tras la actualización:
sudo apt update && sudo apt install --only-upgrade gitlab-runner
El executor Docker acumula imágenes y volúmenes de caché. Revisa el espacio con docker system df y limpia periódicamente lo que no se usa:
sudo docker system prune --filter "until=168h"
Para retirar un runner, bórralo en GitLab (Settings > CI/CD > Runners) y elimina su entrada local:
sudo gitlab-runner unregister --name ci-runner-01
Haz copia de /etc/gitlab-runner/config.toml: contiene los tokens y toda la configuración del runner.
Solución de problemas
El job se queda en pending con el mensaje "This job is stuck": ningún runner online tiene todas las etiquetas del job. Comprueba que las tags del job coinciden con las del runner, o marca Run untagged jobs en el runner.
Cannot connect to the Docker daemon at unix:///var/run/docker.sock: Docker no está instalado o no está en marcha. Comprueba con sudo systemctl status docker.
Con executor shell: ERROR: Job failed: prepare environment: exit status 1: en Ubuntu, el archivo /home/gitlab-runner/.bash_logout limpia la consola y rompe la preparación del job. Elimínalo con sudo rm /home/gitlab-runner/.bash_logout.
Jobs Docker-in-Docker fallan con error during connect: falta privileged = true, el volumen /certs/client o la variable DOCKER_TLS_CERTDIR en el job.
Conclusión
Tienes un GitLab Runner propio en Ubuntu 24.04, registrado con un token de autenticación, ejecutando cada job en un contenedor aislado con límites de CPU y memoria y caché local. Como siguientes pasos, puedes añadir más runners con etiquetas distintas para separar cargas, construir imágenes con Docker-in-Docker en un runner dedicado o añadir análisis de calidad con SonarQube a tus pipelines.