docker.recipes

Woodpecker CI with Gitea

intermediate

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:latest
4 container_name: gitea
5 environment:
6 - USER_UID=1000
7 - USER_GID=1000
8 - GITEA__database__DB_TYPE=postgres
9 - GITEA__database__HOST=db:5432
10 - GITEA__database__NAME=gitea
11 - GITEA__database__USER=gitea
12 - GITEA__database__PASSWD=${DB_PASSWORD}
13 volumes:
14 - gitea-data:/data
15 ports:
16 - "3000:3000"
17 - "222:22"
18 depends_on:
19 - db
20 networks:
21 - woodpecker-network
22 restart: unless-stopped
23
24 woodpecker-server:
25 image: woodpeckerci/woodpecker-server:latest
26 container_name: woodpecker-server
27 environment:
28 - WOODPECKER_OPEN=true
29 - WOODPECKER_HOST=${WOODPECKER_HOST}
30 - WOODPECKER_GITEA=true
31 - 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=postgres
36 - WOODPECKER_DATABASE_DATASOURCE=postgres://woodpecker:${WP_DB_PASSWORD}@db:5432/woodpecker?sslmode=disable
37 volumes:
38 - woodpecker-data:/var/lib/woodpecker
39 ports:
40 - "8000:8000"
41 depends_on:
42 - db
43 - gitea
44 networks:
45 - woodpecker-network
46 restart: unless-stopped
47
48 woodpecker-agent:
49 image: woodpeckerci/woodpecker-agent:latest
50 container_name: woodpecker-agent
51 environment:
52 - WOODPECKER_SERVER=woodpecker-server:9000
53 - WOODPECKER_AGENT_SECRET=${AGENT_SECRET}
54 - WOODPECKER_MAX_WORKFLOWS=4
55 volumes:
56 - /var/run/docker.sock:/var/run/docker.sock
57 depends_on:
58 - woodpecker-server
59 networks:
60 - woodpecker-network
61 restart: unless-stopped
62
63 db:
64 image: postgres:15-alpine
65 container_name: woodpecker-db
66 environment:
67 - POSTGRES_USER=gitea
68 - POSTGRES_PASSWORD=${DB_PASSWORD}
69 - POSTGRES_DB=gitea
70 volumes:
71 - postgres-data:/var/lib/postgresql/data
72 - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql
73 networks:
74 - woodpecker-network
75 restart: unless-stopped
76
77volumes:
78 gitea-data:
79 woodpecker-data:
80 postgres-data:
81
82networks:
83 woodpecker-network:
84 driver: bridge

.env Template

.env
1# Woodpecker CI with Gitea
2DB_PASSWORD=secure_db_password
3WP_DB_PASSWORD=secure_wp_password
4
5# Gitea
6GITEA_URL=http://localhost:3000
7
8# Woodpecker
9WOODPECKER_HOST=http://localhost:8000
10GITEA_CLIENT_ID=your_oauth_client_id
11GITEA_CLIENT_SECRET=your_oauth_client_secret
12AGENT_SECRET=super_secret_agent_key

Usage Notes

  1. 1Gitea at http://localhost:3000
  2. 2Woodpecker at http://localhost:8000
  3. 3Create OAuth app in Gitea settings
  4. 4Add .woodpecker.yml to repos
  5. 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 file
2cat > docker-compose.yml << 'EOF'
3services:
4 gitea:
5 image: gitea/gitea:latest
6 container_name: gitea
7 environment:
8 - USER_UID=1000
9 - USER_GID=1000
10 - GITEA__database__DB_TYPE=postgres
11 - GITEA__database__HOST=db:5432
12 - GITEA__database__NAME=gitea
13 - GITEA__database__USER=gitea
14 - GITEA__database__PASSWD=${DB_PASSWORD}
15 volumes:
16 - gitea-data:/data
17 ports:
18 - "3000:3000"
19 - "222:22"
20 depends_on:
21 - db
22 networks:
23 - woodpecker-network
24 restart: unless-stopped
25
26 woodpecker-server:
27 image: woodpeckerci/woodpecker-server:latest
28 container_name: woodpecker-server
29 environment:
30 - WOODPECKER_OPEN=true
31 - WOODPECKER_HOST=${WOODPECKER_HOST}
32 - WOODPECKER_GITEA=true
33 - 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=postgres
38 - WOODPECKER_DATABASE_DATASOURCE=postgres://woodpecker:${WP_DB_PASSWORD}@db:5432/woodpecker?sslmode=disable
39 volumes:
40 - woodpecker-data:/var/lib/woodpecker
41 ports:
42 - "8000:8000"
43 depends_on:
44 - db
45 - gitea
46 networks:
47 - woodpecker-network
48 restart: unless-stopped
49
50 woodpecker-agent:
51 image: woodpeckerci/woodpecker-agent:latest
52 container_name: woodpecker-agent
53 environment:
54 - WOODPECKER_SERVER=woodpecker-server:9000
55 - WOODPECKER_AGENT_SECRET=${AGENT_SECRET}
56 - WOODPECKER_MAX_WORKFLOWS=4
57 volumes:
58 - /var/run/docker.sock:/var/run/docker.sock
59 depends_on:
60 - woodpecker-server
61 networks:
62 - woodpecker-network
63 restart: unless-stopped
64
65 db:
66 image: postgres:15-alpine
67 container_name: woodpecker-db
68 environment:
69 - POSTGRES_USER=gitea
70 - POSTGRES_PASSWORD=${DB_PASSWORD}
71 - POSTGRES_DB=gitea
72 volumes:
73 - postgres-data:/var/lib/postgresql/data
74 - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql
75 networks:
76 - woodpecker-network
77 restart: unless-stopped
78
79volumes:
80 gitea-data:
81 woodpecker-data:
82 postgres-data:
83
84networks:
85 woodpecker-network:
86 driver: bridge
87EOF
88
89# 2. Create the .env file
90cat > .env << 'EOF'
91# Woodpecker CI with Gitea
92DB_PASSWORD=secure_db_password
93WP_DB_PASSWORD=secure_wp_password
94
95# Gitea
96GITEA_URL=http://localhost:3000
97
98# Woodpecker
99WOODPECKER_HOST=http://localhost:8000
100GITEA_CLIENT_ID=your_oauth_client_id
101GITEA_CLIENT_SECRET=your_oauth_client_secret
102AGENT_SECRET=super_secret_agent_key
103EOF
104
105# 3. Start the services
106docker compose up -d
107
108# 4. View logs
109docker compose logs -f

One-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 | bash

Troubleshooting

  • 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

Ad Space