docker.recipes

Gitea with Actions Runner

intermediate

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-alpine
4 environment:
5 - POSTGRES_USER=gitea
6 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
7 - POSTGRES_DB=gitea
8 volumes:
9 - postgres_data:/var/lib/postgresql/data
10 networks:
11 - gitea_net
12
13 redis:
14 image: redis:7-alpine
15 volumes:
16 - redis_data:/data
17 networks:
18 - gitea_net
19
20 gitea:
21 image: gitea/gitea:latest
22 ports:
23 - "3000:3000"
24 - "2222:22"
25 environment:
26 - USER_UID=1000
27 - USER_GID=1000
28 - GITEA__database__DB_TYPE=postgres
29 - GITEA__database__HOST=postgres:5432
30 - GITEA__database__NAME=gitea
31 - GITEA__database__USER=gitea
32 - GITEA__database__PASSWD=${POSTGRES_PASSWORD}
33 - GITEA__cache__ADAPTER=redis
34 - GITEA__cache__HOST=redis://redis:6379/0
35 - GITEA__actions__ENABLED=true
36 volumes:
37 - gitea_data:/data
38 - /etc/timezone:/etc/timezone:ro
39 - /etc/localtime:/etc/localtime:ro
40 depends_on:
41 - postgres
42 - redis
43 networks:
44 - gitea_net
45
46 gitea-runner:
47 image: gitea/act_runner:latest
48 environment:
49 - GITEA_INSTANCE_URL=http://gitea:3000
50 - GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN}
51 - GITEA_RUNNER_NAME=docker-runner
52 volumes:
53 - /var/run/docker.sock:/var/run/docker.sock
54 - runner_data:/data
55 depends_on:
56 - gitea
57 networks:
58 - gitea_net
59
60volumes:
61 postgres_data:
62 redis_data:
63 gitea_data:
64 runner_data:
65
66networks:
67 gitea_net:

.env Template

.env
1# Gitea with Actions
2POSTGRES_PASSWORD=secure_postgres_password
3RUNNER_TOKEN=your_runner_registration_token
4
5# Gitea at http://localhost:3000
6# SSH at localhost:2222
7# Get runner token from Gitea admin panel

Usage Notes

  1. 1Gitea at http://localhost:3000
  2. 2SSH clone via port 2222
  3. 3Enable Actions in admin settings
  4. 4Get runner token from Site Admin > Actions > Runners
  5. 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 file
2cat > docker-compose.yml << 'EOF'
3services:
4 postgres:
5 image: postgres:15-alpine
6 environment:
7 - POSTGRES_USER=gitea
8 - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
9 - POSTGRES_DB=gitea
10 volumes:
11 - postgres_data:/var/lib/postgresql/data
12 networks:
13 - gitea_net
14
15 redis:
16 image: redis:7-alpine
17 volumes:
18 - redis_data:/data
19 networks:
20 - gitea_net
21
22 gitea:
23 image: gitea/gitea:latest
24 ports:
25 - "3000:3000"
26 - "2222:22"
27 environment:
28 - USER_UID=1000
29 - USER_GID=1000
30 - GITEA__database__DB_TYPE=postgres
31 - GITEA__database__HOST=postgres:5432
32 - GITEA__database__NAME=gitea
33 - GITEA__database__USER=gitea
34 - GITEA__database__PASSWD=${POSTGRES_PASSWORD}
35 - GITEA__cache__ADAPTER=redis
36 - GITEA__cache__HOST=redis://redis:6379/0
37 - GITEA__actions__ENABLED=true
38 volumes:
39 - gitea_data:/data
40 - /etc/timezone:/etc/timezone:ro
41 - /etc/localtime:/etc/localtime:ro
42 depends_on:
43 - postgres
44 - redis
45 networks:
46 - gitea_net
47
48 gitea-runner:
49 image: gitea/act_runner:latest
50 environment:
51 - GITEA_INSTANCE_URL=http://gitea:3000
52 - GITEA_RUNNER_REGISTRATION_TOKEN=${RUNNER_TOKEN}
53 - GITEA_RUNNER_NAME=docker-runner
54 volumes:
55 - /var/run/docker.sock:/var/run/docker.sock
56 - runner_data:/data
57 depends_on:
58 - gitea
59 networks:
60 - gitea_net
61
62volumes:
63 postgres_data:
64 redis_data:
65 gitea_data:
66 runner_data:
67
68networks:
69 gitea_net:
70EOF
71
72# 2. Create the .env file
73cat > .env << 'EOF'
74# Gitea with Actions
75POSTGRES_PASSWORD=secure_postgres_password
76RUNNER_TOKEN=your_runner_registration_token
77
78# Gitea at http://localhost:3000
79# SSH at localhost:2222
80# Get runner token from Gitea admin panel
81EOF
82
83# 3. Start the services
84docker compose up -d
85
86# 4. View logs
87docker 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/gitea-actions/run | bash

Troubleshooting

  • 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

Ad Space