TL;DR — Resumen Rápido

Instala Woodpecker CI para CI/CD autoalojado y ligero. Configura pipelines, secretos, agentes e integración con Gitea, GitHub y GitLab desde cero.

Woodpecker CI es un sistema CI/CD autoalojado y ligero, derivado de Drone CI, que ejecuta pipelines nativos en contenedores con un consumo mínimo de recursos. Esta guía cubre la instalación completa, integración con Gitea, sintaxis de pipelines, gestión de secretos y un pipeline práctico para desplegar una aplicación Go.

Requisitos Previos

  • Servidor Linux con Docker y Docker Compose.
  • Al menos 512 MB de RAM para servidor + agente (se recomienda 1 GB).
  • Una instancia de Gitea, Forgejo, GitHub o GitLab para OAuth.
  • Puertos 8000 (HTTP) y 9000 (comunicación gRPC con agentes) abiertos.

Paso 1: Arquitectura de Woodpecker

Woodpecker sigue un modelo servidor + agente:

  • Servidor — Gestiona la UI web, API, webhooks y programación de pipelines.
  • Agente — Consulta el servidor en busca de trabajo y ejecuta los pasos dentro de contenedores Docker.
  • Forge — El proveedor Git (Gitea, GitHub, GitLab) que envía webhooks y autenticación OAuth.
  • Pipeline — Definido en .woodpecker.yml en la raíz del repositorio.

Paso 2: Instalar con Docker Compose

Crear la App OAuth en Gitea

En Gitea: Ajustes → Aplicaciones → OAuth2 → Crear aplicación OAuth2

  • Nombre: Woodpecker CI
  • URL de redirección: http://tu-servidor-woodpecker:8000/authorize

Copia el Client ID y el Client Secret.

Configuración con Docker Compose

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    container_name: woodpecker-server
    restart: always
    ports:
      - "8000:8000"
      - "9000:9000"
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker/
    environment:
      - WOODPECKER_OPEN=false
      - WOODPECKER_HOST=http://tu-servidor:8000
      - WOODPECKER_GITEA=true
      - WOODPECKER_GITEA_URL=http://tu-gitea:3000
      - WOODPECKER_GITEA_CLIENT=tu-client-id
      - WOODPECKER_GITEA_SECRET=tu-client-secret
      - WOODPECKER_AGENT_SECRET=secreto-compartido-fuerte

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    container_name: woodpecker-agent
    restart: always
    depends_on:
      - woodpecker-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_AGENT_SECRET=secreto-compartido-fuerte
      - WOODPECKER_MAX_PROCS=2

volumes:
  woodpecker-server-data:
docker compose up -d

Paso 3: Sintaxis del Pipeline (.woodpecker.yml)

Pipeline Básico

steps:
  - name: test
    image: golang:1.22
    commands:
      - go test ./...

  - name: build
    image: golang:1.22
    commands:
      - go build -o app .

  - name: notificar
    image: plugins/slack
    settings:
      webhook:
        from_secret: slack_webhook
    when:
      - status: [success, failure]

Ejecución Condicional con when

steps:
  - name: desplegar
    image: alpine
    commands:
      - ./deploy.sh
    when:
      - branch: main
        event: push

Servicios (Base de Datos, Redis)

services:
  - name: postgres
    image: postgres:16
    environment:
      POSTGRES_DB: testdb
      POSTGRES_USER: test
      POSTGRES_PASSWORD: test

steps:
  - name: test
    image: golang:1.22
    environment:
      DATABASE_URL: "postgres://test:test@postgres/testdb?sslmode=disable"
    commands:
      - go test -tags integration ./...

Matrix Builds

matrix:
  GO_VERSION:
    - "1.21"
    - "1.22"

steps:
  - name: test
    image: "golang:${GO_VERSION}"
    commands:
      - go test ./...

Paso 4: Gestión de Secretos

ÁmbitoConfigurado porVisible para
RepositorioPropietario del repoSolo ese repositorio
OrganizaciónAdmin de la orgTodos los repos de la org
GlobalAdmin del servidorTodos los repositorios

Referencia un secreto en el pipeline:

