Gitea with Actions Runner
Self-hosted Git with Gitea and integrated CI/CD runners.
Overview
Gitea is a lightweight, self-hosted Git service written in Go that provides GitHub-like functionality without the resource overhead of larger alternatives like GitLab. Originally forked from Gogs in 2016, Gitea has evolved into a mature platform offering repository management, issue tracking, pull requests, and built-in CI/CD through Gitea Actions. This makes it an ideal choice for teams wanting complete control over their source code and development workflow while maintaining familiar GitHub-style interfaces and workflows.
This stack combines Gitea with PostgreSQL for robust data persistence, Redis for high-performance caching and session management, and the official Gitea Actions runner for automated CI/CD pipelines. PostgreSQL ensures ACID compliance and handles complex queries efficiently, while Redis dramatically improves Gitea's response times by caching frequently accessed data. The Actions runner provides Docker-in-Docker capabilities, enabling teams to run sophisticated build, test, and deployment pipelines using GitHub Actions-compatible workflow syntax.
This configuration targets development teams, DevOps engineers, and organizations requiring private Git hosting with integrated CI/CD capabilities. Small to medium-sized companies benefit from reduced licensing costs compared to hosted solutions, while maintaining enterprise-grade features like OAuth2 authentication, webhook integrations, and scalable runner architecture. The stack is particularly valuable for teams with compliance requirements, air-gapped environments, or those wanting to avoid vendor lock-in while preserving familiar Git workflows.
Key Features
- GitHub Actions-compatible CI/CD workflows with YAML syntax support
- PostgreSQL backend providing ACID transactions and advanced querying capabilities
- Redis caching layer for sub-millisecond session and repository data access
- Docker-in-Docker runner execution supporting multi-stage builds and custom images
- Built-in package registry supporting Docker, npm, Maven, and NuGet packages
- OAuth2 and LDAP authentication with role-based access control
- Pull request workflows with code review, approvals, and merge protection
- Issue tracking with milestones, labels, and project boards
Common Use Cases
- 1Private source code hosting for proprietary software development
- 2Self-hosted CI/CD pipelines replacing Jenkins or GitHub Actions
- 3Code review workflows for distributed development teams
- 4Package registry for internal libraries and Docker images
- 5Migration from GitHub or GitLab to reduce licensing costs
- 6Compliance-driven development in regulated industries
- 7Air-gapped development environments in secure facilities
Prerequisites
- Minimum 1GB RAM (2GB+ recommended for active CI/CD workloads)
- Docker host with /var/run/docker.sock access for runner container
- Ports 3000 and 2222 available for HTTP and SSH Git access
- Basic understanding of Git workflows and YAML syntax
- PostgreSQL administration knowledge for backup and maintenance
- Environment variables POSTGRES_PASSWORD and RUNNER_TOKEN configured
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 postgres: 3 image: postgres:15-alpine4 environment: 5 - POSTGRES_USER=gitea6 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}7 - POSTGRES_DB=gitea8 volumes: 9 - postgres_data:/var/lib/postgresql/data10 networks: 11 - gitea_net1213 redis: 14 image: redis:7-alpine15 volumes: 16 - redis_data:/data17 networks: 18 - gitea_net1920 gitea: 21 image: gitea/gitea:latest22 ports: 23 - "3000:3000"24 - "2222:22"25 environment: 26 - USER_UID=100027 - USER_GID=100028 - GITEA__database__DB_TYPE=postgres29 - GITEA__database__HOST=postgres:543230 - GITEA__database__NAME=gitea31 - GITEA__database__USER=gitea32 - GITEA__database__PASSWD=${POSTGRES_PASSWORD}33 - GITEA__cache__ADAPTER=redis34 - GITEA__cache__HOST=redis://redis:6379/035 - GITEA__actions__ENABLED=true36 volumes: 37 - gitea_data:/data38 - /etc/timezone:/etc/timezone:ro39 - /etc/localtime:/etc/localtime:ro40 depends_on: 41 - postgres42 - redis43 networks: 44 - gitea_net4546 gitea-runner: 47 image: gitea/act_runner:latest48 environment: 49 - GITEA_INSTANCE_URL=http://gitea:300050 - GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN}51 - GITEA_RUNNER_NAME=docker-runner52 volumes: 53 - /var/run/docker.sock:/var/run/docker.sock54 - runner_data:/data55 depends_on: 56 - gitea57 networks: 58 - gitea_net5960volumes: 61 postgres_data: 62 redis_data: 63 gitea_data: 64 runner_data: 6566networks: 67 gitea_net: .env Template
.env
1# Gitea with Actions2POSTGRES_PASSWORD=secure_postgres_password3RUNNER_TOKEN=your_runner_registration_token45# Gitea at http://localhost:30006# SSH at localhost:22227# Get runner token from Gitea admin panelUsage Notes
- 1Gitea at http://localhost:3000
- 2SSH clone via port 2222
- 3Enable Actions in admin settings
- 4Get runner token from Site Admin > Actions > Runners
- 5GitHub Actions compatible workflow files
Individual Services(4 services)
Copy individual services to mix and match with your existing compose files.
postgres
postgres:
image: postgres:15-alpine
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=gitea
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- gitea_net
redis
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
networks:
- gitea_net
gitea
gitea:
image: gitea/gitea:latest
ports:
- "3000:3000"
- "2222:22"
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=postgres:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=${POSTGRES_PASSWORD}
- GITEA__cache__ADAPTER=redis
- GITEA__cache__HOST=redis://redis:6379/0
- GITEA__actions__ENABLED=true
volumes:
- gitea_data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- postgres
- redis
networks:
- gitea_net
gitea-runner
gitea-runner:
image: gitea/act_runner:latest
environment:
- GITEA_INSTANCE_URL=http://gitea:3000
- GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN}
- GITEA_RUNNER_NAME=docker-runner
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- runner_data:/data
depends_on:
- gitea
networks:
- gitea_net
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 postgres:5 image: postgres:15-alpine6 environment:7 - POSTGRES_USER=gitea8 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}9 - POSTGRES_DB=gitea10 volumes:11 - postgres_data:/var/lib/postgresql/data12 networks:13 - gitea_net1415 redis:16 image: redis:7-alpine17 volumes:18 - redis_data:/data19 networks:20 - gitea_net2122 gitea:23 image: gitea/gitea:latest24 ports:25 - "3000:3000"26 - "2222:22"27 environment:28 - USER_UID=100029 - USER_GID=100030 - GITEA__database__DB_TYPE=postgres31 - GITEA__database__HOST=postgres:543232 - GITEA__database__NAME=gitea33 - GITEA__database__USER=gitea34 - GITEA__database__PASSWD=${POSTGRES_PASSWORD}35 - GITEA__cache__ADAPTER=redis36 - GITEA__cache__HOST=redis://redis:6379/037 - GITEA__actions__ENABLED=true38 volumes:39 - gitea_data:/data40 - /etc/timezone:/etc/timezone:ro41 - /etc/localtime:/etc/localtime:ro42 depends_on:43 - postgres44 - redis45 networks:46 - gitea_net4748 gitea-runner:49 image: gitea/act_runner:latest50 environment:51 - GITEA_INSTANCE_URL=http://gitea:300052 - GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN}53 - GITEA_RUNNER_NAME=docker-runner54 volumes:55 - /var/run/docker.sock:/var/run/docker.sock56 - runner_data:/data57 depends_on:58 - gitea59 networks:60 - gitea_net6162volumes:63 postgres_data:64 redis_data:65 gitea_data:66 runner_data:6768networks:69 gitea_net:70EOF7172# 2. Create the .env file73cat > .env << 'EOF'74# Gitea with Actions75POSTGRES_PASSWORD=secure_postgres_password76RUNNER_TOKEN=your_runner_registration_token7778# Gitea at http://localhost:300079# SSH at localhost:222280# Get runner token from Gitea admin panel81EOF8283# 3. Start the services84docker compose up -d8586# 4. View logs87docker 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/gitea-actions/run | bashTroubleshooting
- Runner registration fails with 'token invalid': Generate new runner token from Site Admin > Actions > Runners and update RUNNER_TOKEN environment variable
- Actions workflows stuck in 'waiting' status: Verify runner container has access to Docker socket and check runner logs for connection issues
- Gitea shows 'database connection failed': Ensure PostgreSQL container is healthy and POSTGRES_PASSWORD matches between services
- SSH clone fails on port 2222: Check if host firewall allows port 2222 and verify SSH_PORT setting in Gitea configuration
- Redis connection errors in Gitea logs: Confirm Redis container is running and accessible on gitea_net network
- Actions runner out of disk space: Configure Docker cleanup policies and monitor /var/lib/docker usage on host system
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
giteagitea-runnerpostgresqlredis
Tags
#gitea#git#actions#ci-cd#self-hosted
Category
DevOps & CI/CDAd Space
Shortcuts: C CopyF FavoriteD Download