No description
Find a file
2025-12-15 19:11:17 -06:00
runner-config refactored deployments 2025-12-15 19:11:17 -06:00
.env.example init commit 2025-12-13 22:21:42 -06:00
.gitignore init commit 2025-12-13 22:21:42 -06:00
CLAUDE.md updated docs 2025-12-14 08:09:34 -06:00
docker-compose.yml refactored deployments 2025-12-15 19:11:17 -06:00
README.md setup runners 2025-12-14 17:41:56 -06:00

Forgejo Docker Setup

Self-hosted Git service using Forgejo with Traefik reverse proxy and PostgreSQL database.

Prerequisites

  • Docker and Docker Compose installed
  • Traefik reverse proxy running with external traefik network
  • DNS record pointing to your server
  • Borg backup configured for Docker volume backups

Quick Start

  1. Create environment file:

    cp .env.example .env
    
  2. Configure environment variables: Edit .env and set:

    • DB_PASSWORD - Strong database password
    • FORGEJO_DOMAIN - Your domain (e.g., git.example.com)
    • FORGEJO_ROOT_URL - Full URL (e.g., https://git.example.com)
    • SSH_PORT - SSH port for Git operations (default: 2222)
    • Leave GITEA_RUNNER_REGISTRATION_TOKEN empty for now (see Runner Setup below)
  3. Ensure Traefik network exists:

    docker network create traefik
    
  4. Start services (without runner initially):

    # Start only Forgejo and database first
    docker compose up -d forgejo db
    
  5. Complete initial setup:

    • Navigate to your domain and complete the setup wizard
    • Create an admin account
    • Enable Actions in Site Administration > Actions (if not already enabled)
  6. Configure the runner (after initial setup):

    • In Forgejo web UI, go to: Admin Settings > Actions > Runners
    • Click "Create new Runner" and copy the registration token
    • Add the token to .env as GITEA_RUNNER_REGISTRATION_TOKEN
    • Start the runner: docker compose up -d runner

SSH Configuration

Forgejo's SSH service is exposed on port 2222 (configurable via SSH_PORT in .env).

Clone via SSH:

git clone ssh://git@git.example.com:2222/username/repo.git

Configure SSH client:

Add to ~/.ssh/config:

Host git.example.com
    Port 2222
    User git

Then clone normally:

git clone git@git.example.com:username/repo.git

Initial Setup

  1. Navigate to your Forgejo domain
  2. Complete the installation wizard
  3. Create an admin account
  4. Configure any additional settings

Management

View logs:

docker compose logs -f forgejo

Restart services:

docker compose restart

Stop services:

docker compose down

Backup:

This service uses Docker named volumes for data persistence. Backups are handled via Borg, which is configured to backup Docker volumes.

The following volumes are backed up:

  • forgejo_data - Forgejo repositories and configuration
  • postgres_data - PostgreSQL database
  • runner_data - Runner configuration and cache

Manual backup commands (if needed):

# Backup database to SQL file
docker compose exec db pg_dump -U forgejo forgejo > backup.sql

# Backup Forgejo data volume
docker run --rm \
  -v forgejo_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/forgejo-data-$(date +%Y%m%d).tar.gz /data

Forgejo Actions Runner

The runner is included by default for CI/CD workflows. It must be configured after initial Forgejo setup.

Runner Setup Process

  1. Complete Forgejo initial setup (see Quick Start above)

  2. Generate registration token:

    • Login as admin
    • Navigate to: Site Administration > Actions > Runners
    • Click "Create new Runner"
    • Copy the registration token
  3. Configure runner:

    # Edit .env and add the token
    nano .env
    # Set: GITEA_RUNNER_REGISTRATION_TOKEN=your_token_here
    
  4. Start the runner:

    docker compose up -d runner
    
  5. Verify runner is connected:

    • Go back to Admin Settings > Actions > Runners
    • You should see "main-runner" listed as online

Testing the Runner

To verify your runner is working correctly, create a test repository and add a simple workflow:

  1. Create a new repository in Forgejo (or use an existing one)

  2. Create the workflow file .forgejo/workflows/test.yml:

    name: Test Runner
    on: [push]
    
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - name: Hello World
            run: echo "Runner is working!"
          - name: Show system info
            run: |
              echo "Running on: $(uname -a)"
              echo "Docker available: $(docker --version)"
    
  3. Commit and push the workflow file

  4. Check the Actions tab in your repository to see the workflow run

If the workflow executes successfully and shows "Runner is working!", your runner is configured correctly!

Customizing Runner Labels

Edit GITEA_RUNNER_LABELS in .env to support different environments:

# Default: Ubuntu with Node.js 20 and Docker-in-Docker
GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bookworm,docker:docker://docker:dind

# Add more environments:
GITEA_RUNNER_LABELS=ubuntu-latest:docker://node:20-bookworm,node-18:docker://node:18-alpine,docker:docker://docker:dind

Using Actions in Repositories

Create .forgejo/workflows/ or .gitea/workflows/ in your repository with workflow YAML files:

name: CI
on: [push, pull_request]

jobs:
  test:
    runs-on: deploy  # Uses deployment runners on the server
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: npm test

Remote Runners

Runners can be deployed on any machine that has network access to your Forgejo instance. This allows you to:

  • Offload CI/CD work from your production server
  • Use spare/older hardware for builds and tests
  • Scale horizontally by adding more runner machines
  • Separate CI tasks from deployment tasks using different labels

Remote Runner Setup (e.g., Desktop/Workstation)

Follow these steps to set up a runner on a remote machine:

1. Install Docker

On your remote machine (Ubuntu/Debian):

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add your user to docker group (optional - allows non-root docker)
sudo usermod -aG docker $USER
newgrp docker

2. Create Runner Directory

mkdir -p ~/forgejo-runner
cd ~/forgejo-runner

3. Get Registration Token

On your Forgejo server:

  1. Login as admin
  2. Go to: Site Administration > Actions > Runners
  3. Click "Create new Runner"
  4. Copy the registration token

Note: The same token can be used for multiple runners - each will register as a separate instance.

4. Create Docker Compose File

Create docker-compose.yml on your remote machine:

networks:
  runner-network:
    driver: bridge

volumes:
  runner_data:
  docker_certs:

services:
  docker-dind:
    image: docker:dind
    container_name: ci-runner-docker-dind
    restart: unless-stopped
    privileged: true
    networks:
      - runner-network
    command: ['dockerd', '-H', 'tcp://0.0.0.0:2375', '--tls=false']
    volumes:
      - docker_certs:/certs

  ci-runner:
    image: data.forgejo.org/forgejo/runner:11
    container_name: ci-runner
    restart: unless-stopped
    networks:
      - runner-network
    environment:
      # Replace with your Forgejo domain
      - GITEA_INSTANCE_URL=https://git.bobparsons.dev
      - GITEA_RUNNER_REGISTRATION_TOKEN=YOUR_TOKEN_HERE
      - GITEA_RUNNER_NAME=ci-runner
      # Use "ci" label to differentiate from deployment runners
      - GITEA_RUNNER_LABELS=ci:docker://node:20-bookworm
      - DOCKER_HOST=tcp://docker-dind:2375
    volumes:
      - runner_data:/data
    command: >
      sh -c "if [ ! -f /data/.runner ]; then forgejo-runner register --no-interactive --instance $${GITEA_INSTANCE_URL} --token $${GITEA_RUNNER_REGISTRATION_TOKEN} --name $${GITEA_RUNNER_NAME} --labels $${GITEA_RUNNER_LABELS}; fi && forgejo-runner daemon"
    depends_on:
      - docker-dind

5. Configure Runner Capacity (Optional)

For high-capacity machines (like a 14900K with 64GB RAM), increase job capacity:

# Generate config file
docker compose run --rm ci-runner forgejo-runner generate-config > config.yml

# Edit config.yml and change:
# capacity: 1  ->  capacity: 6  (or whatever suits your hardware)

# Mount config in docker-compose.yml:
volumes:
  - runner_data:/data
  - ./config.yml:/data/config.yml:ro

# Update command:
command: >
  sh -c "if [ ! -f /data/.runner ]; then forgejo-runner register --no-interactive --instance $${GITEA_INSTANCE_URL} --token $${GITEA_RUNNER_REGISTRATION_TOKEN} --name $${GITEA_RUNNER_NAME} --labels $${GITEA_RUNNER_LABELS}; fi && forgejo-runner daemon -c /data/config.yml"

6. Start the Runner

# Replace YOUR_TOKEN_HERE in docker-compose.yml first!
docker compose up -d

# Check logs
docker compose logs -f ci-runner

7. Verify Registration

In Forgejo UI (Site Administration > Actions > Runners), you should see your remote runner listed as online.

Using Different Runners in Workflows

Use the runs-on field to target specific runners by label:

name: Full CI/CD Pipeline
on: [push]

jobs:
  # Runs on remote CI runner (fast desktop/workstation)
  lint:
    runs-on: ci
    steps:
      - uses: actions/checkout@v4
      - name: Lint code
        run: npm run lint

  test:
    runs-on: ci
    needs: lint
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: npm test

  build:
    runs-on: ci
    needs: test
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .

  # Runs on server deployment runners
  deploy:
    runs-on: deploy
    needs: build
    steps:
      - name: Deploy to production
        run: ./deploy.sh

Runner Label Strategy

Recommended setup:

  • Remote machines (CI): Use label ci for linting, testing, building
  • Server (Deployment): Use label deploy for production deployments
  • Specialized: Add labels like ci-python, build-heavy, etc. as needed

Managing Remote Runners

# View runner logs
docker compose logs -f ci-runner

# Restart runner
docker compose restart ci-runner

# Stop runner
docker compose down

# Update runner
docker compose pull
docker compose up -d

Architecture

  • Forgejo: Git service (port 3000 internal)
  • PostgreSQL: Database backend
  • Forgejo Runner: CI/CD runner with Docker-in-Docker support
  • Traefik: Reverse proxy with automatic HTTPS
  • Networks:
    • traefik (external): Routes traffic from Traefik
    • forgejo-internal: Private network for Forgejo ↔ DB ↔ Runner communication

Troubleshooting

Check service health:

docker compose ps

Database connection issues:

docker compose logs db

Traefik routing issues:

docker compose logs forgejo
# Check Traefik dashboard at traefik.bobparsons.dev

References