In my Homelab environment, I used Woodpecker-CI to quickly be able to run some CI/CD jobs.
Here’s my docker-compose.yml in charge of deploying it.
I use two distinct DNS records:
woodpecker-ci.mydomain.tldwhich is aArecord pointing to the local IP of my Traefik server (192.168.0.x).woodpecker-ci-wh.mydomain.tldwhich is aCNAMErecord pointing to my Cloudflare Tunnel instance.
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:v3
#ports:
# - 8000:8000
volumes:
- /opt/woodpecker/server/data:/var/lib/woodpecker/
environment:
- WOODPECKER_OPEN=false # You might need to set this to true the first time to log in using Github
- WOODPECKER_HOST=https://woodpecker-ci.mydomain.tld
- WOODPECKER_GITHUB=true
- WOODPECKER_GITHUB_CLIENT=GITHUB_CLIENT_ID_HERE
- WOODPECKER_GITHUB_SECRET=GITHUB_CLIENT_SECRET_HERE
- WOODPECKER_AGENT_SECRET=YOU_AGENT_SECRET_HERE
- WOODPECKER_ADMIN=YOUR_GITHUB_USERNAME_HERE
- WOODPECKER_EXPERT_WEBHOOK_HOST=https://woodpecker-ci-wh.mydomain.tld
restart: always
networks: # Optional
- apps
labels: # If you don't use traefik, you can comment all the labels and uncomment the `ports` section.
- "traefik.enable=true"
- "traefik.http.services.woodpecker-server.loadbalancer.server.port=8000"
- "traefik.http.routers.woodpecker-server.rule=Host(`woodpecker-ci.mydomain.tld`)"
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:v3
command: agent
restart: always
depends_on:
- woodpecker-server
volumes:
- /opt/woodpecker/agent/config:/etc/woodpecker
- /var/run/docker.sock:/var/run/docker.sock
# Extra volumes can be added to suit your needs
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_AGENT_SECRET=YOU_AGENT_SECRET_HERE
networks: # Optional
- apps
cloudflared-woodpecker-ci-wh:
image: cloudflare/cloudflared:latest
restart: always
depends_on:
- woodpecker-server
command: tunnel --no-autoupdate run --token YOUR_CLOUDFLARED_TOKEN_HERE
networks: # Optional
- apps
networks: # Optional
apps:
name: apps
external: true
Things you need to replace:
YOU_AGENT_SECRET_HEREby a new secret, you can use the commandpwgen 64 1to get a random string. Replace it in bothwoodpecker-serverandwoodpecker-agentenviroment.GITHUB_CLIENT_ID_HERE&GITHUB_CLIENT_SECRET_HEREwith the client ID and secret of your Github OAuth application.YOUR_GITHUB_USERNAME_HEREby… well… your Github username.YOUR_CLOUDFLARED_TOKEN_HEREby the token provided by Cloudflare Tunnels for cloudflared.
Here’s also a summary of my Cloudflare Tunnel config:

Make sure to only route the /api/hook endpoint; the service URL should be http://woodpecker-server:8000.