Woodpecker CI

Simple, container-native continuous integration

CI/CD & Build ★ 7.9k stars Medium setup Apache-2.0

Woodpecker CI is a simple, community fork of Drone offering container-native continuous integration pipelines. It targets developers who want lightweight CI alongside their Git server. It is deployed via Docker.

Key features

  • Container-native pipelines
  • Simple YAML configuration
  • Integrates with Gitea and GitHub
  • Lightweight footprint

Pros & cons

Strengths

  • Easy to set up
  • Lightweight CI
  • Good Git integrations

Trade-offs

  • Fewer features than big CI tools
  • Smaller plugin ecosystem

Woodpecker CI replaces

Last reviewed Sep 13, 2026 · 956 words

Put Woodpecker CI next to your Gitea or Forgejo instance and you have the self-hosted CI most people should run: a server and an agent in two containers, 256 MB of RAM idle, every pipeline step in its own Docker container, and a .woodpecker.yml in each repository that a developer can read in full on the first try. It is a community fork of Drone from the point where Drone's licence changed, and it has kept Drone's simplicity while shedding the parts that were tied to a company. The one honest competitor is the Actions runner now built into Gitea and Forgejo, and the choice between them is the only real decision here.

Server plus agent, wired to your forge

Register an OAuth2 application in Gitea (Settings, Applications, with the redirect URL https://ci.example.com/authorize) and hand the client ID and secret to the server:

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    ports:
      - "8000:8000"
    environment:
      WOODPECKER_OPEN: "true"
      WOODPECKER_HOST: https://ci.example.com
      WOODPECKER_GITEA: "true"
      WOODPECKER_GITEA_URL: https://git.example.com
      WOODPECKER_GITEA_CLIENT: your-client-id
      WOODPECKER_GITEA_SECRET: your-client-secret
      WOODPECKER_AGENT_SECRET: a-long-shared-secret
      WOODPECKER_ADMIN: your-gitea-username
    volumes:
      - ./woodpecker:/var/lib/woodpecker
  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    environment:
      WOODPECKER_SERVER: woodpecker-server:9000
      WOODPECKER_AGENT_SECRET: a-long-shared-secret
      WOODPECKER_MAX_WORKFLOWS: 2
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Forgejo users swap the GITEA variables for the FORGEJO equivalents. Port 8000 is the UI and webhook receiver, 9000 is the gRPC channel agents connect on, and the server keeps its state in SQLite under the mounted volume by default, with Postgres or MySQL as options once several people depend on it. Log in with your forge account, enable a repository, and Woodpecker installs the webhook itself. WOODPECKER_OPEN lets any forge user register; on a private forge that is what you want, on a public one set it to false and list allowed users.

A pipeline is a list of steps in containers

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

  - name: build-image
    image: woodpeckerci/plugin-docker-buildx
    settings:
      repo: git.example.com/me/app
      registry: git.example.com
      username: { from_secret: registry_user }
      password: { from_secret: registry_pass }
      tags: [latest, "${CI_COMMIT_SHA:0:8}"]
    when:
      branch: main
      event: push

Each step runs in the image you name with the repository checked out at the working directory, and a shared workspace volume carries files between steps. Secrets live in the UI per repository or organisation and are injected only where referenced. Services (a Postgres for integration tests) are declared alongside and reachable by name. Multiple workflows live in a .woodpecker/ directory, and depends_on orders them. The plugin ecosystem is smaller than Jenkins or GitHub Actions, but a plugin is just an image that reads settings from environment variables, so writing one for your odd deploy target is a 20-line shell script in a Dockerfile.

Sizing and the docker.sock question

The agent mounting /var/run/docker.sock is what lets it spawn step containers, and it means a pipeline can do anything the Docker daemon can, which on most hosts is root. Woodpecker's answer is trusted-repository settings that gate privileged options, but the honest mitigation is to run the agent on a machine you consider disposable, or in a VM, and never on the same host as your password manager. A Kubernetes backend exists for people who would rather schedule steps as pods. Resource-wise the server is trivial; agents want whatever your builds want, and WOODPECKER_MAX_WORKFLOWS is the knob that keeps four concurrent Go builds from swapping a 4 GB box.

Woodpecker or the forge's own Actions

Gitea Actions and Forgejo Actions run a GitHub Actions-compatible runner, which means the existing marketplace of actions mostly works and a workflow copied from a GitHub project runs with minor edits. That compatibility is the reason to choose them. Woodpecker's reasons are the opposite: a smaller and more predictable model, every step visibly in a container with no hidden runner tooling, a UI that shows a pipeline as steps rather than a log dump, and a project whose entire purpose is this one tool. If your team already writes GitHub workflows, use Actions. If you are building from scratch on Gitea or Forgejo, I would take Woodpecker's clarity; the self-hosted git forges piece covers how the two forges themselves differ.

The bigger alternatives and why they are not the default

Jenkins does everything and needs a full-time owner to stay that way. GitLab CI is excellent if you are running GitLab, which is its own 4 GB commitment. Concourse is the right tool for a platform team building long-lived delivery pipelines and the wrong one for per-repository tests. Drone itself still exists but its future belongs to a company that bought it. For a self-hoster with a forge and between 1 and 50 repositories, Woodpecker is the lightest tool in CI/CD that is still a complete CI system, and that is the whole case for it.

What I'd do

Woodpecker server and one agent in Docker on a separate small VM from the forge, Postgres instead of SQLite if more than 2 people will use it, WOODPECKER_OPEN off on any forge with public registration, and a .woodpecker.yml template copied into every new repository with test and build steps. Push images to the forge's own container registry so there is one thing to back up. Reach for Gitea or Forgejo Actions only when a GitHub-compatible workflow is worth more to you than a smaller system you can hold in your head.

Compare Woodpecker CI

10 head-to-head comparisons.

Similar ci/cd & build apps