No description
Find a file
Bob Parsons 1e21ac5cee
Some checks failed
YAML Lint and Fix / yaml-lint-fix (push) Failing after 0s
add kirria pipeline runner
2026-04-13 07:48:19 -05:00
.forgejo/workflows updated infiscio runners 2026-03-28 22:22:18 -05:00
runner-config probably wrong inf config 2026-03-28 22:45:24 -05:00
runner-images change base 2026-03-28 22:54:57 -05:00
.env.example add kirria runner 2026-04-11 16:54:42 -05:00
.env.runner.example add runner and workflow for linting 2025-12-15 21:23:12 -06:00
.gitignore add runner and workflow for linting 2025-12-15 21:23:12 -06:00
.prettierrc add prettier 2025-12-15 21:27:19 -06:00
.yamllint add runner and workflow for linting 2025-12-15 21:23:12 -06:00
CLAUDE.md updated docs 2025-12-14 08:09:34 -06:00
docker-compose.runner.yml add runner and workflow for linting 2025-12-15 21:23:12 -06:00
docker-compose.yml add kirria pipeline runner 2026-04-13 07:48:19 -05:00
README.md add kirria runner 2026-04-11 16:54:42 -05:00
RUNNER-SETUP.md add runner and workflow for linting 2025-12-15 21:23:12 -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

Organization-Scoped Runner

This repo also supports an organization-scoped runner for the Kirria organization without changing workflow labels in that org's repositories.

The kirria-org-runner service is intentionally separate from the existing user-level deployment runners:

  • Separate container: forgejo-kirria-org-runner
  • Separate persistent volume: kirria_org_runner_data
  • Separate token variable: KIRRIA_ORG_RUNNER_REGISTRATION_TOKEN
  • Same deploy label mapping, so existing runs-on: deploy workflows continue to match

Manual Setup On The Server

  1. Generate an organization runner token in Forgejo:

    • Go to Kirria organization > Settings > Actions > Runners
    • Click Create new Runner
    • Copy the registration token
  2. Place the token in the server's .env file:

    KIRRIA_ORG_RUNNER_REGISTRATION_TOKEN=your_kirria_org_runner_token_here
    
  3. Start only the org-scoped runner:

    docker compose up -d kirria-org-runner
    
  4. Verify registration:

    • In Forgejo UI: Kirria organization > Settings > Actions > Runners
    • Confirm kirria-org-runner appears as online
    • Confirm it shows the deploy label
  5. Optional log check:

    docker compose logs -f kirria-org-runner
    

Assumptions

  • Compose project name remains the repo default, so the internal network name for service-to-service access is still the Compose-managed network while the service joins the existing forgejo-internal network declared in docker-compose.yml
  • The Forgejo service remains reachable from runners at http://forgejo:3000 on that network
  • The deploy label format continues to be deploy:docker://git.bobparsons.dev/deadstyle/runner-images:deploy, which matches runs-on: deploy

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

📦 Quick Setup: For a simplified, reusable runner deployment, see RUNNER-SETUP.md. This guide provides a standalone Docker Compose configuration that can be easily deployed across multiple machines.

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