docker.recipes

Forgejo with Actions Runner

intermediate

Forgejo Git forge with GitHub Actions compatible CI/CD runners.

Overview

Forgejo is a self-hosted Git forge that emerged as a community-driven fork of Gitea, focusing on federation capabilities and user freedom. It provides comprehensive Git repository hosting with built-in issue tracking, pull requests, wikis, and project management features. What sets Forgejo apart is its commitment to remaining fully community-owned and its development of ActivityPub federation for decentralized collaboration across instances. This stack combines Forgejo with its dedicated Actions Runner to create a complete GitHub-alternative CI/CD platform. The PostgreSQL database handles repository metadata, user accounts, and issue tracking, while Redis accelerates session management and caches frequently accessed data. The Docker-in-Docker (DinD) container provides isolated build environments for CI/CD pipelines, ensuring that Actions workflows run securely without affecting the host system. This configuration is ideal for organizations seeking GitHub functionality with complete control over their code and infrastructure. Teams migrating from GitHub will find familiar Actions syntax compatibility, while the federation features position this stack for future decentralized development workflows. The combination delivers enterprise-grade Git hosting with modern CI/CD capabilities, all under open-source licenses.

Key Features

  • GitHub Actions compatible workflow syntax with .forgejo/workflows/ directory support
  • ActivityPub federation protocol for cross-instance collaboration and decentralized development
  • Docker-in-Docker isolation for secure CI/CD pipeline execution without host contamination
  • PostgreSQL JSONB storage for efficient Git metadata and issue tracking with complex queries
  • Redis-backed session clustering and cache acceleration for multi-user repository access
  • Forgejo Runner daemon with automatic job polling and distributed build execution
  • Built-in container registry for Docker image publishing from CI/CD pipelines
  • Advanced Git LFS support with PostgreSQL metadata tracking and Redis caching

Common Use Cases

  • 1Self-hosted GitHub alternative for teams requiring code sovereignty and data control
  • 2CI/CD automation for Docker applications with integrated container registry publishing
  • 3Private Git hosting for sensitive projects with Actions-based testing and deployment
  • 4Educational institutions teaching DevOps with GitHub-compatible workflow syntax
  • 5Open source projects seeking federated collaboration across multiple Forgejo instances
  • 6Compliance-focused organizations needing auditable Git operations and build processes
  • 7Development teams migrating from GitHub while maintaining existing Actions workflows

Prerequisites

  • Minimum 2GB RAM for PostgreSQL database operations and Redis caching
  • Docker host with privileged container support for Docker-in-Docker functionality
  • Ports 3000 (web UI) and 222 (SSH Git access) available on the host system
  • Basic understanding of Git forge administration and CI/CD workflow concepts
  • SSL certificate setup knowledge for production HTTPS deployment
  • Familiarity with GitHub Actions syntax for workflow creation and debugging

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 forgejo:
3 image: codeberg.org/forgejo/forgejo:7
4 container_name: forgejo
5 environment:
6 - USER_UID=1000
7 - USER_GID=1000
8 - FORGEJO__database__DB_TYPE=postgres
9 - FORGEJO__database__HOST=db:5432
10 - FORGEJO__database__NAME=forgejo
11 - FORGEJO__database__USER=forgejo
12 - FORGEJO__database__PASSWD=${DB_PASSWORD}
13 - FORGEJO__cache__ADAPTER=redis
14 - FORGEJO__cache__HOST=redis://redis:6379/0
15 - FORGEJO__session__PROVIDER=redis
16 - FORGEJO__session__PROVIDER_CONFIG=redis://redis:6379/1
17 - FORGEJO__actions__ENABLED=true
18 volumes:
19 - forgejo-data:/data
20 - /etc/timezone:/etc/timezone:ro
21 - /etc/localtime:/etc/localtime:ro
22 ports:
23 - "3000:3000"
24 - "222:22"
25 depends_on:
26 - db
27 - redis
28 networks:
29 - forgejo-network
30 restart: unless-stopped
31
32 runner:
33 image: code.forgejo.org/forgejo/runner:3.3.0
34 container_name: forgejo-runner
35 environment:
36 - DOCKER_HOST=tcp://docker-in-docker:2376
37 - DOCKER_TLS_VERIFY=1
38 - DOCKER_CERT_PATH=/certs/client
39 volumes:
40 - runner-data:/data
41 - docker-certs:/certs/client:ro
42 depends_on:
43 - forgejo
44 - docker-in-docker
45 networks:
46 - forgejo-network
47 restart: unless-stopped
48 command: >
49 sh -c "
50 while ! nc -z forgejo 3000; do sleep 1; done;
51 forgejo-runner daemon
52 "
53
54 docker-in-docker:
55 image: docker:dind
56 container_name: forgejo-dind
57 privileged: true
58 environment:
59 - DOCKER_TLS_CERTDIR=/certs
60 volumes:
61 - docker-certs:/certs
62 - dind-data:/var/lib/docker
63 networks:
64 - forgejo-network
65 restart: unless-stopped
66
67 db:
68 image: postgres:15-alpine
69 container_name: forgejo-db
70 environment:
71 - POSTGRES_USER=forgejo
72 - POSTGRES_PASSWORD=${DB_PASSWORD}
73 - POSTGRES_DB=forgejo
74 volumes:
75 - postgres-data:/var/lib/postgresql/data
76 networks:
77 - forgejo-network
78 restart: unless-stopped
79
80 redis:
81 image: redis:7-alpine
82 container_name: forgejo-redis
83 volumes:
84 - redis-data:/data
85 networks:
86 - forgejo-network
87 restart: unless-stopped
88
89volumes:
90 forgejo-data:
91 runner-data:
92 docker-certs:
93 dind-data:
94 postgres-data:
95 redis-data:
96
97networks:
98 forgejo-network:
99 driver: bridge