steps:
  - name: desplegar
    image: alpine
    environment:
      DEPLOY_KEY:
        from_secret: deploy_key
    commands:
      - echo "$DEPLOY_KEY" | base64 -d > /tmp/key
      - ./deploy.sh

Paso 5: Plugins

PluginImagenPropósito
Dockerwoodpeckerci/plugin-docker-buildxConstruir y publicar imágenes Docker
S3woodpeckerci/plugin-s3Subir artefactos a S3
Slackplugins/slackNotificaciones de build
Webhookwoodpeckerci/plugin-webhookPOST a URLs arbitrarias

Paso 6: Agentes, CLI y Builds Multiplataforma

Etiquetas de Agentes

WOODPECKER_FILTER_LABELS=platform=linux/arm64,type=build
labels:
  platform: linux/arm64

steps:
  - name: build-arm
    image: golang:1.22
    commands:
      - GOARCH=arm64 go build -o app-arm64 .

woodpecker-cli

export WOODPECKER_SERVER=http://tu-servidor:8000
export WOODPECKER_TOKEN=tu-token-api

woodpecker pipeline ls propietario/repo
woodpecker pipeline start propietario/repo --branch main
woodpecker secret add --repository propietario/repo --name deploy_key --value "$(cat key.pem)"

Tareas Programadas (Cron)

woodpecker cron add --repository propietario/repo --name build-nocturno \
  --expr "0 2 * * *" --branch main

Woodpecker vs Alternativas

CaracterísticaWoodpeckerDrone OSSGitea ActionsJenkinsConcourse
LicenciaMITApache 2.0MITMITApache 2.0
RAM (en reposo)~50 MB~80 MB~100 MB~500 MB~200 MB
Formato pipelineYAMLYAMLYAML (GHA)Groovy/YAMLYAML
Matrix buildsNo (OSS)
Multi-pipelineNo (OSS)No
Backend KubernetesNoNo

Ejemplo Práctico: Pipeline para Aplicación Go

steps:
  - name: test
    image: golang:1.22
    commands:
      - go vet ./...
      - go test -race ./...

  - name: build-docker
    image: woodpeckerci/plugin-docker-buildx
    settings:
      repo: registry.ejemplo.com/miapp
      tags: ["latest", "${CI_COMMIT_SHA:0:8}"]
      platforms: "linux/amd64,linux/arm64"
      username:
        from_secret: registry_user
      password:
        from_secret: registry_password
    when:
      - branch: main
        event: push

  - name: desplegar
    image: alpine
    environment:
      DEPLOY_KEY:
        from_secret: deploy_ssh_key
      DEPLOY_HOST:
        from_secret: deploy_host
    commands:
      - apk add --no-cache openssh-client
      - echo "$DEPLOY_KEY" | base64 -d > /tmp/key && chmod 600 /tmp/key
      - ssh -i /tmp/key -o StrictHostKeyChecking=no deploy@$DEPLOY_HOST
          "docker pull registry.ejemplo.com/miapp:latest && docker restart miapp"
    when:
      - branch: main
        event: push

Problemas Comunes

ProblemaSolución
Agente no se conectaVerifica que WOODPECKER_AGENT_SECRET coincida; comprueba que el puerto 9000 esté abierto
Pipeline en estado pendienteNingún agente conectado o etiquetas no coinciden; revisa el estado del agente en la UI
Webhook no se disparaVerifica que Gitea pueda alcanzar el servidor Woodpecker; revisa Ajustes > Hooks del repo
Secretos no inyectadosEl nombre del secreto debe coincidir exactamente con el pipeline; revisa el filtro de eventos
Build multiplataforma fallaVerifica que QEMU esté instalado o usa privileged: true

Resumen

  • Woodpecker CI es un fork ligero de Drone CI que usa ~50 MB de RAM con arquitectura servidor + agente.
  • Se integra con 6 forges (Gitea, Forgejo, GitHub, GitLab, Bitbucket) via OAuth2.
  • Los pipelines usan .woodpecker.yml con pasos, servicios, matrix builds y multi-pipeline por rutas.
  • Los secretos se gestionan por repositorio, organización o globalmente, con backends externos como Vault.
  • El CLI woodpecker-cli permite gestionar pipelines, secretos y tareas cron desde la terminal.

Artículos Relacionados