Woodpecker CI with Gitea
Lightweight CI/CD platform integrated with Gitea for automated builds.
Overview
Woodpecker CI is a lightweight, cloud-native continuous integration and continuous deployment platform built on a simple yet powerful architecture. Originally forked from Drone CI, Woodpecker focuses on simplicity and container-first workflows, using YAML-based pipeline definitions that execute inside Docker containers. The platform follows a distributed architecture with a central server managing builds and lightweight agents executing the actual pipeline steps. This stack combines Woodpecker CI with Gitea, a minimal self-hosted Git service that provides GitHub-like functionality with significantly lower resource requirements. The integration creates a complete DevOps pipeline where Gitea handles source code management, issue tracking, and pull requests, while Woodpecker automatically triggers builds, tests, and deployments based on repository events. PostgreSQL serves as the backbone database for both services, storing repository metadata, build histories, user accounts, and pipeline configurations. This combination delivers enterprise-grade CI/CD capabilities without the overhead of larger platforms like GitLab or Jenkins, making it ideal for teams that need full control over their development infrastructure while maintaining operational simplicity.
Key Features
- Automatic webhook integration between Gitea repositories and Woodpecker pipelines
- YAML-based pipeline definitions with multi-stage builds and parallel execution
- Docker-native build environment with isolated container execution per step
- Built-in secrets management with repository and organization-level scope
- Matrix builds supporting multiple versions, environments, and configurations
- Pull request validation with status checks integrated into Gitea's review process
- Pipeline visualization with real-time logs and build artifact management
- Multi-agent architecture supporting distributed builds across different machines
Common Use Cases
- 1Small to medium development teams requiring private Git hosting with integrated CI/CD
- 2Organizations migrating from hosted services to self-managed infrastructure for compliance
- 3Homelab and personal projects needing automated testing and deployment pipelines
- 4Educational environments teaching DevOps practices without cloud service dependencies
- 5Startups and agencies managing multiple client projects with isolated CI/CD workflows
- 6Companies requiring air-gapped development environments with full source control
- 7Development teams building containerized applications with Docker-based testing
Prerequisites
- Docker and Docker Compose installed with at least 2GB available RAM
- Ports 3000, 8000, and 222 available for Gitea web, Woodpecker web, and Gitea SSH respectively
- Domain names or accessible hostnames for proper OAuth application configuration
- Docker socket access for Woodpecker agent to spawn build containers
- Basic understanding of Git workflows and YAML syntax for pipeline creation
- SSL certificates if deploying with HTTPS in production environments
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 gitea: 3 image: gitea/gitea:latest4 container_name: gitea5 environment: 6 - USER_UID=10007 - USER_GID=10008 - GITEA__database__DB_TYPE=postgres9 - GITEA__database__HOST=db:543210 - GITEA__database__NAME=gitea11 - GITEA__database__USER=gitea12 - GITEA__database__PASSWD=${DB_PASSWORD}13 volumes: 14 - gitea-data:/data15 ports: 16 - "3000:3000"17 - "222:22"18 depends_on: 19 - db20 networks: 21 - woodpecker-network22 restart: unless-stopped2324 woodpecker-server: 25 image: woodpeckerci/woodpecker-server:latest26 container_name: woodpecker-server27 environment: 28 - WOODPECKER_OPEN=true29 - WOODPECKER_HOST=${WOODPECKER_HOST}30 - WOODPECKER_GITEA=true31 - WOODPECKER_GITEA_URL=${GITEA_URL}32 - WOODPECKER_GITEA_CLIENT=${GITEA_CLIENT_ID}33 - WOODPECKER_GITEA_SECRET=${GITEA_CLIENT_SECRET}34 - WOODPECKER_AGENT_SECRET=${AGENT_SECRET}35 - WOODPECKER_DATABASE_DRIVER=postgres36 - WOODPECKER_DATABASE_DATASOURCE=postgres://woodpecker:${WP_DB_PASSWORD}@db:5432/woodpecker?sslmode=disable37 volumes: 38 - woodpecker-data:/var/lib/woodpecker39 ports: 40 - "8000:8000"41 depends_on: 42 - db43 - gitea44 networks: 45 - woodpecker-network46 restart: unless-stopped4748 woodpecker-agent: 49 image: woodpeckerci/woodpecker-agent:latest50 container_name: woodpecker-agent51 environment: 52 - WOODPECKER_SERVER=woodpecker-server:900053 - WOODPECKER_AGENT_SECRET=${AGENT_SECRET}54 - WOODPECKER_MAX_WORKFLOWS=455 volumes: 56 - /var/run/docker.sock:/var/run/docker.sock57 depends_on: 58 - woodpecker-server59 networks: 60 - woodpecker-network61 restart: unless-stopped6263 db: 64 image: postgres:15-alpine65 container_name: woodpecker-db66 environment: 67 - POSTGRES_USER=gitea68 - POSTGRES_PASSWORD=${DB_PASSWORD}69 - POSTGRES_DB=gitea70 volumes: 71 - postgres-data:/var/lib/postgresql/data72 - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql73 networks: 74 - woodpecker-network75 restart: unless-stopped7677volumes: 78 gitea-data: 79 woodpecker-data: 80 postgres-data: 8182networks: 83 woodpecker-network: 84 driver: bridge.env Template
.env
1# Woodpecker CI with Gitea2DB_PASSWORD=secure_db_password3WP_DB_PASSWORD=secure_wp_password45# Gitea6GITEA_URL=http://localhost:300078# Woodpecker9WOODPECKER_HOST=http://localhost:800010GITEA_CLIENT_ID=your_oauth_client_id11GITEA_CLIENT_SECRET=your_oauth_client_secret12AGENT_SECRET=super_secret_agent_keyUsage Notes
- 1Gitea at http://localhost:3000
- 2Woodpecker at http://localhost:8000
- 3Create OAuth app in Gitea settings
- 4Add .woodpecker.yml to repos
- 5Supports Docker-based pipelines
Individual Services(4 services)
Copy individual services to mix and match with your existing compose files.
gitea
gitea:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=${DB_PASSWORD}
volumes:
- gitea-data:/data
ports:
- "3000:3000"
- "222:22"
depends_on:
- db
networks:
- woodpecker-network
restart: unless-stopped
woodpecker-server
woodpecker-server:
image: woodpeckerci/woodpecker-server:latest
container_name: woodpecker-server
environment:
- WOODPECKER_OPEN=true
- WOODPECKER_HOST=${WOODPECKER_HOST}
- WOODPECKER_GITEA=true
- WOODPECKER_GITEA_URL=${GITEA_URL}
- WOODPECKER_GITEA_CLIENT=${GITEA_CLIENT_ID}
- WOODPECKER_GITEA_SECRET=${GITEA_CLIENT_SECRET}
- WOODPECKER_AGENT_SECRET=${AGENT_SECRET}
- WOODPECKER_DATABASE_DRIVER=postgres
- WOODPECKER_DATABASE_DATASOURCE=postgres://woodpecker:${WP_DB_PASSWORD}@db:5432/woodpecker?sslmode=disable
volumes:
- woodpecker-data:/var/lib/woodpecker
ports:
- "8000:8000"
depends_on:
- db
- gitea
networks:
- woodpecker-network
restart: unless-stopped
woodpecker-agent
woodpecker-agent:
image: woodpeckerci/woodpecker-agent:latest
container_name: woodpecker-agent
environment:
- WOODPECKER_SERVER=woodpecker-server:9000
- WOODPECKER_AGENT_SECRET=${AGENT_SECRET}
- WOODPECKER_MAX_WORKFLOWS=4
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- woodpecker-server
networks:
- woodpecker-network
restart: unless-stopped
db
db:
image: postgres:15-alpine
container_name: woodpecker-db
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=gitea
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init-db.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- woodpecker-network
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 gitea:5 image: gitea/gitea:latest6 container_name: gitea7 environment:8 - USER_UID=10009 - USER_GID=100010 - GITEA__database__DB_TYPE=postgres11 - GITEA__database__HOST=db:543212 - GITEA__database__NAME=gitea13 - GITEA__database__USER=gitea14 - GITEA__database__PASSWD=${DB_PASSWORD}15 volumes:16 - gitea-data:/data17 ports:18 - "3000:3000"19 - "222:22"20 depends_on:21 - db22 networks:23 - woodpecker-network24 restart: unless-stopped2526 woodpecker-server:27 image: woodpeckerci/woodpecker-server:latest28 container_name: woodpecker-server29 environment:30 - WOODPECKER_OPEN=true31 - WOODPECKER_HOST=${WOODPECKER_HOST}32 - WOODPECKER_GITEA=true33 - WOODPECKER_GITEA_URL=${GITEA_URL}34 - WOODPECKER_GITEA_CLIENT=${GITEA_CLIENT_ID}35 - WOODPECKER_GITEA_SECRET=${GITEA_CLIENT_SECRET}36 - WOODPECKER_AGENT_SECRET=${AGENT_SECRET}37 - WOODPECKER_DATABASE_DRIVER=postgres38 - WOODPECKER_DATABASE_DATASOURCE=postgres://woodpecker:${WP_DB_PASSWORD}@db:5432/woodpecker?sslmode=disable39 volumes:40 - woodpecker-data:/var/lib/woodpecker41 ports:42 - "8000:8000"43 depends_on:44 - db45 - gitea46 networks:47 - woodpecker-network48 restart: unless-stopped4950 woodpecker-agent:51 image: woodpeckerci/woodpecker-agent:latest52 container_name: woodpecker-agent53 environment:54 - WOODPECKER_SERVER=woodpecker-server:900055 - WOODPECKER_AGENT_SECRET=${AGENT_SECRET}56 - WOODPECKER_MAX_WORKFLOWS=457 volumes:58 - /var/run/docker.sock:/var/run/docker.sock59 depends_on:60 - woodpecker-server61 networks:62 - woodpecker-network63 restart: unless-stopped6465 db:66 image: postgres:15-alpine67 container_name: woodpecker-db68 environment:69 - POSTGRES_USER=gitea70 - POSTGRES_PASSWORD=${DB_PASSWORD}71 - POSTGRES_DB=gitea72 volumes:73 - postgres-data:/var/lib/postgresql/data74 - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql75 networks:76 - woodpecker-network77 restart: unless-stopped7879volumes:80 gitea-data:81 woodpecker-data:82 postgres-data:8384networks:85 woodpecker-network:86 driver: bridge87EOF8889# 2. Create the .env file90cat > .env << 'EOF'91# Woodpecker CI with Gitea92DB_PASSWORD=secure_db_password93WP_DB_PASSWORD=secure_wp_password9495# Gitea96GITEA_URL=http://localhost:30009798# Woodpecker99WOODPECKER_HOST=http://localhost:8000100GITEA_CLIENT_ID=your_oauth_client_id101GITEA_CLIENT_SECRET=your_oauth_client_secret102AGENT_SECRET=super_secret_agent_key103EOF104105# 3. Start the services106docker compose up -d107108# 4. View logs109docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/woodpecker-ci-gitea/run | bashTroubleshooting
- OAuth application not found error: Verify GITEA_CLIENT_ID and GITEA_CLIENT_SECRET match the OAuth app created in Gitea admin settings
- Woodpecker agent not connecting: Check AGENT_SECRET matches between server and agent, and ensure agent can reach server on port 9000
- Pipeline failing to clone repository: Confirm Gitea is accessible from Woodpecker containers and SSH keys or tokens are properly configured
- Database connection refused: Ensure PostgreSQL container is fully started before Gitea and Woodpecker attempt connections, add healthchecks if needed
- Permission denied on Docker socket: Verify woodpecker-agent container has proper access to /var/run/docker.sock or consider using rootless Docker
- Build artifacts not persisting: Check volume mounts and ensure workspace directories are properly configured in pipeline steps
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
woodpecker-serverwoodpecker-agentgiteapostgresql
Tags
#ci-cd#woodpecker#gitea#automation#builds
Category
DevOps & CI/CDAd Space
Shortcuts: C CopyF FavoriteD Download