Woodpecker — CI/CD Pipelines¶
Woodpecker CI is the self-hosted CI/CD engine for AKKO, replacing GitHub Actions for builds, tests, and deployments. Pipelines run as Kubernetes pods on the same cluster, eliminating external runner dependencies. It integrates with GitHub via OAuth and stores pipeline state in PostgreSQL.
Architecture¶
GitHub (webhooks)
|
+--v-------------------+
| Woodpecker Server |
| (:80 web + API) |
| (:9000 gRPC) |
+--+-------+-----------+
| |
| +----v-----------+
| | PostgreSQL |
| | (pipeline DB) |
| +-----------------+
|
+--v-------------------+
| Woodpecker Agent(s) |
| (2 replicas) |
| spawns k8s pods |
+----------------------+
- Server handles webhooks, web UI, API, and pipeline scheduling
- Agents connect to the server via gRPC and execute pipelines as Kubernetes pods
- PostgreSQL stores pipeline state, build logs, and secrets
- GitHub OAuth for login and repository access
URLs¶
| Mode | URL |
|---|---|
| Kubernetes (k3d) | https://ci.<domain> |
Configuration (Helm values)¶
akko-woodpecker:
enabled: true
server:
image:
repository: woodpeckerci/woodpecker-server
tag: "v3.4.0"
replicas: 1
agent:
image:
repository: woodpeckerci/woodpecker-agent
tag: "v3.4.0"
replicas: 2 # 2 concurrent pipelines
secret: "" # 32+ char shared secret (values-dev-secrets.yaml)
github:
enabled: true
client_id: "" # GitHub OAuth App (values-dev-secrets.yaml)
client_secret: ""
host: "ci.akko.local"
database:
driver: "postgres"
host: "akko-postgresql"
name: "woodpecker"
service:
webPort: 80
grpcPort: 9000
ingress:
enabled: true
host: "ci.akko.local"
resources:
server:
requests: { cpu: 50m, memory: 128Mi }
limits: { cpu: 500m, memory: 512Mi }
agent:
requests: { cpu: 100m, memory: 256Mi }
limits: { cpu: 1, memory: 1Gi }
workspace:
pvcSize: "10Gi"
Health Check¶
Woodpecker server exposes a health endpoint on the web port:
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 15
periodSeconds: 30
readinessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 10
periodSeconds: 10
RBAC (who can access)¶
- GitHub OAuth — users log in with their GitHub account
- Repository permissions — Woodpecker respects GitHub repository access (admin, write, read)
- Admin users — configured via Woodpecker environment variables (first login becomes admin, or set explicitly)
Setup Requirements¶
To enable Woodpecker, you must:
- Create a GitHub OAuth App at
https://github.com/settings/developers - Homepage URL:
https://ci.<domain> - Callback URL:
https://ci.<domain>/authorize - Set credentials in
values-dev-secrets.yaml: - Create the database — the
akko-initjob creates thewoodpeckerdatabase in PostgreSQL
Key Features¶
| Feature | Description |
|---|---|
| Kubernetes-native | Pipelines run as pods, not Docker-in-Docker |
| GitHub integration | OAuth login + webhook-triggered builds |
| Multi-agent | 2+ agents for concurrent pipeline execution |
| PostgreSQL backend | Durable pipeline state and build logs |
| Apache 2.0 | Fully open-source, no license restrictions |
| YAML pipelines | .woodpecker.yml in repo root |
Resource Requirements¶
| Component | Minimum RAM | Recommended |
|---|---|---|
| Server | 128 Mi | 512 Mi |
| Agent (each) | 256 Mi | 1 Gi |
Troubleshooting¶
Agent Cannot Connect to Server¶
Symptoms: Agent logs show connection refused or failed to connect to server.
Cause: The shared secret does not match between server and agent, or the gRPC port (9000) is blocked.
Solution:
# Check agent logs
kubectl logs -n akko deploy/akko-woodpecker-agent --tail=50
# Verify the shared secret matches
kubectl get secret -n akko akko-woodpecker -o yaml | grep agent-secret
# Test gRPC connectivity
kubectl exec -n akko deploy/akko-woodpecker-agent -- nc -zv akko-woodpecker-server 9000
GitHub Webhooks Not Triggering Builds¶
Symptoms: Pushing to a repository does not trigger a Woodpecker pipeline.
Cause: The webhook URL is incorrect, the GitHub OAuth App is misconfigured, or Woodpecker cannot reach the repository.
Solution:
# Check server logs for webhook errors
kubectl logs -n akko deploy/akko-woodpecker-server --tail=100 | grep -i "webhook\|hook\|error"
# Verify the ingress is accessible
kubectl get ingress -n akko | grep woodpecker
# Check GitHub OAuth configuration
kubectl describe deploy -n akko akko-woodpecker-server | grep -i github
Database Connection Failure¶
Symptoms: Server pod enters CrashLoopBackOff. Logs show could not connect to database.
Cause: PostgreSQL is not ready or the woodpecker database does not exist.
Solution:
# Check PostgreSQL status
kubectl get pods -n akko -l app.kubernetes.io/name=akko-postgresql
# Verify the database exists
kubectl exec -n akko deploy/akko-postgresql -- psql -U postgres -c "\l" | grep woodpecker
# If missing, create it
kubectl exec -n akko deploy/akko-postgresql -- psql -U postgres -c "CREATE DATABASE woodpecker;"
# Restart the server
kubectl rollout restart -n akko deploy/akko-woodpecker-server