### Why Woodpecker CI?

Woodpecker CI is a community-driven fork of Drone CI, offering a lightweight yet feature-rich CI/CD solution perfect for developers who want full control over their build infrastructure.

#### Key Advantages

- Lightweight footprint — ideal for VPS
- Container-native — isolated Docker steps
- Simple YAML configuration
- Multi-platform support (Linux, Windows, ARM)
- Active community & regular updates
- No vendor lock-in

#### Supported Git Forges

- GitHub
- GitLab
- Gitea
- Forgejo
- Bitbucket

### Prerequisites

Before beginning, ensure you have:

#### Server Requirements

- RamNode VPS with 2GB+ RAM recommended
- Ubuntu 22.04 or 24.04 LTS
- Root or sudo access
- Domain name pointed to your server

#### Required Ports

- **22/TCP:** SSH access
- **80/TCP:** HTTP traffic
- **443/TCP:** HTTPS traffic

### Update System & Install Utilities

```
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg lsb-release ca-certificates apt-transport-https
```

### Configure Firewall

```
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
```

### Install Docker

Woodpecker runs as Docker containers. Install Docker Engine:

#### Add Docker Repository

```
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

#### Install Docker Engine

```
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

#### Enable Docker & Verify

```
sudo systemctl enable docker
sudo systemctl start docker
docker --version

# Optional: Add user to docker group
sudo usermod -aG docker $USER
newgrp docker
```

### Create OAuth Application

Woodpecker authenticates users through your Git forge. Create an OAuth application:

#### GitHub

Settings → Developer settings → OAuth Apps → New OAuth App

- **Application name:** Woodpecker CI
- **Homepage URL:** https://ci.yourdomain.com
- **Callback URL:** https://ci.yourdomain.com/authorize

#### GitLab

User Settings → Applications

- **Name:** Woodpecker CI
- **Redirect URI:** https://ci.yourdomain.com/authorize
- **Scopes:** api, read_user

#### Gitea/Forgejo

Site Administration → Applications

- **Application Name:** Woodpecker CI
- **Redirect URI:** https://ci.yourdomain.com/authorize

💡 **Tip:** Save the Client ID and Client Secret — you'll need these in the next step.

### Configure Woodpecker Server

Create the configuration directory and Docker Compose file:

#### Create Directory & Generate Secret

```
sudo mkdir -p /opt/woodpecker
cd /opt/woodpecker

# Generate agent secret
openssl rand -hex 32
```

#### Create docker-compose.yml

```
sudo nano docker-compose.yml
```

#### docker-compose.yml

```
version: '3.8'

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    container_name: woodpecker-server
    restart: unless-stopped
    ports:
      - "8000:8000"
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker/
    environment:
      # Server Configuration
      - WOODPECKER_HOST=https://ci.yourdomain.com
      - WOODPECKER_OPEN=true
      - WOODPECKER_ADMIN=your-git-username

# Agent Secret (use the value generated earlier)
      - WOODPECKER_AGENT_SECRET=your-generated-secret-here

# GitHub Configuration
      - WOODPECKER_GITHUB=true
      - WOODPECKER_GITHUB_CLIENT=your-github-client-id
      - WOODPECKER_GITHUB_SECRET=your-github-client-secret

# GitLab Configuration (uncomment for GitLab)
      # - WOODPECKER_GITLAB=true
      # - WOODPECKER_GITLAB_URL=https://gitlab.com
      # - WOODPECKER_GITLAB_CLIENT=your-gitlab-client-id
      # - WOODPECKER_GITLAB_SECRET=your-gitlab-client-secret

# Gitea Configuration (uncomment for Gitea)
      # - WOODPECKER_GITEA=true
      # - WOODPECKER_GITEA_URL=https://gitea.yourdomain.com
      # - WOODPECKER_GITEA_CLIENT=your-gitea-client-id
      # - WOODPECKER_GITEA_SECRET=your-gitea-client-secret

woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    container_name: woodpecker-agent
    restart: unless-stopped
    depends_on:
      - woodpecker-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_AGENT_SECRET=your-generated-secret-here
      - WOODPECKER_MAX_WORKFLOWS=4

volumes:
  woodpecker-server-data:
```

### Nginx & SSL Configuration

Set up Nginx as a reverse proxy with SSL:

#### Install Nginx

```
sudo apt install -y nginx
```

#### Create Nginx Configuration

```
sudo nano /etc/nginx/sites-available/woodpecker
```

#### Nginx Server Block

```
server {
    listen 80;
    server_name ci.yourdomain.com;

location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}
```

