4.8 KiB
| layout | title | date | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|
| post | Migrating from Drone CI to Woodpecker CI | 2026-04-18 |
|
Woodpecker CI is a community fork of Drone CI, created when Drone changed its licensing model around 2021 and moved features behind a paid enterprise tier. Woodpecker continues as a fully open-source (Apache 2.0) project with active development, while Drone itself has been largely absorbed into Harness CI and is in maintenance mode.
If you're running Drone with Gitea, Woodpecker is a natural migration target — it has strong Gitea integration and an actively maintained codebase. Here is what the migration actually involves, based on a real setup using Docker Compose and Traefik.
Docker Compose
The server and runner/agent images change, and there are several environment variable renames. Woodpecker also uses different ports: the web UI runs on 8000 (not 80), and the agent communicates with the server over gRPC on port 9000.
woodpecker:
image: woodpeckerci/woodpecker-server:latest
container_name: woodpecker
restart: unless-stopped
environment:
- WOODPECKER_HOST=https://drone.example.org # full URL including scheme
- WOODPECKER_GITEA=true
- WOODPECKER_GITEA_URL=https://gitea.example.org
- WOODPECKER_CRON_DISABLED=true
env_file:
- ./woodpecker.env
volumes:
- woodpecker:/var/lib/woodpecker # different path from Drone's /data
networks:
- services
- woodpecker
labels:
traefik.enable: "true"
traefik.http.services.woodpecker.loadbalancer.server.port: 8000 # not 80!
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:latest
restart: unless-stopped
environment:
- WOODPECKER_SERVER=woodpecker:9000 # gRPC port, not HTTP
- WOODPECKER_GRPC_SECURE=false
env_file:
- ./woodpecker.env
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- woodpecker
Make sure both the server and agent containers are on the same Docker network. If the agent can resolve the server's hostname but port 9000 is refused, it is likely a startup ordering issue — simply restarting the agent container after the server is fully up will fix it.
Environment Variables
Your drone.env secrets need to be renamed in a new woodpecker.env file:
drone.env |
woodpecker.env |
|---|---|
DRONE_GITEA_CLIENT_ID |
WOODPECKER_GITEA_CLIENT |
DRONE_GITEA_CLIENT_SECRET |
WOODPECKER_GITEA_SECRET |
DRONE_RPC_SECRET |
WOODPECKER_AGENT_SECRET |
DRONE_COOKIE_SECRET |
WOODPECKER_SECRET |
Note that WOODPECKER_AGENT_SECRET (RPC) and WOODPECKER_SECRET (cookie signing) are separate variables — do not conflate them.
You also need to set WOODPECKER_ADMIN to your Gitea username, otherwise Woodpecker will not allow you to register or access the admin panel:
WOODPECKER_ADMIN=yourusername
You will also need to create a new OAuth application in Gitea pointing at your Woodpecker URL, since the callback URL changes.
Pipeline Files
You must rename .drone.yml to .woodpecker.yml. Despite what the documentation suggests, Woodpecker (at least on the next tag) does not fall back to .drone.yml — it will silently ignore it, and pushes will not trigger any pipelines.
The pipeline syntax is largely compatible. Steps, images, commands, secrets, and when conditions mostly work as-is. A few things to check:
Move trigger to the pipeline level. In Drone it was sometimes written under individual steps; in Woodpecker it must be a top-level key.
Drone plugins still work. They are just Docker images, so plugins like drillster/drone-rsync are fully compatible.
DRONE_* environment variables become CI_*. If your pipeline scripts reference injected variables like DRONE_COMMIT, these are renamed in Woodpecker (e.g. CI_COMMIT_SHA).
What Does Not Migrate
Woodpecker does not import Drone's database. This means:
- Build history is lost — you start with a clean slate
- Secrets must be re-entered via the Woodpecker UI for each repository
- Repos must be re-activated in Woodpecker
If retaining build history matters, you can keep the old Drone instance running read-only alongside Woodpecker temporarily, since they can coexist on different hostnames.
Summary
For a straightforward Drone + Gitea + Docker Compose setup, the migration is low effort. The main steps are:
- Update
docker-compose.ymlwith the new images and port numbers - Rename secrets in your env file and set
WOODPECKER_ADMIN - Create a new OAuth app in Gitea
- Rename
.drone.ymlto.woodpecker.ymlin each repository - Move any pipeline-level
triggerblocks to the top level - Re-activate repos and re-enter secrets in the Woodpecker UI