Skip to content

Latest commit

 

History

History
156 lines (123 loc) · 6.68 KB

File metadata and controls

156 lines (123 loc) · 6.68 KB

Forgejo Docker Compose — Deployment Spec

Target Environment

Hetzner CPX11 (2 vCPU, 4 GB RAM, 40 GB NVMe, Ubuntu 24.04 LTS)

Architecture

                        ┌──────────────────────────────────────────┐
                        │            docker network: forgejo        │
                        │                                          │
  :80/:443 ────────────►│  forgejo     forgejo-runner              │
                        │     │              │                     │
                        │     ▼              ▼                     │
                        │  postgres       redis                    │
                        │  (port 5432)   (port 6379)               │
                        └──────────────────────────────────────────┘

Services

forgejo

  • Image: codeberg.org/forgejo/forgejo:10 (latest stable major)
  • Replaces: binary + systemd from setup.sh
  • Listens: HTTP on 3000 (mapped to host 80), SSH on 22 (mapped to host 222)
  • Config delivered via environment variables (FORGEJO__section__key pattern)
  • Persistent volume: forgejo_data/data
  • Depends on: postgres, redis

postgres

  • Image: postgres:17-alpine
  • Replaces: SQLite (default in setup.sh)
  • Database: forgejo, user: forgejo
  • Persistent volume: postgres_data/var/lib/postgresql/data
  • Only reachable inside the forgejo network (no host port binding)

redis

  • Image: redis:7-alpine
  • Used as: cache adapter + session store + queue backend for Forgejo
  • No auth required inside the private network (can be enabled via requirepass)
  • Persistent volume: redis_data/data (AOF + RDB persistence)
  • Only reachable inside the forgejo network

forgejo-runner

  • Image: code.forgejo.org/forgejo/runner:6
  • Replaces: runner binary + systemd from runner.sh
  • Mounts Docker socket (/var/run/docker.sock) to run job containers
  • Configured via environment: FORGEJO_INSTANCE_URL, FORGEJO_RUNNER_REGISTRATION_TOKEN
  • Config file mounted: ./runner/config.yml/etc/runner/config.yml
  • Labels match runner.sh: docker and ubuntu-latest
  • Depends on: forgejo

Files to Be Created

.
├── docker-compose.yml          # all four services
├── .env.example                # template — copy to .env and fill in secrets
├── .env                        # gitignored — actual secrets
└── runner/
    └── config.yml              # forgejo-runner config (labels, concurrency, etc.)

Forgejo Configuration (env var approach)

All settings passed as FORGEJO__<SECTION>__<KEY> environment variables so no app.ini file is required in the repo.

Section Key Value
server DOMAIN $FORGEJO_DOMAIN (e.g. git.example.com)
server ROOT_URL https://$FORGEJO_DOMAIN/
server SSH_PORT 222
database DB_TYPE postgres
database HOST postgres:5432
database NAME forgejo
database USER forgejo
database PASSWD $POSTGRES_PASSWORD
database SSL_MODE disable
cache ADAPTER redis
cache HOST redis://redis:6379/0
session PROVIDER redis
session PROVIDER_CONFIG redis://redis:6379/1
queue TYPE redis
queue CONN_STR redis://redis:6379/2
security SECRET_KEY $FORGEJO_SECRET_KEY (random 64-char)
security INTERNAL_TOKEN $FORGEJO_INTERNAL_TOKEN

Redis uses three separate DB indexes: 0 (cache), 1 (sessions), 2 (queue) to keep keyspaces isolated.

.env Variables

FORGEJO_DOMAIN=git.example.com
POSTGRES_PASSWORD=<generate with: openssl rand -hex 32>
FORGEJO_SECRET_KEY=<generate with: openssl rand -hex 32>
FORGEJO_INTERNAL_TOKEN=<generate with: openssl rand -hex 32>
FORGEJO_RUNNER_REGISTRATION_TOKEN=<paste from Forgejo UI after first boot>

Runner Labels

Matches the labels used in runner.sh:

labels:
  - "docker:docker://node:22-bookworm"
  - "ubuntu-latest:docker://ubuntu:22.04"

Workflows that use runs-on: docker or runs-on: ubuntu-latest will be picked up by this runner.

Networking

  • Single bridge network forgejo — all services communicate by service name
  • No inter-service ports exposed to the host; only Forgejo HTTP (80) and SSH (222) are published
  • Postgres and Redis are internal-only

Volumes

Volume Purpose Approx size on CPX11
forgejo_data repos, attachments, avatars bulk of disk usage
postgres_data database files grows with activity
redis_data AOF/RDB snapshots small (<1 GB)

All volumes are named Docker volumes (managed by Docker, survive docker compose down). Use docker compose down -v only when intentionally wiping data.

First-Boot Sequence

  1. Copy .env.example to .env and fill in all values (leave FORGEJO_RUNNER_REGISTRATION_TOKEN blank for now)
  2. docker compose up -d postgres redis — let DB init complete
  3. docker compose up -d forgejo — Forgejo will run DB migrations on first start
  4. Open http://<server-ip>:80 and complete the install wizard (DB fields will be pre-filled from env)
  5. Go to Admin → Actions → Runners → New Runner and copy the registration token
  6. Add token to .env as FORGEJO_RUNNER_REGISTRATION_TOKEN
  7. docker compose up -d forgejo-runner

Upgrade Path

# Pull new images
docker compose pull

# Recreate containers (Forgejo runs migrations automatically on start)
docker compose up -d --remove-orphans

Out of Scope

  • TLS termination — handled by a reverse proxy (Caddy / nginx) in front of port 80; not included here to keep the compose self-contained
  • Backups — postgres_data and forgejo_data volumes should be snapshotted via Hetzner volume snapshots or pg_dump cron