Drone CI with Gitea
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:latest4 container_name: gitea5 restart: unless-stopped6 ports: 7 - "${GITEA_HTTP:-3000}:3000"8 - "${GITEA_SSH:-222}:22"9 environment: 10 - USER_UID=100011 - USER_GID=100012 - GITEA__database__DB_TYPE=postgres13 - GITEA__database__HOST=gitea-db:543214 - GITEA__database__NAME=gitea15 - GITEA__database__USER=gitea16 - GITEA__database__PASSWD=${DB_PASSWORD}17 volumes: 18 - gitea_data:/data19 - /etc/timezone:/etc/timezone:ro20 - /etc/localtime:/etc/localtime:ro21 depends_on: 22 - gitea-db2324 gitea-db: 25 image: postgres:15-alpine26 container_name: gitea-db27 restart: unless-stopped28 environment: 29 - POSTGRES_USER=gitea30 - POSTGRES_PASSWORD=${DB_PASSWORD}31 - POSTGRES_DB=gitea32 volumes: 33 - gitea_db_data:/var/lib/postgresql/data3435 drone: 36 image: drone/drone:latest37 container_name: drone38 restart: unless-stopped39 ports: 40 - "${DRONE_PORT:-8080}:80"41 environment: 42 - DRONE_GITEA_SERVER=http://gitea:300043 - 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=http48 volumes: 49 - drone_data:/data50 depends_on: 51 - gitea5253 drone-runner: 54 image: drone/drone-runner-docker:latest55 container_name: drone-runner56 restart: unless-stopped57 environment: 58 - DRONE_RPC_PROTO=http59 - DRONE_RPC_HOST=drone60 - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}61 - DRONE_RUNNER_CAPACITY=262 - DRONE_RUNNER_NAME=runner-163 volumes: 64 - /var/run/docker.sock:/var/run/docker.sock65 depends_on: 66 - drone6768volumes: 69 gitea_data: 70 gitea_db_data: 71 drone_data: .env Template
.env
1# Drone CI with Gitea2GITEA_HTTP=30003GITEA_SSH=2224DRONE_PORT=808056# Database7DB_PASSWORD=gitea_password89# Gitea OAuth App (create in Gitea settings)10GITEA_CLIENT_ID=your-gitea-client-id11GITEA_CLIENT_SECRET=your-gitea-client-secret1213# Drone RPC Secret (generate with: openssl rand -hex 16)14DRONE_RPC_SECRET=your-rpc-secret1516# Drone host (your server hostname)17DRONE_HOST=localhost:8080Usage Notes
- 1Gitea at http://localhost:3000 - create admin account
- 2Create OAuth app in Gitea: Settings > Applications
- 3Drone at http://localhost:8080 - login via Gitea
- 4Create .drone.yml in repos for CI pipelines
- 5Runner auto-registers with Drone server
- 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 file2cat > docker-compose.yml << 'EOF'3services:4 gitea:5 image: gitea/gitea:latest6 container_name: gitea7 restart: unless-stopped8 ports:9 - "${GITEA_HTTP:-3000}:3000"10 - "${GITEA_SSH:-222}:22"11 environment:12 - USER_UID=100013 - USER_GID=100014 - GITEA__database__DB_TYPE=postgres15 - GITEA__database__HOST=gitea-db:543216 - GITEA__database__NAME=gitea17 - GITEA__database__USER=gitea18 - GITEA__database__PASSWD=${DB_PASSWORD}19 volumes:20 - gitea_data:/data21 - /etc/timezone:/etc/timezone:ro22 - /etc/localtime:/etc/localtime:ro23 depends_on:24 - gitea-db2526 gitea-db:27 image: postgres:15-alpine28 container_name: gitea-db29 restart: unless-stopped30 environment:31 - POSTGRES_USER=gitea32 - POSTGRES_PASSWORD=${DB_PASSWORD}33 - POSTGRES_DB=gitea34 volumes:35 - gitea_db_data:/var/lib/postgresql/data3637 drone:38 image: drone/drone:latest39 container_name: drone40 restart: unless-stopped41 ports:42 - "${DRONE_PORT:-8080}:80"43 environment:44 - DRONE_GITEA_SERVER=http://gitea:300045 - 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=http50 volumes:51 - drone_data:/data52 depends_on:53 - gitea5455 drone-runner:56 image: drone/drone-runner-docker:latest57 container_name: drone-runner58 restart: unless-stopped59 environment:60 - DRONE_RPC_PROTO=http61 - DRONE_RPC_HOST=drone62 - DRONE_RPC_SECRET=${DRONE_RPC_SECRET}63 - DRONE_RUNNER_CAPACITY=264 - DRONE_RUNNER_NAME=runner-165 volumes:66 - /var/run/docker.sock:/var/run/docker.sock67 depends_on:68 - drone6970volumes:71 gitea_data:72 gitea_db_data:73 drone_data:74EOF7576# 2. Create the .env file77cat > .env << 'EOF'78# Drone CI with Gitea79GITEA_HTTP=300080GITEA_SSH=22281DRONE_PORT=80808283# Database84DB_PASSWORD=gitea_password8586# Gitea OAuth App (create in Gitea settings)87GITEA_CLIENT_ID=your-gitea-client-id88GITEA_CLIENT_SECRET=your-gitea-client-secret8990# Drone RPC Secret (generate with: openssl rand -hex 16)91DRONE_RPC_SECRET=your-rpc-secret9293# Drone host (your server hostname)94DRONE_HOST=localhost:808095EOF9697# 3. Start the services98docker compose up -d99100# 4. View logs101docker 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/drone-ci-gitea/run | bashTroubleshooting
- 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
Components
giteadronedrone-runnerpostgres
Tags
#drone#ci-cd#gitea#git#lightweight#devops
Category
DevOps & CI/CDAd Space
Shortcuts: C CopyF FavoriteD Download