Overview

Woodpecker CI is a lightweight, cloud-native continuous integration and deployment system built on Docker. This document covers the deployment and configuration of Woodpecker CI using Docker Compose with Traefik as a reverse proxy.

Service Details

ComponentValue
URLhttps://ci.trymondo.com
Server Imagewoodpeckerci/woodpecker-server:v3.5.2
Agent Imagewoodpeckerci/woodpecker-agent:v3.5.2
DatabasePostgreSQL 17
Serviceswoodpecker-server, woodpecker-agent, woodpecker-db
Networkswoodpecker-net, traefik-net
AuthenticationGitHub OAuth

Architecture

The deployment consists of three main components:

  1. Woodpecker Server: The core service that manages the UI, API, and orchestrates CI jobs
  2. Woodpecker Agent: Executes CI jobs in containers
  3. PostgreSQL Database: Stores all Woodpecker CI data
                 ┌─────────────┐
                 │   Traefik   │
                 └─────────────┘

                       │ HTTP/HTTPS

              ┌─────────────────────┐
              │  Woodpecker Server  │
              └─────────────────────┘
                ↑               ↑
    gRPC (9000) │               │ Database
                ↓               ↓
      ┌───────────────┐    ┌────────────┐
      │ Woodpecker    │    │ PostgreSQL │
      │ Agent         │    │            │
      └───────────────┘    └────────────┘


      ┌──────────────┐
      │ Docker API   │
      └──────────────┘

Prerequisites

  • Docker Engine (24.0+)
  • Docker Compose v2
  • Traefik reverse proxy configured and running
  • External networks: woodpecker-net and traefik-net
  • GitHub OAuth application
  • DNS configured for ci.trymondo.com

Configuration Preparation

GitHub OAuth Setup

  1. Create a GitHub OAuth application at https://github.com/settings/applications/new
  2. Set the callback URL to https://ci.trymondo.com/login
  3. Note the Client ID and Client Secret for your .env file

Environment Variables

Create a .env file with the following variables:

# Woodpecker Configuration
WOODPECKER_HOST=https://ci.trymondo.com
WOODPECKER_OPEN=true
WOODPECKER_GITHUB_CLIENT=your_github_client_id
WOODPECKER_GITHUB_SECRET=your_github_client_secret
WOODPECKER_AGENT_SECRET=generate_a_secure_random_string
WOODPECKER_ADMIN=github_username

# Database Configuration
POSTGRES_PASSWORD=secure_postgres_password
openssl rand -hex 32

Deployment Configuration

Docker Compose File

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:v3.5.2
    container_name: woodpecker-server
    restart: unless-stopped
    expose:
      - '8000'
      - '9000'
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker
    environment:
      - WOODPECKER_OPEN=${WOODPECKER_OPEN:-true}
      - WOODPECKER_HOST=${WOODPECKER_HOST?Variable WOODPECKER_HOST is not set}
      - WOODPECKER_GITHUB=true
      - WOODPECKER_GITHUB_CLIENT=${WOODPECKER_GITHUB_CLIENT?Variable WOODPECKER_GITHUB_CLIENT is not set}
      - WOODPECKER_GITHUB_SECRET=${WOODPECKER_GITHUB_SECRET?Variable WOODPECKER_GITHUB_SECRET is not set}
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET?Variable WOODPECKER_AGENT_SECRET is not set}
      - WOODPECKER_DATABASE_DRIVER=postgres
      - WOODPECKER_DATABASE_DATASOURCE=postgres://woodpecker:${POSTGRES_PASSWORD?Variable POSTGRES_PASSWORD is not set}@woodpecker-db:5432/woodpecker?sslmode=disable
      - WOODPECKER_GITHUB_URL=https://github.com
      - WOODPECKER_ADMIN=${WOODPECKER_ADMIN?Variable WOODPECKER_ADMIN is not set}
    networks:
      - woodpecker-net
      - traefik-net
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik-net
      - traefik.http.services.woodpecker.loadbalancer.server.port=8000
      - traefik.http.routers.woodpecker-secure.rule=Host(`ci.trymondo.com`)
      - traefik.http.routers.woodpecker-secure.entrypoints=websecure
      - traefik.http.routers.woodpecker-secure.service=woodpecker
      - traefik.http.routers.woodpecker-secure.tls=true
      - traefik.http.routers.woodpecker-secure.tls.certresolver=production
      - traefik.http.middlewares.woodpecker-redirect.redirectscheme.scheme=https
      - traefik.http.middlewares.woodpecker-redirect.redirectscheme.permanent=true
      - traefik.http.routers.woodpecker-http.rule=Host(`ci.trymondo.com`)
      - traefik.http.routers.woodpecker-http.entrypoints=web
      - traefik.http.routers.woodpecker-http.service=woodpecker
      - traefik.http.routers.woodpecker-http.middlewares=woodpecker-redirect@docker

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:v3.5.2
    container_name: woodpecker-agent
    restart: unless-stopped
    depends_on:
      - woodpecker-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:rw
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_GRPC_SECURE=false
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET?Variable WOODPECKER_AGENT_SECRET is not set}
    networks:
      - woodpecker-net

  woodpecker-db:
    image: postgres:17
    container_name: woodpecker-db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=woodpecker
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=woodpecker
    volumes:
      - woodpecker-db-data:/var/lib/postgresql/data
    networks:
      - woodpecker-net

