Skip to content

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:

  1. Create a GitHub OAuth App at https://github.com/settings/developers
  2. Homepage URL: https://ci.<domain>
  3. Callback URL: https://ci.<domain>/authorize
  4. Set credentials in values-dev-secrets.yaml:
    akko-woodpecker:
      github:
        client_id: "your-github-oauth-client-id"
        client_secret: "your-github-oauth-client-secret"
      agent:
        secret: "a-random-32-character-shared-secret"
    
  5. Create the database — the akko-init job creates the woodpecker database 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