#### Enable Site & Get SSL Certificate

```
sudo ln -s /etc/nginx/sites-available/woodpecker /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

# Install Certbot and get SSL certificate
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d ci.yourdomain.com

# Verify auto-renewal
sudo certbot renew --dry-run
```

### Launch Woodpecker

Start the Woodpecker server and agent:

```
cd /opt/woodpecker
sudo docker compose up -d

# Verify containers are running
docker compose ps

# Check logs for any issues
docker compose logs -f woodpecker-server
```

✅ **Success:** Navigate to `https://ci.yourdomain.com` and login with your Git forge credentials.

### Create Your First Pipeline

Create a `.woodpecker.yml` file in your repository root:

#### Node.js Pipeline Example

```
steps:
  - name: install
    image: node:20-alpine
    commands:
      - npm ci

- name: lint
    image: node:20-alpine
    commands:
      - npm run lint

- name: test
    image: node:20-alpine
    commands:
      - npm test

- name: build
    image: node:20-alpine
    commands:
      - npm run build
```

#### Python Pipeline Example

```
steps:
  - name: install
    image: python:3.12-slim
    commands:
      - pip install -r requirements.txt

- name: lint
    image: python:3.12-slim
    commands:
      - pip install flake8
      - flake8 .

- name: test
    image: python:3.12-slim
    commands:
      - pip install pytest
      - pytest
```

💡 **Tip:** Enable your repository in the Woodpecker UI, then commit and push the pipeline file to trigger your first build.

### Advanced Configuration

Explore advanced pipeline features:

#### Using Secrets

Secrets in Pipelines

```
steps:
  - name: deploy
    image: alpine
    secrets: [docker_username, docker_password]
    commands:
      - echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
      - docker push myregistry/myapp:latest
```

#### Conditional Execution

Branch-based Deployment

```
steps:
  - name: deploy-staging
    image: alpine
    commands:
      - ./deploy.sh staging
    when:
      branch: develop

- name: deploy-production
    image: alpine
    commands:
      - ./deploy.sh production
    when:
      branch: main
      event: push
```

#### Matrix Builds

Test Multiple Versions

```
matrix:
  NODE_VERSION:
    - 18
    - 20
    - 22

steps:
  - name: test
    image: node:${NODE_VERSION}-alpine
    commands:
      - npm ci
      - npm test
```

#### Services

Database for Integration Tests

```
services:
  - name: database
    image: postgres:16
    environment:
      - POSTGRES_USER=test
      - POSTGRES_PASSWORD=test
      - POSTGRES_DB=testdb

steps:
  - name: test
    image: node:20-alpine
    environment:
      - DATABASE_URL=postgres://test:test@database:5432/testdb
    commands:
      - npm ci
      - npm test
```

### Security Best Practices

Secure your Woodpecker installation:

#### Security Recommendations

- **Disable Open Registration:** Set `WOODPECKER_OPEN=false` after initial setup
- **Configure User Allowlist:** Use `WOODPECKER_ORGS=your-organization`
- **Use Repository Trust Wisely:** Only mark repos as trusted when necessary
- **Rotate Secrets Regularly:** Regenerate agent secret and OAuth credentials
- **Network Isolation:** Place agent on internal network with limited access

### Troubleshooting

#### Common Issues

- **Pipeline stuck in pending:** Verify agent is connected and running
- **OAuth callback errors:** Ensure callback URL matches exactly (including https and /authorize)
- **Agent cannot pull images:** Confirm Docker is running and has socket access
- **SSL certificate issues:** Verify Certbot renewal is working
- **Build containers cannot access network:** Check Docker network and firewall rules

#### Maintenance Commands

```
# View logs
docker compose logs -f
docker compose logs -f woodpecker-server
docker compose logs -f woodpecker-agent

# Update Woodpecker
cd /opt/woodpecker
docker compose pull
docker compose up -d

# Monitor resource usage
docker stats woodpecker-server woodpecker-agent

# Backup data
docker run --rm -v woodpecker-server-data:/data -v $(pwd):/backup alpine tar czf /backup/woodpecker-backup-$(date +%Y%m%d).tar.gz /data
```

### Next Steps

Your Woodpecker CI is now ready! Consider these next steps:

- Add additional agents for parallel builds
- Integrate with container registries for automated deployments
- Connect multiple Git forges to centralize CI/CD
- Set up notifications (Slack, Discord, email)
- Configure cron jobs for scheduled builds

For advanced configurations, consult the official [Woodpecker documentation](https://woodpecker-ci.org/docs).
