# ForgeJo Runner : Uses a side-container with DinD apiVersion: apps/v1 kind: Deployment metadata: name: forgejo-runner namespace: forgejo spec: # Single replica, the concurrency is handled by the runner itself replicas: 1 selector: matchLabels: app: forgejo-runner template: metadata: labels: app: forgejo-runner spec: containers: # Runner : main container - name: forgejo-runner image: code.forgejo.org/forgejo/runner:3.3.0 command: - /bin/sh - -c - | # Register the runner on first boot if .runner does not exist yet. # The register step contacts Forgejo, exchanges the registration token # for a session token, and writes it to /data/.runner. # On subsequent starts the file already exists and we skip straight to daemon. if [ ! -f /data/.runner ]; then forgejo-runner register \ --no-interactive \ --config /config/config.yaml \ --instance "$GITEA_INSTANCE_URL" \ --token "$GITEA_RUNNER_REGISTRATION_TOKEN" fi exec forgejo-runner daemon --config /config/config.yaml env: - name: GITEA_INSTANCE_URL value: "https://git.qcampos.fr" # The runner must talk to DinD for job container management. - name: DOCKER_HOST value: "tcp://localhost:2375" - name: GITEA_RUNNER_REGISTRATION_TOKEN valueFrom: secretKeyRef: name: forgejo-runner-secret key: registration-token volumeMounts: - name: config mountPath: /config readOnly: true # Persistent storage for the .runner file (post-registration session token) - name: data mountPath: /data # DinD : side container — provides the Docker daemon for job containers - name: docker-dind image: docker:dind env: # Disable TLS so the runner connects on plain TCP port 2375 - name: DOCKER_TLS_CERTDIR value: "" securityContext: # Required for DinD to create kernel namespaces and run containers privileged: true volumeMounts: # Persist Docker layer cache across pod restarts to speed up builds - name: docker-storage mountPath: /var/lib/docker # Registry credentials — mounted here so DinD can bind-mount this # path into job containers (e.g. Kaniko) via container.options. # The file is exposed at /run/secrets/docker/config.json. - name: registry-credentials mountPath: /run/secrets/docker readOnly: true volumes: - name: config configMap: name: forgejo-runner-config - name: data persistentVolumeClaim: claimName: forgejo-runner-data # emptyDir is fine here — Docker layers are re-pulled after a pod restart, # which is acceptable on a VPS. Replace with a PVC if cold starts become slow. - name: docker-storage emptyDir: {} # Docker config.json for the Forgejo registry — injected from a K8s secret. # DinD bind-mounts this into every job container via container.options in the configmap. - name: registry-credentials secret: secretName: forgejo-registry-secret