volumes:
  woodpecker-server-data:
  woodpecker-db-data:

networks:
  woodpecker-net:
    external: true
  traefik-net:
    external: true

Network Configuration

Before deployment, ensure the required networks exist:

docker network create woodpecker-net
docker network create traefik-net

Deployment Instructions

  1. Create the deployment directory:

    mkdir -p /opt/apps/woodpecker
    
  2. Create the docker-compose.yml and .env files:

    nano /opt/apps/woodpecker/docker-compose.yml
    nano /opt/apps/woodpecker/.env
    
  3. Deploy the service:

    cd /opt/apps/woodpecker
    docker compose up -d
    
  4. Verify all services are running:

    docker compose ps
    

Traefik Integration Details

The Woodpecker server is configured with the following Traefik settings:

  • Host Rule: ci.trymondo.com
  • Entrypoints: websecure (HTTPS on port 443), web (HTTP on port 80 with redirect to HTTPS)
  • TLS: Enabled with production certificate resolver
  • Backend Port: 8000 (Woodpecker Web UI)
  • Middleware: HTTP to HTTPS redirect for enhanced security

Pipeline Configuration

Basic .woodpecker.yml Example

Create a .woodpecker.yml file in the root of your GitHub repository:

pipeline:
  build:
    image: node:20
    commands:
      - npm install
      - npm run build
      - npm test

  docker:
    image: plugins/docker
    settings:
      registry: registry.example.com
      repo: registry.example.com/myapp
      tags: latest
      username:
        from_secret: docker_username
      password:
        from_secret: docker_password
    when:
      branch: main

Secrets Management

To add secrets to your Woodpecker CI projects:

  1. Navigate to your repository in the Woodpecker UI
  2. Go to Settings > Secrets
  3. Add required secrets (e.g., docker_username, docker_password)

Scaling and Performance

Additional Agents

To scale out CI capacity, you can add more agents:

woodpecker-agent-2:
  image: woodpeckerci/woodpecker-agent:v3.5.2
  container_name: woodpecker-agent-2
  restart: unless-stopped
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:rw
  environment:
    - WOODPECKER_SERVER=woodpecker-server:9000
    - WOODPECKER_GRPC_SECURE=false
    - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
  networks:
    - woodpecker-net

Resource Constraints

For improved stability, consider adding resource constraints:

deploy:
  resources:
    limits:
      cpus: '2.0'
      memory: 2G

Maintenance

Backup Strategy

Back up Woodpecker CI regularly:

  1. Database backup:

    docker compose exec woodpecker-db pg_dump -U woodpecker woodpecker > woodpecker_backup_$(date +%Y%m%d).sql
    
  2. Volume backup using Restic/Backrest:

    • woodpecker-server-data (contains server state)
    • woodpecker-db-data (contains database files)

Updates

To update Woodpecker CI:

  1. Update the image tags in docker-compose.yml

  2. Apply the update:

    docker compose pull
    docker compose up -d
    
  3. Check logs for any issues:

    docker compose logs
    

Troubleshooting

Server Startup Issues

If the server fails to start:

  1. Check environment variables:

    docker compose logs woodpecker-server | grep "required key"
    
  2. Verify database connection:

    docker compose logs woodpecker-server | grep "database"
    

Agent Connection Problems

If agents can’t connect to the server:

  1. Check agent logs:

    docker compose logs woodpecker-agent
    
  2. Verify agent secret is consistent between server and agent

  3. Check network connectivity between containers:

    docker compose exec woodpecker-agent ping woodpecker-server
    

GitHub Integration Issues

If GitHub integration is not working:

  1. Verify OAuth callback URL is correctly set to https://ci.trymondo.com/login

  2. Check GitHub client ID and secret in environment variables

  3. Examine server logs for OAuth-related errors:

    docker compose logs woodpecker-server | grep -i "github"
    

Security Considerations

  • Agent Secret: Use a strong, randomly generated secret for agent authentication
  • Admin Access: Limit admin access to specific GitHub usernames
  • Docker Socket: The agent has access to the Docker socket, which grants significant privileges
  • HTTPS: Enforce HTTPS-only access through Traefik
  • Network Isolation: Use separate networks for communication between services

Additional Resources

Pipeline Examples

Node.js Application

pipeline:
  test:
    image: node:20
    commands:
      - npm install
      - npm test

Docker Build and Push

pipeline:
  build:
    image: plugins/docker
    settings:
      registry: docker.io
      repo: myuser/myapp
      tags: latest
      username:
        from_secret: docker_username
      password:
        from_secret: docker_password

Multi-stage Pipeline with Approval

pipeline:
  test:
    image: golang:1.21
    commands:
      - go test ./...

  build:
    image: golang:1.21
    commands:
      - go build -o myapp

  deploy:
    image: plugins/ssh
    settings:
      host: production.example.com
      user: deploy
      key:
        from_secret: ssh_key
      script:
        - ./deploy.sh
    when:
      status: success
      branch: main
    approval:
      approved_by:
        - admin_user

Was this page helpful?