.env Template

.env
1# Forgejo with Actions
2DB_PASSWORD=secure_forgejo_password
3
4# Runner registration token (get from Forgejo admin)
5RUNNER_TOKEN=your_runner_token

Usage Notes

  1. 1Forgejo at http://localhost:3000
  2. 2Register runner in Forgejo admin settings
  3. 3GitHub Actions compatible workflows
  4. 4Uses Docker-in-Docker for isolation
  5. 5Support for .forgejo/workflows/

Individual Services(5 services)

Copy individual services to mix and match with your existing compose files.

forgejo
forgejo:
  image: codeberg.org/forgejo/forgejo:7
  container_name: forgejo
  environment:
    - USER_UID=1000
    - USER_GID=1000
    - FORGEJO__database__DB_TYPE=postgres
    - FORGEJO__database__HOST=db:5432
    - FORGEJO__database__NAME=forgejo
    - FORGEJO__database__USER=forgejo
    - FORGEJO__database__PASSWD=${DB_PASSWORD}
    - FORGEJO__cache__ADAPTER=redis
    - FORGEJO__cache__HOST=redis://redis:6379/0
    - FORGEJO__session__PROVIDER=redis
    - FORGEJO__session__PROVIDER_CONFIG=redis://redis:6379/1
    - FORGEJO__actions__ENABLED=true
  volumes:
    - forgejo-data:/data
    - /etc/timezone:/etc/timezone:ro
    - /etc/localtime:/etc/localtime:ro
  ports:
    - "3000:3000"
    - "222:22"
  depends_on:
    - db
    - redis
  networks:
    - forgejo-network
  restart: unless-stopped
runner
runner:
  image: code.forgejo.org/forgejo/runner:3.3.0
  container_name: forgejo-runner
  environment:
    - DOCKER_HOST=tcp://docker-in-docker:2376
    - DOCKER_TLS_VERIFY=1
    - DOCKER_CERT_PATH=/certs/client
  volumes:
    - runner-data:/data
    - docker-certs:/certs/client:ro
  depends_on:
    - forgejo
    - docker-in-docker
  networks:
    - forgejo-network
  restart: unless-stopped
  command: |
    sh -c "
      while ! nc -z forgejo 3000; do sleep 1; done;
      forgejo-runner daemon
    "
docker-in-docker
docker-in-docker:
  image: docker:dind
  container_name: forgejo-dind
  privileged: true
  environment:
    - DOCKER_TLS_CERTDIR=/certs
  volumes:
    - docker-certs:/certs
    - dind-data:/var/lib/docker
  networks:
    - forgejo-network
  restart: unless-stopped
db
db:
  image: postgres:15-alpine
  container_name: forgejo-db
  environment:
    - POSTGRES_USER=forgejo
    - POSTGRES_PASSWORD=${DB_PASSWORD}
    - POSTGRES_DB=forgejo
  volumes:
    - postgres-data:/var/lib/postgresql/data
  networks:
    - forgejo-network
  restart: unless-stopped
