CI/CD con GitLab Runner local para desplegar automáticamente un blog Hugo
Etiquetas: gitlab,ci/cd,hugo,docker,automatizaciónIntroducción
Cansado de hacer deploy manual de mi blog Hugo cada vez que publico un artículo. Decidí montar un pipeline CI/CD local con GitLab Runner. El resultado: automático, confiable y sin depender de servicios externos.
Requisitos previos
Necesitas:
– Un servidor con Docker instalado
– Un repositorio en GitLab (puede ser autohospedado o gitlab.com)
– Hugo instalado localmente para testing
– Acceso SSH configurado en tu servidor
Instalación de GitLab Runner
Lo primero es instalar GitLab Runner en tu servidor. Yo lo hice en Docker porque ya tenía el demonio corriendo.
docker pull gitlab/gitlab-runner:latest
docker run -d --name gitlab-runner \
--restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
gitlab/gitlab-runner:latest
Esto monta el socket de Docker para que el runner pueda ejecutar contenedores anidados. Importante para construir imágenes.
Registrar el Runner
Necesitas un token de tu proyecto GitLab. Lo encuentras en:
Configuración del proyecto → CI/CD → Runners
Luego ejecutas:
docker exec -it gitlab-runner gitlab-runner register \
--url https://gitlab.com/ \
--registration-token TU_TOKEN_AQUI \
--executor docker \
--docker-image alpine:latest \
--docker-volumes /var/run/docker.sock:/var/run/docker.sock \
--description "Runner Local Hugo"
Escoge Docker como executor. Es lo más limpio para este caso.
Configurar el pipeline
En la raíz de tu repositorio creas .gitlab-ci.yml:
stages:
- build
- deploy
variables:
DEPLOY_PATH: /home/deploy/blog-hugo/public
build:
stage: build
image: alpine:latest
before_script:
- apk add --no-cache hugo git
script:
- hugo --minify
- echo "Build completado"
artifacts:
paths:
- public/
expire_in: 1 week
only:
- main
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client rsync
- mkdir -p ~/.ssh
- echo "$DEPLOY_KEY" | base64 -d > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H localhost >> ~/.ssh/known_hosts
script:
- rsync -avz --delete public/ deploy@localhost:${DEPLOY_PATH}
- ssh deploy@localhost 'sudo systemctl restart nginx'
only:
- main
when: on_success
Variables de entorno
En Configuración del proyecto → CI/CD → Variables, añade:
DEPLOY_KEY: Tu clave SSH privada en base64 (cat ~/.ssh/id_rsa | base64 -w0)DEPLOY_PATH: Ruta donde quieres los archivos (yo uso/home/deploy/blog-hugo/public)
Usuario de deploy
En tu servidor creas un usuario específico:
sudo useradd -m -s /bin/bash deploy
sudo usermod -aG docker deploy
sudo mkdir -p /home/deploy/blog-hugo/public
sudo chown deploy:deploy /home/deploy/blog-hugo
Configura la clave SSH pública del runner:
sudo -u deploy ssh-keygen -t ed25519 -N "" -f /home/deploy/.ssh/id_rsa
cat /home/deploy/.ssh/id_rsa.pub >> /home/deploy/.ssh/authorized_keys
Verificar que funciona
Haz un push a la rama main:
git add .
git commit -m "Test CI/CD"
git push origin main
En GitLab ves el pipeline en tiempo real. Si todo está bien, en segundos tu blog estará desplegado.
sudo -u deploy cat /home/deploy/blog-hugo/public/index.html
Notas finales
- El runner local nunca sale de tu red. Total control.
- Los tiempos de build son rápidos porque todo está en la máquina local.
- Si necesitas cachear dependencias, configura volumes persistentes en Docker.
- He puesto restricciones a la rama
mainpara evitar deploys accidentales.
Después de tres meses funcionando sin problemas. Es simple pero efectivo.
Equipamiento recomendado
- Raspberry Pi 3 B+ — Servidor ligero de bajo consumo para empezar tu homelab
- Raspberry Pi 4 (4GB) — La base perfecta para homelab, Docker y monitorización
Enlaces de afiliado. Sin coste extra para ti.