Woodpecker is a container-native CI engine: a server that talks to your git forge and one or more agents that run each pipeline step in a container. It replaces a hosted GitHub Actions or CircleCI plan for people who already run their own forge.
Our verdict on Woodpecker CI#
Woodpecker exists because Drone changed its licence. It was forked from Drone 0.8, just before the 1.0 release and the move away from Apache 2.0, renamed in August 2019, and it has stayed Apache-2.0 ever since. That is the entire reason to prefer it over Drone and it is a good one. What you get is deliberately small: a Go server on port 8000, a gRPC listener on 9000 for agents, SQLite unless you point it at PostgreSQL, and pipeline steps that are just containers with a shared workspace volume. It runs on a Raspberry Pi and the whole thing idles under 100 MB. The tradeoff is that it does exactly this and no more. There is no artifact store, no secrets manager beyond per-repo secrets, no built-in caching layer, and no user database: everyone who logs in does so through your forge's OAuth. If your forge already has usable CI, such as Forgejo Actions, the case for a second system is weaker than it was.
Who Woodpecker CI is for#
Choose it if
- Anyone running Forgejo or Gitea who wants real CI without adding GitLab-sized infrastructure.
- Homelabs where the CI host is a Pi or a small NUC and 250 MB of overhead actually matters.
- Teams that left Drone over the licence change and want a drop-in with familiar YAML.
- Multi-arch builders who want an arm64 agent on real arm64 hardware rather than emulation.
Look elsewhere if
- You need artifact retention, build caching or a package registry as part of CI; Woodpecker leaves all of that to you.
- You want to gate CI access with your own identity provider, because login is your git forge's OAuth and nothing else.
- Your forge already ships Actions-compatible CI and your pipelines are simple, in which case a second service is pure overhead.
What running it actually looks like#
Two containers. The server holds the web UI on 8000 and a gRPC listener on 9000; agents dial the server on 9000 and authenticate with a shared WOODPECKER_AGENT_SECRET that you generate yourself. Before first start you need an OAuth application registered in your forge, its client ID and secret, and WOODPECKER_HOST set to the exact public URL, because the OAuth callback is built from it. WOODPECKER_OPEN is false by default, so registration is closed and you list admins explicitly in WOODPECKER_ADMIN. The agent needs the Docker socket to start step containers, which is root-equivalent access to that host, so keep agents off the machine running your forge. Upgrades are tag bumps and a restart; major versions have changed pipeline syntax and removed deprecated settings, so read the migration notes on 1.x, 2.x and 3.x boundaries.
Resource profile#
- Memory
- 90 MB idle, around 250 MB in ordinary use. Server and agent are small Go processes, roughly 50 MB and 30 MB resident; the number that matters is whatever your pipeline containers consume, which Woodpecker does not account for.
- CPU and acceleration
- The server is idle between webhooks. All real CPU load is inside the step containers the agent starts, so size the agent host for your builds, not for Woodpecker.
- Storage growth
- The SQLite database stays in the tens of megabytes for years. Disk pressure comes from the Docker image cache and pipeline workspaces on the agent host, which need periodic pruning.
- Operational load
- 2 of 5, Light. Two small services and a shared secret, SQLite by default, and upgrades are usually a tag bump. You pay attention on major versions, which have changed pipeline syntax and dropped deprecated config, and you prune the agent's image cache.
Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.
Data and backup surface#
Almost everything worth keeping is one SQLite file at /var/lib/woodpecker/woodpecker.sqlite: users, repository registrations, secrets, pipeline metadata and logs. Stop the server and copy it, or use sqlite3 .backup for a consistent snapshot on a running instance. On PostgreSQL, a plain pg_dump is enough. Keep the WOODPECKER_AGENT_SECRET and the forge OAuth client secret with your other credentials, because they live in environment variables and not in the database, and a restore without them leaves agents unable to connect. Agents hold nothing durable: their workspaces and image cache are regenerable and should be excluded. Old pipeline logs are the main growth and can be pruned without consequence.
Derived backup shape
SQLite backup. sqlite3 <db> ".backup out.db" while running, or stop the container and copy. A live cp of a WAL-mode SQLite file can restore corrupt.
Traps and surprises#
The agent's Docker socket is host root
The standard agent configuration bind-mounts /var/run/docker.sock so it can start step containers. Anyone who can push a pipeline file to a repository Woodpecker watches can therefore start a privileged container on that host and read the whole filesystem. Run agents on a machine that holds nothing else, or use the Kubernetes or local backend instead of the Docker backend.
WOODPECKER_HOST must match the public URL exactly
The OAuth callback URL, the links in build status notifications and the webhook targets are all derived from WOODPECKER_HOST. Set it to http://localhost:8000 while testing behind a reverse proxy and forge logins fail with a redirect mismatch, while webhooks point at an address the forge cannot reach. Include the scheme, and the port only if it is non-standard.
Major versions changed pipeline syntax
Woodpecker has broken its YAML across majors: pipeline: became steps:, platform: became labels:, and settings that used to be top level moved under plugin settings. Upgrading the server does not rewrite your repositories' .woodpecker.yml files, so pipelines fail on the first push after an upgrade. Read the migration page for every major you cross and update the files before switching.
Registration is closed by default
WOODPECKER_OPEN defaults to false, which means a new user who authenticates through the forge OAuth is bounced with a bland error rather than being created. This looks like a broken OAuth setup and sends people digging in the wrong place. Either set WOODPECKER_OPEN=true with a forge organization filter, or add each user to WOODPECKER_ADMIN and the per-repository access lists.
Specifications#
- Category
- Git forges and developer infrastructure
- Licence
- Apache-2.0 (Permissive)
- Written in
- Go / Vue
- First release
- 2019
- Maturity
- Stable
- Datastore
- SQLite (default), PostgreSQL or MySQL optional
- Default ports
8000,9000- Ships as
- docker, native binary, helm chart, kubernetes
- arm64 builds
- Yes
- Identity
- Native OIDC. There are no local accounts at all: login is OAuth against the configured forge (Forgejo, Gitea, GitHub, GitLab or Bitbucket), so your forge is your identity provider and there is no generic OIDC option.
- Replaces
- CircleCI, Travis CI, Jenkins, Drone
- Project site
- woodpecker-ci.org
- Source
- github.com/woodpecker-ci/woodpecker
- Documentation
- woodpecker-ci.org/docs/intro
Alternatives to Woodpecker CI#
Everything else in git forges and developer infrastructure, closest in operational weight first.
| Tool | Ops load | Idle RAM | Licence |
|---|---|---|---|
| Forgejo | 2, Light | 150 MB | GPL-3.0-or-later |
| Gitea | 2, Light | 150 MB | MIT |
| code-server | 2, Light | 200 MB | MIT |
| GitLab CE | 4, Heavy | 4096 MB | MIT |
| Harbor | 4, Heavy | 2500 MB | Apache-2.0 |
Where Woodpecker CI comes up elsewhere#
Head to head
Migration guides
Sources#
Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.