docker.recipes

Drone CI with Gitea

intermediate

Lightweight Drone CI integrated with Gitea for self-hosted Git and continuous integration

Overview

Gitea is a lightweight, self-hosted Git service that provides GitHub-like functionality with minimal resource requirements. Written in Go, Gitea offers repository hosting, pull requests, issue tracking, and built-in CI/CD capabilities while consuming significantly fewer resources than alternatives like GitLab. Its painless setup and maintenance make it ideal for small teams and self-hosted environments. This stack combines Gitea with Drone CI to create a complete DevOps pipeline for continuous integration and deployment. Drone CI acts as the automation engine, executing builds, tests, and deployments triggered by Git events from Gitea repositories. The PostgreSQL database ensures reliable data persistence for both Git repositories and CI/CD metadata, while the Docker-based runner provides isolated execution environments for pipeline tasks. This combination delivers enterprise-grade CI/CD capabilities without the overhead of larger platforms like Jenkins or GitLab CI. Teams seeking full control over their development workflow will find this stack particularly valuable. The Gitea-Drone integration provides immediate feedback on code changes, automated testing, and deployment pipelines while maintaining complete data sovereignty. Small development teams, startups, and organizations with strict data privacy requirements can establish professional development practices without relying on external services or complex infrastructure.

Key Features

  • GitHub-like web interface with repository browsing, pull requests, and issue tracking
  • Drone CI pipeline execution with Docker-based isolation for build environments
  • PostgreSQL backend providing ACID compliance and reliable data persistence
  • OAuth2 authentication integration between Gitea and Drone for single sign-on
  • Scalable runner architecture supporting multiple concurrent build jobs
  • Webhook-driven automation triggering builds on push, pull request, and tag events
  • YAML-based pipeline configuration with .drone.yml files in repositories
  • Built-in Docker registry support for storing and deploying container images

Common Use Cases

  • 1Small development teams requiring private Git hosting with automated testing
  • 2Startups building CI/CD pipelines without external service dependencies
  • 3Organizations with data sovereignty requirements needing on-premises DevOps tools
  • 4Open source projects wanting self-hosted infrastructure for community contributions
  • 5Homelab enthusiasts learning DevOps practices with production-like tooling
  • 6Educational institutions teaching version control and continuous integration
  • 7Companies migrating from GitHub/GitLab to reduce licensing costs while maintaining functionality

Prerequisites

  • Docker and Docker Compose installed with at least 2GB available RAM
  • Minimum 1GB RAM recommended for PostgreSQL database performance
  • Ports 3000 (Gitea), 8080 (Drone), and 222 (SSH) available on the host system
  • Basic understanding of Git workflows and CI/CD pipeline concepts
  • Docker socket access for Drone runner to execute containerized builds
  • Environment variables configured for database passwords and OAuth credentials

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 restart: unless-stopped
6 ports:
7 - "${GITEA_HTTP:-3000}:3000"
8 - "${GITEA_SSH:-222}:22"
9 environment:
10 - USER_UID=1000
11 - USER_GID=1000
12 - GITEA__database__DB_TYPE=postgres
13 - GITEA__database__HOST=gitea-db:5432
14 - GITEA__database__NAME=gitea
15 - GITEA__database__USER=gitea
16 - GITEA__database__PASSWD=${DB_PASSWORD}
17 volumes:
18 - gitea_data:/data
19 - /etc/timezone:/etc/timezone:ro
20 - /etc/localtime:/etc/localtime:ro
21 depends_on:
22 - gitea-db
23
24 gitea-db:
25 image: postgres:15-alpine
26 container_name: gitea-db
27 restart: unless-stopped
28 environment:
29 - POSTGRES_USER=gitea
30 - POSTGRES_PASSWORD=${DB_PASSWORD}
31 - POSTGRES_DB=gitea
32 volumes:
33 - gitea_db_data:/var/lib/postgresql/data
34
35 drone:
36 image: drone/drone:latest
37 container_name: drone
38 restart: unless-stopped
39 ports:
40 - "${DRONE_PORT:-8080}:80"
41 environment:
42 - DRONE_GITEA_SERVER=http://gitea:3000
43 - DRONE_GITEA_CLIENT_ID=${GITEA_CLIENT_ID}
44 - DRONE_GITEA_CLIENT_SECRET=${GITEA_CLIENT_SECRET}
45 - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
46 - DRONE_SERVER_HOST=${DRONE_HOST:-localhost:8080}
47 - DRONE_SERVER_PROTO=http
48 volumes:
49 - drone_data:/data
50 depends_on:
51 - gitea
52
53 drone-runner:
54 image: drone/drone-runner-docker:latest
55 container_name: drone-runner
56 restart: unless-stopped
57 environment:
58 - DRONE_RPC_PROTO=http
59 - DRONE_RPC_HOST=drone
60 - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
61 - DRONE_RUNNER_CAPACITY=2
62 - DRONE_RUNNER_NAME=runner-1
63 volumes:
64 - /var/run/docker.sock:/var/run/docker.sock
65 depends_on:
66 - drone
67
68volumes:
69 gitea_data:
70 gitea_db_data:
71 drone_data:

