No description
  • Go Template 42.7%
  • Shell 42.2%
  • Dockerfile 15.1%
Find a file
2026-06-04 12:42:22 -05:00
templates Fix resources indentation in deployment template 2026-06-04 12:42:22 -05:00
.dockerignore Initial commit: Forgejo Runner DinD image and Helm chart 2026-06-04 12:18:50 -05:00
Chart.yaml Initial commit: Forgejo Runner DinD image and Helm chart 2026-06-04 12:18:50 -05:00
Dockerfile Initial commit: Forgejo Runner DinD image and Helm chart 2026-06-04 12:18:50 -05:00
entrypoint.sh Initial commit: Forgejo Runner DinD image and Helm chart 2026-06-04 12:18:50 -05:00
forgejo-runner-dind-0.1.0.tgz Fix resources indentation in deployment template 2026-06-04 12:42:22 -05:00
README.md Add Helm chart consumption instructions to README 2026-06-04 12:27:10 -05:00
values.yaml Initial commit: Forgejo Runner DinD image and Helm chart 2026-06-04 12:18:50 -05:00

Forgejo Runner DinD

Custom container image and Helm chart for running Forgejo Actions runners on Kubernetes with rootful Docker-in-Docker support.

Overview

This project provides:

  • Custom container image combining Forgejo Runner with rootful Docker-in-Dind (DinD) in a single container.
  • Helm chart for deploying the runner as a Kubernetes Deployment.

The image is designed for docker build / docker push workflows where the runner needs its own Docker daemon.

Architecture

┌─────────────────────────────────────────────┐
│  Kubernetes Pod (privileged)                │
│                                             │
│  ┌───────────────────────────────────────┐  │
│  │ Custom Image: forgejo-runner-dind     │  │
│  │                                       │  │
│  │  ┌─────────────┐  ┌────────────────┐  │  │
│  │  │ forgejo-    │  │ dockerd        │  │  │
│  │  │ runner      │  │ (rootful DinD) │  │  │
│  │  │ daemon      │  │                │  │  │
│  │  │             │  │ :2375 (127.0.0.1)│ │  │
│  │  └─────────────┘  └────────────────┘  │  │
│  │                                       │  │
│  │  DOCKER_HOST=tcp://127.0.0.1:2375     │  │
│  └───────────────────────────────────────┘  │
└─────────────────────────────────────────────┘

Components

Component Source
forgejo-runner Official Forgejo Runner image (data.forgejo.org/forgejo/runner:12.7.3)
Docker daemon docker:27-dind
Runtime tini (init system)
Tools git, bash, curl, jq, coreutils, ca-certificates

Container Image

Building

docker build -t git.home-net.work/sjenkins/forgejo-runner-dind:12.7.3 .

Base image

  • Final stage: docker:27-dind
  • Source stage: data.forgejo.org/forgejo/runner:12.7.3

The multi-stage build copies the forgejo-runner binary from the official runner image into the DinD base.

Entrypoint

The entrypoint script (entrypoint.sh):

  1. Starts dockerd on tcp://127.0.0.1:2375 with the configured storage driver
  2. Waits for Docker daemon readiness
  3. Registers the runner with Forgejo (if not already registered)
  4. Starts forgejo-runner daemon

Helm Chart

Prerequisites

  • Kubernetes 1.25+
  • Helm 3.x
  • A Forgejo instance with Actions enabled
  • A runner registration token from your Forgejo instance

Installation

Using an existing secret

helm install forgejo-runner ./ \
  --set forgejo.instanceUrl=https://git.home-net.work \
  --set forgejo.existingSecret=my-forgejo-secret \
  --set runner.labels="docker:docker://node:20-bookworm" \
  --set image.repository=git.home-net.work/sjenkins/forgejo-runner-dind \
  --set image.tag=12.7.3 \
  --namespace forgejo-runners \
  --create-namespace

Using chart-generated secret

