Instalación y Configuración de Woodpecker CI

Woodpecker CI es un sistema de integración continua ligero y nativo de contenedores, diseñado para funcionar directamente con Gitea y Forgejo como fuente de repositorios. Con una arquitectura de servidor y agentes distribuidos, pipelines definidos en YAML y soporte para múltiples plataformas, Woodpecker es una alternativa autoalojada ideal a servicios como GitHub Actions o CircleCI.

Requisitos Previos

  • Servidor Linux con Docker y Docker Compose
  • Instancia de Gitea o Forgejo en funcionamiento
  • Dominio con HTTPS configurado (requerido para OAuth)
  • Mínimo 1 GB de RAM para el servidor
  • Los agentes pueden estar en servidores separados

Configuración de la Aplicación OAuth en Gitea/Forgejo

Woodpecker usa OAuth2 para autenticar usuarios. Crea la aplicación OAuth en Gitea:

1. Ve a: Tu perfil > Ajustes > Aplicaciones
2. En "Gestionar aplicaciones OAuth2", haz clic en "Crear nueva aplicación OAuth2"
3. Nombre: Woodpecker CI
4. URL de redirección: https://ci.tudominio.com/authorize
5. Haz clic en "Crear aplicación"
6. Guarda el Client ID y Client Secret que se generan

Instalación del Servidor Woodpecker

# Crear directorio de trabajo
mkdir -p /opt/woodpecker
cd /opt/woodpecker

# Generar un secret compartido entre servidor y agentes
WOODPECKER_AGENT_SECRET=$(openssl rand -hex 32)
echo "Agent Secret: $WOODPECKER_AGENT_SECRET"

Crea el fichero docker-compose.yml:

# /opt/woodpecker/docker-compose.yml
version: "3.8"

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    container_name: woodpecker-server
    restart: unless-stopped
    ports:
      - "8000:8000"  # Puerto web
      - "9000:9000"  # Puerto gRPC para agentes
    environment:
      # Configuración del servidor
      - WOODPECKER_HOST=https://ci.tudominio.com
      - WOODPECKER_OPEN=false  # Solo usuarios autorizados
      - WOODPECKER_ADMIN=tu_usuario_gitea

      # Secreto compartido con los agentes
      - WOODPECKER_AGENT_SECRET=TU_AGENT_SECRET_AQUI

      # Integración con Gitea
      - WOODPECKER_GITEA=true
      - WOODPECKER_GITEA_URL=https://git.tudominio.com
      - WOODPECKER_GITEA_CLIENT=TU_OAUTH_CLIENT_ID
      - WOODPECKER_GITEA_SECRET=TU_OAUTH_CLIENT_SECRET

      # Base de datos (SQLite para empezar, PostgreSQL para producción)
      - WOODPECKER_DATABASE_DRIVER=sqlite3
      - WOODPECKER_DATABASE_DATASOURCE=/var/lib/woodpecker/woodpecker.sqlite
    volumes:
      - woodpecker_server_data:/var/lib/woodpecker/

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    container_name: woodpecker-agent
    restart: unless-stopped
    depends_on:
      - woodpecker-server
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_AGENT_SECRET=TU_AGENT_SECRET_AQUI
      - WOODPECKER_MAX_PROCS=4  # Pipelines paralelos por agente
      - WOODPECKER_BACKEND=docker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - woodpecker_agent_data:/etc/woodpecker

volumes:
  woodpecker_server_data:
  woodpecker_agent_data:
# Arrancar Woodpecker
docker compose up -d

# Verificar los logs de inicio
docker compose logs -f woodpecker-server

Configura el proxy inverso con Nginx:

