857 lines
20 KiB
Markdown
Raw Permalink Normal View History

2026-01-12 03:36:55 +00:00
# Woodpecker CI Setup Guide for VAPORA
Comprehensive guide for setting up and using Woodpecker CI/CD pipelines for VAPORA provisioning.
## Overview
Woodpecker is a self-hosted, container-based CI/CD platform compatible with Docker Compose and Kubernetes. This guide covers VAPORA's 5 production-ready Woodpecker pipelines as an alternative to GitHub Actions.
### Key Features
- **Self-Hosted**: Deploy on your own infrastructure (Docker, Kubernetes, VMs)
- **Container-Based**: Runs pipeline steps in isolated Docker containers
- **YAML Pipelines**: Simple YAML syntax for defining workflows
- **Flexible Triggers**: Git webhooks, cron schedules, manual promotions
- **Secret Management**: Built-in secret storage with environment variable injection
- **Artifact Handling**: Workspace persistence across stages
- **Multi-Pipeline Support**: Run multiple pipelines in parallel
### VAPORA Woodpecker Pipelines
| Pipeline | Purpose | Trigger | Duration |
|----------|---------|---------|----------|
| **validate-and-build.yml** | Validate configs, generate artifacts | Push, PR, manual | ~5 min |
| **deploy-docker.yml** | Deploy to Docker Compose | Manual, after validation | ~3 min |
| **deploy-kubernetes.yml** | Deploy to Kubernetes | Manual with dry-run | ~5-10 min |
| **health-check.yml** | Continuous monitoring | Cron (15min, 6hr), manual | ~5 min |
| **rollback.yml** | Safe rollback with verification | Manual only | ~3-5 min |
---
## Prerequisites
### Infrastructure Requirements
**Minimum**:
- Linux server (Ubuntu 20.04+, Debian 11+, CentOS 8+)
- Docker 20.10+ installed and running
- 2 CPU cores, 4GB RAM, 20GB disk
**Recommended for Production**:
- Kubernetes cluster (v1.24+)
- 4+ CPU cores, 8GB+ RAM, 50GB+ disk
- Separate storage for workspace/artifacts
- SSL/TLS for Woodpecker UI
### Prerequisites to Install
```bash
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y docker.io docker-compose git curl wget jq
# Start Docker daemon
sudo systemctl start docker
sudo systemctl enable docker
# Add current user to docker group (after logout/login required)
sudo usermod -aG docker $USER
```
### Git Repository
- GitLab, GitHub, Gitea, or Gogs repository
- Repository webhook URL accessible from Woodpecker server
- OAuth token for repository access (for most Git services)
---
## Installation
### Option 1: Docker Compose Installation (Recommended for Testing)
```bash
# Create Woodpecker directory
mkdir -p ~/woodpecker && cd ~/woodpecker
# Create docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
woodpecker-server:
image: woodpeckerci/woodpecker-server:latest
ports:
- "80:8000"
- "443:443"
environment:
- WOODPECKER_ADMIN_USER=admin
- WOODPECKER_ADMIN_PASSWORD=admin123
- WOODPECKER_GITHUB_SERVER=https://github.com
- WOODPECKER_GITHUB_CLIENT_ID=<YOUR_GITHUB_CLIENT_ID>
- WOODPECKER_GITHUB_CLIENT_SECRET=<YOUR_GITHUB_CLIENT_SECRET>
- WOODPECKER_RPC_SECRET=<GENERATE_WITH: head -c 32 /dev/urandom | base64>
- WOODPECKER_LOG_LEVEL=info
volumes:
- woodpecker-data:/var/lib/woodpecker
restart: always
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:latest
environment:
- WOODPECKER_SERVER=http://woodpecker-server:9000
- WOODPECKER_AGENT_SECRET=<SAME_AS_RPC_SECRET>
- WOODPECKER_LOG_LEVEL=info
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always
depends_on:
- woodpecker-server
volumes:
woodpecker-data:
EOF
# Generate RPC secret
RPC_SECRET=$(head -c 32 /dev/urandom | base64)
echo "RPC_SECRET=$RPC_SECRET"
# Start services
docker-compose up -d
# Logs
docker-compose logs -f
```
### Option 2: Kubernetes Deployment
Create `woodpecker-deployment.yaml`:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: woodpecker
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: woodpecker-server
namespace: woodpecker
spec:
replicas: 1
selector:
matchLabels:
app: woodpecker-server
template:
metadata:
labels:
app: woodpecker-server
spec:
containers:
- name: server
image: woodpeckerci/woodpecker-server:latest
ports:
- containerPort: 8000
- containerPort: 9000
env:
- name: WOODPECKER_ADMIN_USER
value: "admin"
- name: WOODPECKER_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: woodpecker-secrets
key: admin-password
- name: WOODPECKER_RPC_SECRET
valueFrom:
secretKeyRef:
name: woodpecker-secrets
key: rpc-secret
- name: WOODPECKER_GITHUB_CLIENT_ID
valueFrom:
secretKeyRef:
name: woodpecker-secrets
key: github-client-id
- name: WOODPECKER_GITHUB_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: woodpecker-secrets
key: github-client-secret
volumeMounts:
- name: woodpecker-data
mountPath: /var/lib/woodpecker
volumes:
- name: woodpecker-data
persistentVolumeClaim:
claimName: woodpecker-pvc
---
apiVersion: v1
kind: Service
metadata:
name: woodpecker-server
namespace: woodpecker
spec:
selector:
app: woodpecker-server
ports:
- name: ui
port: 8000
targetPort: 8000
- name: rpc
port: 9000
targetPort: 9000
type: LoadBalancer
```
Deploy:
```bash
# Create secrets
kubectl create secret generic woodpecker-secrets \
-n woodpecker \
--from-literal=admin-password=YOUR_PASSWORD \
--from-literal=rpc-secret=$(head -c 32 /dev/urandom | base64) \
--from-literal=github-client-id=YOUR_CLIENT_ID \
--from-literal=github-client-secret=YOUR_CLIENT_SECRET
# Apply deployment
kubectl apply -f woodpecker-deployment.yaml
# Check status
kubectl get pods -n woodpecker
kubectl port-forward -n woodpecker svc/woodpecker-server 8000:8000
```
---
## GitHub Integration Setup
### Step 1: Create GitHub OAuth App
1. Go to GitHub → Settings → Developer settings → OAuth Apps
2. Click "New OAuth App"
3. Fill in:
- **Application name**: `VAPORA Woodpecker`
- **Homepage URL**: `https://woodpecker.your-domain.com`
- **Authorization callback URL**: `https://woodpecker.your-domain.com/authorize`
4. Copy `Client ID` and `Client Secret`
### Step 2: Configure Woodpecker
For Docker Compose:
```bash
# Update docker-compose.yml environment variables
WOODPECKER_GITHUB_CLIENT_ID=your_client_id_here
WOODPECKER_GITHUB_CLIENT_SECRET=your_client_secret_here
WOODPECKER_RPC_SECRET=$(head -c 32 /dev/urandom | base64)
```
For Kubernetes:
```bash
kubectl patch secret woodpecker-secrets -n woodpecker \
--type=merge \
-p '{"data":{"github-client-id":"'$(echo -n YOUR_CLIENT_ID | base64)'","github-client-secret":"'$(echo -n YOUR_CLIENT_SECRET | base64)'"}}'
```
### Step 3: Repository Setup
1. Access Woodpecker UI: `http://localhost:8000` (or your domain)
2. Login with admin credentials
3. Go to Admin → Repositories
4. Authorize your VAPORA repository
5. Enable webhooks by visiting `http://your-github.com/settings/hooks`
---
## Secret Management
### Adding Secrets
#### Via Woodpecker UI
1. Go to repository → Settings → Secrets
2. Click "Add secret"
3. Name: `SECRET_NAME`
4. Value: Your secret value
5. Save
#### Via CLI
```bash
# Install woodpecker-cli
go install github.com/woodpeckerci/woodpecker/cmd/woodpecker-cli@latest
# Login
woodpecker-cli login -s http://woodpecker-server:8000 \
-u admin \
-p admin_password
# Add secret
woodpecker-cli secret add \
-r owner/repo \
-n KUBE_CONFIG_STAGING \
-v "$(cat ~/.kube/config | base64)"
```
### Required VAPORA Secrets
```bash
# Kubernetes kubeconfigs (base64 encoded)
KUBE_CONFIG_STAGING # Staging cluster kubeconfig
KUBE_CONFIG_PRODUCTION # Production cluster kubeconfig
# Optional: Slack notifications
SLACK_WEBHOOK # General notifications webhook
SLACK_WEBHOOK_ALERTS # Critical alerts webhook
# Optional: Docker registry
DOCKER_USERNAME # Docker Hub username
DOCKER_PASSWORD # Docker Hub access token
```
### Encoding Kubeconfig
```bash
# Get kubeconfig and encode as base64
cat ~/.kube/config | base64 > kube_config_base64.txt
# Use the output in Woodpecker secret UI
cat kube_config_base64.txt
# Verify locally before adding to Woodpecker
echo "$(cat kube_config_base64.txt)" | base64 -d | kubectl cluster-info
```
---
## Pipeline Triggers
### Automatic Triggers
Pipelines trigger automatically when:
```yaml
# On push to main/develop branches (if provisioning files change)
trigger:
event: [push]
branch: [main, develop]
paths:
include:
- provisioning/schemas/**
- provisioning/scripts/**
# On pull requests
trigger:
event: [pull_request]
branch: [main, develop]
```
### Manual Triggers (Promotions)
Manually trigger from UI:
1. Go to repository → Active builds
2. Find a completed build
3. Click "Promote"
4. Select pipeline: `deploy-docker`, `deploy-kubernetes`, etc.
5. Set deployment parameters:
- Mode: `solo`, `multiuser`, `enterprise`
- Environment: `staging`, `production`
- Dry-run: `true`/`false`
6. Click "Promote"
### Scheduled Triggers (Cron)
Health check pipeline runs on schedule:
```yaml
trigger:
cron:
- "*/15 * * * *" # Every 15 minutes
- "0 */6 * * *" # Every 6 hours
```
---
## Deployment Workflows
### Workflow 1: Local Development
```
Developer pushes to feature branch
[Validate & Build] runs automatically
Review artifacts in workspace
[Deploy to Docker] manually for local testing
Test with docker compose
Create PR
```
### Workflow 2: Staging Deployment
```
Merge PR to develop
[Validate & Build] runs automatically
Download artifacts from workspace
Manually run [Deploy to Kubernetes]
- Mode: multiuser
- Environment: staging
- Dry-run: true
Review dry-run output
Run again with dry-run: false
[Health Check] verifies deployment
Staging live
```
### Workflow 3: Production Deployment
```
Code review approved
Merge to main
[Validate & Build] runs automatically
Manually run [Deploy to Kubernetes]
- Mode: enterprise
- Environment: production
- Dry-run: true
Carefully review changes
Run with dry-run: false
[Health Check] monitoring (auto every 6 hours)
Production deployment complete
```
### Workflow 4: Emergency Rollback
```
Production issue detected
[Health Check] alerts in Slack
Manually run [Rollback Deployment]
- Environment: production
Services restored
Investigate root cause
```
---
## Configuration Environment Variables
### For validate-and-build.yml
```bash
ARTIFACTS_DIR=provisioning/artifacts # Output directory for configs
LOG_DIR=provisioning/logs # Output directory for logs
```
### For deploy-docker.yml
```bash
ARTIFACTS_DIR=provisioning/artifacts
LOGS_DIR=provisioning/logs
```
### For deploy-kubernetes.yml
```bash
ARTIFACTS_DIR=provisioning/artifacts
LOGS_DIR=provisioning/logs
VAPORA_NAMESPACE=vapora # Kubernetes namespace
```
### For health-check.yml
```bash
LOGS_DIR=provisioning/logs
VAPORA_NAMESPACE=vapora
```
---
## Monitoring & Logs
### Via Woodpecker UI
1. Go to repository → Active/Previous builds
2. Click a build to see full pipeline execution
3. Click a stage to see detailed logs
4. Download logs or artifacts
### Via CLI
```bash
# List recent builds
woodpecker-cli build list -r owner/repo
# View build details
woodpecker-cli build view -r owner/repo -b <BUILD_NUMBER>
# Watch build in real-time
woodpecker-cli build watch -r owner/repo -b <BUILD_NUMBER>
# Get build logs
woodpecker-cli build logs -r owner/repo -b <BUILD_NUMBER>
```
### Logs Location
All logs stored in workspace:
```bash
provisioning/logs/
├── validate-solo.log
├── validate-multiuser.log
├── validate-enterprise.log
├── build.log
├── docker/
│ ├── backend.log
│ ├── frontend.log
│ └── all-services.log
├── kubernetes/
│ ├── backend.log
│ ├── agents.log
│ ├── llm-router.log
│ └── events.log
└── health-checks/
├── docker-endpoints.log
├── k8s-deployments.log
└── HEALTH_REPORT.md
```
---
## Slack Integration
### Setup Webhook
1. Go to Slack workspace → Apps → Custom Integrations
2. Create Incoming Webhook
3. Select channel: `#deployments`
4. Copy Webhook URL
5. Add to Woodpecker secret: `SLACK_WEBHOOK`
### Slack Messages
**Build Success**:
```
✅ VAPORA Artifact Build Complete
Artifacts ready for deployment
```
**Docker Deploy Success**:
```
✅ VAPORA Docker deployment successful!
Mode: multiuser | Environment: staging
```
**Kubernetes Deploy Success**:
```
✅ VAPORA Kubernetes deployment successful!
Mode: enterprise | Environment: production
```
**Health Check Alert**:
```
❌ VAPORA Health Check Failed
Target: kubernetes
```
**Rollback Alert**:
```
🔙 VAPORA Rollback Executed
Environment: production
Verify service health immediately
```
---
## Troubleshooting
### Pipeline Not Triggering
**Problem**: Push doesn't trigger validate-and-build
**Solution**:
1. Check repository is authorized in Woodpecker
2. Verify webhook exists in GitHub settings
3. Check file paths in `trigger.paths.include` match your changes
4. Enable debug logging: `WOODPECKER_LOG_LEVEL=debug`
### Secret Not Found
**Problem**: `Secret not found` error in logs
**Solution**:
1. Verify secret exists in repository settings
2. Check exact spelling (case-sensitive)
3. Ensure secret value is not empty
4. Test secret value locally before adding
### Kubeconfig Decode Error
**Problem**: `base64: invalid input` during kubectl setup
**Solution**:
```bash
# Test locally first
echo "$(cat kube_config_base64.txt)" | base64 -d | kubectl cluster-info
# If it fails, re-encode
cat ~/.kube/config | base64 | pbcopy # macOS
# Update secret in Woodpecker UI
```
### Docker Connection Failed
**Problem**: `Cannot connect to Docker daemon` in deploy-docker stage
**Solution**:
1. Ensure Docker socket mounted in agent: `-v /var/run/docker.sock:/var/run/docker.sock`
2. Verify Docker daemon running: `docker ps`
3. Check volume permissions: `sudo chmod 666 /var/run/docker.sock`
### Deployment Hangs
**Problem**: Pipeline stage times out waiting for rollout
**Solution**:
1. Check pod logs: `kubectl logs -n vapora <pod>`
2. Describe pod: `kubectl describe pod -n vapora <pod>`
3. Increase timeout in pipeline stage
4. Check resource requests/limits
5. Verify cluster has sufficient resources
### Workspace Persistence Issues
**Problem**: Files from one stage not available in next stage
**Solution**:
1. Create file in correct location (workspace root or subdirectory)
2. Use absolute paths: `${LOGS_DIR}/output.log`
3. Check artifact uploads in "publish" stages
4. Verify docker volumes: `docker volume ls`
---
## Advanced Configuration
### Multi-Agent Setup
For distributed build execution:
```yaml
# Agent 1 (Docker builds)
environment:
- WOODPECKER_FILTER_LABELS=type:docker
# Agent 2 (Kubernetes operations)
environment:
- WOODPECKER_FILTER_LABELS=type:kubernetes
# Agent 3 (Health checks)
environment:
- WOODPECKER_FILTER_LABELS=type:monitoring
```
### Pipeline Concurrency Control
Limit concurrent executions:
```yaml
concurrency:
limit: 2 # Max 2 concurrent builds
timeout_minutes: 60 # Timeout after 60 minutes
```
### Conditional Stage Execution
Run stage only if conditions met:
```yaml
when:
evaluate: 'return build.Deploy_Environment == "production"'
```
---
## Comparison: Woodpecker vs GitHub Actions
| Feature | Woodpecker | GitHub Actions |
|---------|-----------|---|
| **Hosting** | Self-hosted | GitHub-hosted |
| **YAML Format** | Similar | Familiar |
| **Manual Dispatch** | Promotion UI | workflow_dispatch |
| **Scheduled Workflows** | Cron syntax | schedule syntax |
| **Artifact Storage** | Workspace persistence | upload-artifact action |
| **PR Comments** | Limited | ✓ Native |
| **Slack Integration** | Via webhooks | Actions |
| **Secret Management** | Built-in UI | Built-in |
| **Free for Public** | Self-hosted cost | ✓ Free |
| **Concurrency Control** | ✓ Advanced | ✓ Concurrency groups |
| **Deployment Safety** | Dry-run support | Deployment protection |
### When to Use Woodpecker
- ✓ You want full control over CI/CD infrastructure
- ✓ You need to run on-premise for compliance
- ✓ You prefer self-hosted solutions
- ✓ You have multiple repositories needing unified CI/CD
- ✓ You want to avoid vendor lock-in
### When to Use GitHub Actions
- ✓ You want GitHub-hosted runners (no infrastructure)
- ✓ You prefer tight GitHub integration
- ✓ You want PR comments and GitHub UI integration
- ✓ You're already using GitHub workflow syntax
---
## First Deployment with Woodpecker
### Step 1: Enable Woodpecker for Repository
1. Access Woodpecker UI
2. Click "Administration" → "Repositories"
3. Find VAPORA repository
4. Click to enable
5. Grant webhook access
### Step 2: Create Test Branch
```bash
git checkout -b test/woodpecker-setup
echo "# Woodpecker Test" >> README.md
git add README.md
git commit -m "test: trigger Woodpecker"
git push origin test/woodpecker-setup
```
### Step 3: Monitor Pipeline
1. Go to Woodpecker → repository
2. See "Validate & Build" trigger automatically
3. Monitor pipeline execution
4. Check logs for each stage
### Step 4: Download Artifacts
1. In completed build, find "Files" section
2. Access workspace artifacts:
- `provisioning/artifacts/` - Generated configs
- `provisioning/logs/` - Pipeline logs
### Step 5: Test Docker Deployment
1. Download artifacts
2. Go to Woodpecker → repository
3. Click "Promote" on validated build
4. Select "deploy-docker"
5. Set:
- Mode: `multiuser`
- Environment: `staging`
- Dry-run: `true`
6. Monitor deployment
### Step 6: Create Pull Request
```bash
git push origin test/woodpecker-setup
# Create PR on GitHub
```
---
## Security Best Practices
**Do**:
- Use environment-specific kubeconfigs
- Rotate secrets regularly
- Run health checks after deployments
- Enable dry-run by default
- Keep logs for audit trail
- Use RBAC in Kubernetes
- Monitor Slack alerts
- Test on staging first
**Don't**:
- Commit secrets to repository
- Deploy directly to production without testing
- Disable dry-run validation
- Skip health checks
- Use same credentials for all environments
- Share Woodpecker admin credentials
- Keep old pipelines around
- Ignore Slack alerts
---
## Support & Resources
- **Woodpecker Docs**: https://woodpecker-ci.org/docs/intro
- **VAPORA Docs**: See `./../docs/` directory
- **GitHub Actions Guide**: `./../.github/GITHUB_ACTIONS_GUIDE.md`
- **Nushell Scripts**: `provisioning/scripts/*.nu`
---
## Files Created
```
.woodpecker/
├── validate-and-build.yml (410 lines)
├── deploy-docker.yml (340 lines)
├── deploy-kubernetes.yml (380 lines)
├── health-check.yml (290 lines)
├── rollback.yml (330 lines)
└── SETUP.md (This file)
Total: 5 pipelines + comprehensive documentation
```
---
## Next Steps
1. ✅ Install and configure Woodpecker server
2. → Integrate with GitHub repository
3. → Add secrets for Kubernetes kubeconfigs
4. → Configure Slack webhooks (optional)
5. → Run first validation pipeline
6. → Test Docker deployment
7. → Test Kubernetes deployment
8. → Configure health checks
9. → Document team runbooks
10. → Deploy to production
---
**Generated**: 2026-01-12
**Status**: Production-ready
**Pipelines**: 5 (validate-and-build, deploy-docker, deploy-kubernetes, health-check, rollback)
**Documentation**: Complete