> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trymondo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Woodpecker

## 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

| Component      | Value                                              |
| -------------- | -------------------------------------------------- |
| URL            | [https://ci.trymondo.com](https://ci.trymondo.com) |
| Server Image   | woodpeckerci/woodpecker-server:v3.5.2              |
| Agent Image    | woodpeckerci/woodpecker-agent:v3.5.2               |
| Database       | PostgreSQL 17                                      |
| Services       | woodpecker-server, woodpecker-agent, woodpecker-db |
| Networks       | woodpecker-net, traefik-net                        |
| Authentication | GitHub 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](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:

```env theme={null}
# 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
```

<Callout type="warning">
  Generate a secure, random string for WOODPECKER\_AGENT\_SECRET. This is used to authenticate agents with the server.
</Callout>

<Callout type="info">
  You can generate a secure random string with:
</Callout>

```bash theme={null}
openssl rand -hex 32
```

## Deployment Configuration

### Docker Compose File

```yaml theme={null}
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:

```bash theme={null}
docker network create woodpecker-net
docker network create traefik-net
```

## Deployment Instructions

1. Create the deployment directory:

   ```bash theme={null}
   mkdir -p /opt/apps/woodpecker
   ```

2. Create the `docker-compose.yml` and `.env` files:

   ```bash theme={null}
   nano /opt/apps/woodpecker/docker-compose.yml
   nano /opt/apps/woodpecker/.env
   ```

3. Deploy the service:

   ```bash theme={null}
   cd /opt/apps/woodpecker
   docker compose up -d
   ```

4. Verify all services are running:

   ```bash theme={null}
   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:

```yaml theme={null}
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:

```yaml theme={null}
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:

```yaml theme={null}
deploy:
  resources:
    limits:
      cpus: '2.0'
      memory: 2G
```

## Maintenance

### Backup Strategy

Back up Woodpecker CI regularly:

1. Database backup:

   ```bash theme={null}
   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:

   ```bash theme={null}
   docker compose pull
   docker compose up -d
   ```

3. Check logs for any issues:

   ```bash theme={null}
   docker compose logs
   ```

## Troubleshooting

### Server Startup Issues

If the server fails to start:

1. Check environment variables:

   ```bash theme={null}
   docker compose logs woodpecker-server | grep "required key"
   ```

2. Verify database connection:

   ```bash theme={null}
   docker compose logs woodpecker-server | grep "database"
   ```

### Agent Connection Problems

If agents can't connect to the server:

1. Check agent logs:

   ```bash theme={null}
   docker compose logs woodpecker-agent
   ```

2. Verify agent secret is consistent between server and agent

3. Check network connectivity between containers:

   ```bash theme={null}
   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:

   ```bash theme={null}
   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

* [Official Woodpecker CI Documentation](https://woodpecker-ci.org/docs/)
* [Woodpecker CI GitHub Repository](https://github.com/woodpecker-ci/woodpecker)
* [Traefik Documentation](https://doc.traefik.io/traefik/)
* [PostgreSQL Documentation](https://www.postgresql.org/docs/)

## Pipeline Examples

### Node.js Application

```yaml theme={null}
pipeline:
  test:
    image: node:20
    commands:
      - npm install
      - npm test
```

### Docker Build and Push

```yaml theme={null}
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

```yaml theme={null}
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
```