helm install forgejo-runner ./ \
  --set forgejo.instanceUrl=https://git.home-net.work \
  --set forgejo.registrationToken="your-registration-token-here" \
  --set runner.labels="docker:docker://node:20-bookworm" \
  --set image.repository=git.home-net.work/sjenkins/forgejo-runner-dind \
  --set image.tag=12.7.3 \
  --namespace forgejo-runners \
  --create-namespace

Configuration

See values.yaml for all available options. Key configuration:

Parameter Description Default
image.repository Container image repository git.home-net.work/sjenkins/forgejo-runner-dind
image.tag Container image tag 12.7.3
forgejo.instanceUrl Forgejo instance URL https://git.home-net.work
forgejo.existingSecret Existing secret name for registration token ""
forgejo.registrationToken Registration token (if no existing secret) ""
runner.labels Runner labels for job matching docker:docker://node:20-bookworm
runner.name Runner name (empty = pod hostname) ""
docker.storageDriver Docker storage driver overlay2
persistence.docker.enabled Use PVC for Docker graph false
persistence.runner.enabled Use PVC for runner data false
nodeSelector Node selector for pod placement {}
tolerations Tolerations for pod placement []

Example workflow

name: build
on:
  push:
    branches:
      - main

jobs:
  docker-build:
    runs-on: docker
    steps:
      - uses: actions/checkout@v4
      - name: Docker info
        run: docker info
      - name: Login
        run: echo "$REGISTRY_PASSWORD" | docker login git.home-net.work -u "$REGISTRY_USERNAME" --password-stdin
      - name: Build
        run: docker build -t git.home-net.work/sjenkins/example:latest .
      - name: Push
        run: docker push git.home-net.work/sjenkins/example:latest

Security considerations

  • Privileged pods: The container runs with privileged: true for rootful DinD.
  • Docker daemon: Bound to 127.0.0.1:2375, not exposed externally.
  • TLS disabled: DOCKER_TLS_CERTDIR="" disables DinD TLS (set a directory to enable).
  • Dedicated namespace: Recommended to isolate runners in a separate namespace.
  • Dedicated nodes: Use nodeSelector/tolerations to pin runners to worker nodes.
  • Ephemeral storage: By default uses emptyDir; use PVC-backed /var/lib/docker for large builds.

Troubleshooting

Runner not picking up jobs

  1. Verify labels match: kubectl exec <pod> -- forgejo-runner list-labels
  2. Check registration: kubectl exec <pod> -- cat /data/.runner
  3. Verify Forgejo instance URL: kubectl exec <pod> -- env | grep FORGEJO

Docker not ready

  1. Check dockerd logs: kubectl logs <pod>
  2. Verify storage driver: kubectl exec <pod> -- docker info | grep Storage
  3. Check node supports overlay2: kubectl exec --privileged <node-pod> -- modprobe overlay

Consuming the Chart

The chart is published to the Forgejo Helm package registry.

Add the repository

helm repo add forgejo-runner-dind --username <user> --password <token> \
  https://git.home-net.work/api/packages/sjenkins/helm

Update and install

helm repo update
helm search repo forgejo-runner-dind
helm install forgejo-runner forgejo-runner-dind/forgejo-runner-dind \
  --set forgejo.instanceUrl=https://git.home-net.work \
  --set forgejo.registrationToken=<token> \
  --namespace forgejo-runners \
  --create-namespace

Repository Structure

.
├── Chart.yaml              # Helm chart metadata
├── Dockerfile              # Multi-stage Docker image definition
├── entrypoint.sh           # Container entrypoint script
├── values.yaml             # Helm chart default values
├── templates/
│   ├── _helpers.tpl        # Helm template helpers
│   ├── deployment.yaml     # Kubernetes Deployment
│   ├── secret.yaml         # Registration token secret
│   ├── configmap.yaml      # Optional ConfigMap
│   └── serviceaccount.yaml # Optional ServiceAccount
└── README.md