Woodpecker CI is a community fork of Drone CI, fully open source (Apache 2.0), lightweight, and popular with self-hosters, especially alongside Gitea or Forgejo. Pipelines are YAML files in your repository, and every step runs in a container. A small VPS runs it easily.

Comparison: Drone CI and Gitea Actions (GitHub Actions-compatible, built into Gitea).

Architecture

  • Server: web UI, API, receives webhooks from your forge (Gitea, Forgejo, GitHub, GitLab, Bitbucket).
  • Agents: run pipeline steps using a backend (Docker, Kubernetes, or local).

1. OAuth application in Gitea/Forgejo

Settings → Applications → Create OAuth2 Application:

  • name: Woodpecker;
  • redirect URI: https://ci.example.com/authorize.

Note the client ID and secret.

2. Docker Compose

# /opt/woodpecker/compose.yaml
services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:v3
    restart: unless-stopped
    ports:
      - "127.0.0.1:8000:8000"
    volumes:
      - ./data:/var/lib/woodpecker
    environment:
      WOODPECKER_HOST: https://ci.example.com
      WOODPECKER_OPEN: "false"
      WOODPECKER_ADMIN: youradmin
      WOODPECKER_GITEA: "true"
      WOODPECKER_GITEA_URL: https://git.example.com
      WOODPECKER_GITEA_CLIENT: <client-id>
      WOODPECKER_GITEA_SECRET: <client-secret>
      WOODPECKER_AGENT_SECRET: <openssl rand -hex 32>

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:v3
    restart: unless-stopped
    depends_on: [woodpecker-server]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WOODPECKER_SERVER: woodpecker-server:9000
      WOODPECKER_AGENT_SECRET: <same secret>
      WOODPECKER_MAX_WORKFLOWS: 2
cd /opt/woodpecker && docker compose up -d

Put Nginx with HTTPS in front of port 8000. See Nginx reverse proxy. Check the Woodpecker docs for the current major version, and environment variable names.

WOODPECKER_OPEN=false with WOODPECKER_ADMIN keeps random users of your forge from registering. The Gitea instance itself: see Gitea.

3. Enable a repository, add a pipeline

Log in, enable the repository, and add .woodpecker.yaml (or a .woodpecker/ directory with several workflow files):

when:
  - event: [push, pull_request]
    branch: main

steps:
  - name: test
    image: python:3.12-slim
    commands:
      - pip install -r requirements.txt
      - pytest -q

  - name: image
    image: woodpeckerci/plugin-docker-buildx
    settings:
      registry: git.example.com
      repo: git.example.com/team/myapp
      tags: ${CI_COMMIT_SHA:0:8}
      username: { from_secret: registry_user }
      password: { from_secret: registry_token }
    when:
      - event: push
        branch: main

  - name: deploy
    image: appleboy/drone-ssh
    settings:
      host: { from_secret: vps_host }
      username: deploy
      key: { from_secret: vps_ssh_key }
      script:
        - cd /opt/app && docker compose pull && docker compose up -d
    when:
      - event: push
        branch: main

Gitea and Forgejo include a container registry, so git.example.com can host your images. Add secrets in the repository settings in Woodpecker. See GitHub Actions secrets for the general principles.

Securing agents

  • The agent mounts the Docker socket: pipelines can control the host. Use dedicated build VPS agents, and restrict which repositories may run privileged plugins.
  • Limit concurrency (WOODPECKER_MAX_WORKFLOWS) to the VPS’s CPU and RAM.
  • Clean up images and volumes regularly. See Docker disk cleanup.
  • Pull requests from forks: don’t expose secrets to them (Woodpecker requires approval for untrusted contributors).

Woodpecker vs Gitea Actions vs Drone

Woodpecker Gitea Actions Drone
Licence Apache 2.0 MIT (part of Gitea) Mixed (enterprise features)
Syntax Drone-like YAML GitHub Actions-compatible Drone YAML
Separate service Yes Built into Gitea (+ act_runner) Yes
Best for Simple, open-source CI Reusing GitHub Actions workflows Existing Drone users

Quick reference

Item Value
Server / agent images woodpeckerci/woodpecker-server, woodpeckerci/woodpecker-agent
Pipeline file .woodpecker.yaml or .woodpecker/*.yaml
Shared secret WOODPECKER_AGENT_SECRET
Secrets in steps from_secret:
Gitea redirect URI https://ci.example.com/authorize

Related: CI/CD pipeline explained and Docker Compose in production.

  • CI/CD
  • Gitea
  • Self-Hosting