.env Template

.env
1# Drone CI with Gitea
2GITEA_HTTP=3000
3GITEA_SSH=222
4DRONE_PORT=8080
5
6# Database
7DB_PASSWORD=gitea_password
8
9# Gitea OAuth App (create in Gitea settings)
10GITEA_CLIENT_ID=your-gitea-client-id
11GITEA_CLIENT_SECRET=your-gitea-client-secret
12
13# Drone RPC Secret (generate with: openssl rand -hex 16)
14DRONE_RPC_SECRET=your-rpc-secret
15
16# Drone host (your server hostname)
17DRONE_HOST=localhost:8080

Usage Notes

  1. 1Gitea at http://localhost:3000 - create admin account
  2. 2Create OAuth app in Gitea: Settings > Applications
  3. 3Drone at http://localhost:8080 - login via Gitea
  4. 4Create .drone.yml in repos for CI pipelines
  5. 5Runner auto-registers with Drone server
  6. 6Scale runners: docker compose up -d --scale drone-runner=3

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
  restart: unless-stopped
  ports:
    - ${GITEA_HTTP:-3000}:3000
    - ${GITEA_SSH:-222}:22
  environment:
    - USER_UID=1000
    - USER_GID=1000
    - GITEA__database__DB_TYPE=postgres
    - GITEA__database__HOST=gitea-db:5432
    - GITEA__database__NAME=gitea
    - GITEA__database__USER=gitea
    - GITEA__database__PASSWD=${DB_PASSWORD}
  volumes:
    - gitea_data:/data
    - /etc/timezone:/etc/timezone:ro
    - /etc/localtime:/etc/localtime:ro
  depends_on:
    - gitea-db
gitea-db
gitea-db:
  image: postgres:15-alpine
  container_name: gitea-db
  restart: unless-stopped
  environment:
    - POSTGRES_USER=gitea
    - POSTGRES_PASSWORD=${DB_PASSWORD}
    - POSTGRES_DB=gitea
  volumes:
    - gitea_db_data:/var/lib/postgresql/data
drone
drone:
  image: drone/drone:latest
  container_name: drone
  restart: unless-stopped
  ports:
    - ${DRONE_PORT:-8080}:80
  environment:
    - DRONE_GITEA_SERVER=http://gitea:3000
    - DRONE_GITEA_CLIENT_ID=${GITEA_CLIENT_ID}
    - DRONE_GITEA_CLIENT_SECRET=${GITEA_CLIENT_SECRET}
    - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
    - DRONE_SERVER_HOST=${DRONE_HOST:-localhost:8080}
    - DRONE_SERVER_PROTO=http
  volumes:
    - drone_data:/data
  depends_on:
    - gitea