redis
redis:
  image: redis:7-alpine
  container_name: forgejo-redis
  volumes:
    - redis-data:/data
  networks:
    - forgejo-network
  restart: unless-stopped

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 forgejo:
5 image: codeberg.org/forgejo/forgejo:7
6 container_name: forgejo
7 environment:
8 - USER_UID=1000
9 - USER_GID=1000
10 - FORGEJO__database__DB_TYPE=postgres
11 - FORGEJO__database__HOST=db:5432
12 - FORGEJO__database__NAME=forgejo
13 - FORGEJO__database__USER=forgejo
14 - FORGEJO__database__PASSWD=${DB_PASSWORD}
15 - FORGEJO__cache__ADAPTER=redis
16 - FORGEJO__cache__HOST=redis://redis:6379/0
17 - FORGEJO__session__PROVIDER=redis
18 - FORGEJO__session__PROVIDER_CONFIG=redis://redis:6379/1
19 - FORGEJO__actions__ENABLED=true
20 volumes:
21 - forgejo-data:/data
22 - /etc/timezone:/etc/timezone:ro
23 - /etc/localtime:/etc/localtime:ro
24 ports:
25 - "3000:3000"
26 - "222:22"
27 depends_on:
28 - db
29 - redis
30 networks:
31 - forgejo-network
32 restart: unless-stopped
33
34 runner:
35 image: code.forgejo.org/forgejo/runner:3.3.0
36 container_name: forgejo-runner
37 environment:
38 - DOCKER_HOST=tcp://docker-in-docker:2376
39 - DOCKER_TLS_VERIFY=1
40 - DOCKER_CERT_PATH=/certs/client
41 volumes:
42 - runner-data:/data
43 - docker-certs:/certs/client:ro
44 depends_on:
45 - forgejo
46 - docker-in-docker
47 networks:
48 - forgejo-network
49 restart: unless-stopped
50 command: >
51 sh -c "
52 while ! nc -z forgejo 3000; do sleep 1; done;
53 forgejo-runner daemon
54 "
55
56 docker-in-docker:
57 image: docker:dind
58 container_name: forgejo-dind
59 privileged: true
60 environment:
61 - DOCKER_TLS_CERTDIR=/certs
62 volumes:
63 - docker-certs:/certs
64 - dind-data:/var/lib/docker
65 networks:
66 - forgejo-network
67 restart: unless-stopped
68
69 db:
70 image: postgres:15-alpine
71 container_name: forgejo-db
72 environment:
73 - POSTGRES_USER=forgejo
74 - POSTGRES_PASSWORD=${DB_PASSWORD}
75 - POSTGRES_DB=forgejo
76 volumes:
77 - postgres-data:/var/lib/postgresql/data
78 networks:
79 - forgejo-network
80 restart: unless-stopped
81
82 redis:
83 image: redis:7-alpine
84 container_name: forgejo-redis
85 volumes:
86 - redis-data:/data
87 networks:
88 - forgejo-network
89 restart: unless-stopped
90
91volumes:
92 forgejo-data:
93 runner-data:
94 docker-certs:
95 dind-data:
96 postgres-data:
97 redis-data:
98
99networks:
100 forgejo-network:
101 driver: bridge
102EOF
103
104# 2. Create the .env file
105cat > .env << 'EOF'
106# Forgejo with Actions
107DB_PASSWORD=secure_forgejo_password
108
109# Runner registration token (get from Forgejo admin)
110RUNNER_TOKEN=your_runner_token
111EOF
112
113# 3. Start the services
114docker compose up -d
115
116# 4. View logs
117docker 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/forgejo-actions/run | bash

Troubleshooting

  • Runner registration fails with 'connection refused': Ensure Forgejo is fully started before runner attempts registration, check network connectivity between containers
  • Actions workflows fail with Docker permission errors: Verify docker-in-docker container is running with privileged mode and proper TLS certificate mounting
  • PostgreSQL connection timeout during startup: Increase DB_PASSWORD complexity, check PostgreSQL container logs for authentication failures or resource constraints
  • Redis session data not persisting: Confirm Redis volume mounting and check for Redis memory limits causing data eviction in high-traffic scenarios
  • Forgejo web interface returns 500 errors: Check database migration status and ensure PostgreSQL has sufficient disk space for repository metadata
  • Git clone operations timeout: Verify SSH port 222 accessibility and check Forgejo SSH key configuration for the git user

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