sudo tee /etc/nginx/sites-available/woodpecker << 'EOF'
server {
    listen 443 ssl http2;
    server_name ci.tudominio.com;

    ssl_certificate /etc/letsencrypt/live/ci.tudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ci.tudominio.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Necesario para streaming de logs en tiempo real
        proxy_buffering off;
        proxy_read_timeout 3600s;
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/woodpecker \
  /etc/nginx/sites-enabled/woodpecker
sudo certbot --nginx -d ci.tudominio.com
sudo systemctl reload nginx

Instalación de Agentes

Los agentes pueden desplegarse en servidores separados para escalar la capacidad de compilación:

# En el servidor del agente (puede ser diferente al del servidor)
mkdir -p /opt/woodpecker-agent
cd /opt/woodpecker-agent

tee docker-compose.yml << 'EOF'
version: "3.8"

services:
  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    restart: unless-stopped
    environment:
      # Apuntar al servidor Woodpecker
      - WOODPECKER_SERVER=ci.tudominio.com:9000
      - WOODPECKER_AGENT_SECRET=EL_MISMO_AGENT_SECRET
      - WOODPECKER_MAX_PROCS=2
      - WOODPECKER_BACKEND=docker
      # Etiquetar este agente para pipelines específicos
      - WOODPECKER_LABELS=platform=linux,arch=amd64
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
EOF

docker compose up -d

Sintaxis de Pipelines

Crea el fichero .woodpecker.yml en la raíz de tu repositorio:

# Pipeline básico de CI
steps:
  # Paso de pruebas
  pruebas:
    image: node:20-alpine
    commands:
      - npm ci
      - npm test
      - npm run lint

  # Construcción de imagen Docker
  construir:
    image: plugins/docker
    settings:
      repo: registro.tudominio.com/mi-app
      tags:
        - latest
        - ${CI_COMMIT_SHA}
      username:
        from_secret: docker_username
      password:
        from_secret: docker_password
    when:
      branch: main

  # Despliegue en producción
  desplegar:
    image: appleboy/drone-ssh
    settings:
      host: produccion.tudominio.com
      username: deploy
      key:
        from_secret: ssh_private_key
      script:
        - cd /opt/mi-app
        - docker compose pull
        - docker compose up -d --remove-orphans
    when:
      branch: main
      event: push

Pipeline con múltiples etapas y dependencias:

# Pipeline con etapas secuenciales
steps:
  instalar:
    image: node:20
    commands:
      - npm ci

  pruebas-unitarias:
    image: node:20
    commands:
      - npm run test:unit
    depends_on: [instalar]

  pruebas-integracion:
    image: node:20
    commands:
      - npm run test:integration
    depends_on: [instalar]

  construir:
    image: node:20
    commands:
      - npm run build
    depends_on:
      - pruebas-unitarias
      - pruebas-integracion

  notificar-fallo:
    image: curlimages/curl
    commands:
      - |
        curl -X POST "$TELEGRAM_URL" \
          -d "chat_id=$CHAT_ID&text=❌ Pipeline fallido en $CI_REPO"
    when:
      status: [failure]
    depends_on: [construir]

Gestión de Secretos

Los secretos se configuran desde la interfaz web o mediante la CLI:

# Instalar la CLI de Woodpecker
curl -sL https://github.com/woodpecker-ci/woodpecker/releases/latest/download/woodpecker-cli-linux-amd64.tar.gz \
  | tar -xz -C /usr/local/bin/

# Configurar la CLI
export WOODPECKER_SERVER=https://ci.tudominio.com
export WOODPECKER_TOKEN=TU_TOKEN_API

# Crear un secreto para un repositorio específico
woodpecker secret add \
  --repository tu-org/mi-app \
  --name docker_password \
  --value "contraseña_docker_segura"

# Crear un secreto global (disponible en todos los repositorios)
woodpecker secret add \
  --global \
  --name ssh_private_key \
  --value "$(cat ~/.ssh/id_rsa)"

# Listar secretos de un repositorio
woodpecker secret ls --repository tu-org/mi-app

En el pipeline, accede a los secretos:

steps:
  desplegar:
    image: alpine
    environment:
      # Los secretos se inyectan como variables de entorno
      API_KEY:
        from_secret: mi_api_key
    commands:
      - echo "Usando la clave API: $API_KEY"

Compilaciones Multi-plataforma

Configura compilaciones para múltiples arquitecturas (amd64, arm64):

# Pipeline multi-plataforma
platform: linux/amd64,linux/arm64

steps:
  construir-imagen:
    image: plugins/docker
    settings:
      platforms: linux/amd64,linux/arm64
      repo: registro.tudominio.com/mi-app
      tags: [latest, "${CI_COMMIT_SHA}"]
      username:
        from_secret: docker_username
      password:
        from_secret: docker_password
    when:
      branch: main

Para agentes específicos por arquitectura:

# Ejecutar en un agente ARM específico
labels:
  platform: linux/arm64

steps:
  pruebas-arm:
    image: golang:1.22-alpine
    commands:
      - go test ./...

Solución de Problemas

El agente no se conecta al servidor:

# Verificar que el puerto gRPC (9000) está accesible
telnet ci.tudominio.com 9000

# Comprobar el secret en ambos lados
docker exec woodpecker-server env | grep AGENT_SECRET
docker exec woodpecker-agent env | grep AGENT_SECRET

Pipeline falla al hacer pull de la imagen:

# Verificar credenciales del registro Docker
docker exec woodpecker-agent \
  docker login registro.tudominio.com

# Ver logs del agente durante la ejecución
docker compose logs -f woodpecker-agent

OAuth no redirige correctamente:

# Verificar que la URL de callback coincide exactamente
# En Gitea: Ajustes > Aplicaciones > OAuth2
# URL de redirección debe ser: https://ci.tudominio.com/authorize

# Revisar logs del servidor
docker compose logs woodpecker-server | grep -i oauth

Conclusión

Woodpecker CI ofrece una solución de integración continua nativa de contenedores, sencilla de operar y perfectamente integrada con Gitea y Forgejo. Su arquitectura de servidor y agentes permite escalar horizontalmente la capacidad de compilación según las necesidades del equipo, mientras que la sintaxis YAML simple facilita la definición de pipelines complejos. Es la combinación ideal para equipos que ya utilizan Gitea o Forgejo como plataforma de hosting Git.