drone-runner
drone-runner:
  image: drone/drone-runner-docker:latest
  container_name: drone-runner
  restart: unless-stopped
  environment:
    - DRONE_RPC_PROTO=http
    - DRONE_RPC_HOST=drone
    - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
    - DRONE_RUNNER_CAPACITY=2
    - DRONE_RUNNER_NAME=runner-1
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock
  depends_on:
    - drone

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 restart: unless-stopped
8 ports:
9 - "${GITEA_HTTP:-3000}:3000"
10 - "${GITEA_SSH:-222}:22"
11 environment:
12 - USER_UID=1000
13 - USER_GID=1000
14 - GITEA__database__DB_TYPE=postgres
15 - GITEA__database__HOST=gitea-db:5432
16 - GITEA__database__NAME=gitea
17 - GITEA__database__USER=gitea
18 - GITEA__database__PASSWD=${DB_PASSWORD}
19 volumes:
20 - gitea_data:/data
21 - /etc/timezone:/etc/timezone:ro
22 - /etc/localtime:/etc/localtime:ro
23 depends_on:
24 - gitea-db
25
26 gitea-db:
27 image: postgres:15-alpine
28 container_name: gitea-db
29 restart: unless-stopped
30 environment:
31 - POSTGRES_USER=gitea
32 - POSTGRES_PASSWORD=${DB_PASSWORD}
33 - POSTGRES_DB=gitea
34 volumes:
35 - gitea_db_data:/var/lib/postgresql/data
36
37 drone:
38 image: drone/drone:latest
39 container_name: drone
40 restart: unless-stopped
41 ports:
42 - "${DRONE_PORT:-8080}:80"
43 environment:
44 - DRONE_GITEA_SERVER=http://gitea:3000
45 - DRONE_GITEA_CLIENT_ID=${GITEA_CLIENT_ID}
46 - DRONE_GITEA_CLIENT_SECRET=${GITEA_CLIENT_SECRET}
47 - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
48 - DRONE_SERVER_HOST=${DRONE_HOST:-localhost:8080}
49 - DRONE_SERVER_PROTO=http
50 volumes:
51 - drone_data:/data
52 depends_on:
53 - gitea
54
55 drone-runner:
56 image: drone/drone-runner-docker:latest
57 container_name: drone-runner
58 restart: unless-stopped
59 environment:
60 - DRONE_RPC_PROTO=http
61 - DRONE_RPC_HOST=drone
62 - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
63 - DRONE_RUNNER_CAPACITY=2
64 - DRONE_RUNNER_NAME=runner-1
65 volumes:
66 - /var/run/docker.sock:/var/run/docker.sock
67 depends_on:
68 - drone
69
70volumes:
71 gitea_data:
72 gitea_db_data:
73 drone_data:
74EOF
75
76# 2. Create the .env file
77cat > .env << 'EOF'
78# Drone CI with Gitea
79GITEA_HTTP=3000
80GITEA_SSH=222
81DRONE_PORT=8080
82
83# Database
84DB_PASSWORD=gitea_password
85
86# Gitea OAuth App (create in Gitea settings)
87GITEA_CLIENT_ID=your-gitea-client-id
88GITEA_CLIENT_SECRET=your-gitea-client-secret
89
90# Drone RPC Secret (generate with: openssl rand -hex 16)
91DRONE_RPC_SECRET=your-rpc-secret
92
93# Drone host (your server hostname)
94DRONE_HOST=localhost:8080
95EOF
96
97# 3. Start the services
98docker compose up -d
99
100# 4. View logs
101docker 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/drone-ci-gitea/run | bash

Troubleshooting

  • Drone shows 'OAuth application not found': Verify GITEA_CLIENT_ID and GITEA_CLIENT_SECRET match the OAuth app created in Gitea settings
  • Runner not connecting to Drone server: Ensure DRONE_RPC_SECRET matches between drone and drone-runner services
  • Gitea SSH clone fails on port 22: Change GITEA_SSH environment variable to use port 222 or configure SSH client with custom port
  • Pipeline builds failing with permission errors: Check that /var/run/docker.sock is properly mounted and accessible to the runner container
  • PostgreSQL connection refused during startup: Wait for gitea-db container to fully initialize before Gitea attempts database connection
  • Drone webhooks not triggering builds: Verify webhook URLs in Gitea repository settings point to the correct Drone server address

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