CI/CD con GitLab Runner local para desplegar automáticamente un blog Hugo

Etiquetas:

Introducció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 main para evitar deploys accidentales.

Después de tres meses funcionando sin problemas. Es simple pero efectivo.


Equipamiento recomendado

Enlaces de afiliado. Sin coste extra para ti.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *