zegit-forgejo-runner

Custom toolchain image for the cluster's self-hosted Gitea Actions (Forgejo) runner, which runs in host mode (Docker disabled) — workflow steps execute inside this image, so it must carry node/git/make/etc. that the stock code.forgejo.org/forgejo/runner image lacks.

This repo lives only on Gitea (zegit-zoo/zegit-forgejo-runner). The cluster-side deployment and rationale live in flux-config (runners.md, applications/forgejo-runner/).

Build & push

The runner needs this image to run any job, so the first build must be done by hand (CI can't bootstrap itself). The cluster is mixed amd64/arm64, so build multi-arch:

docker buildx create --use --name zegit-ci 2>/dev/null || true
docker login gitea.langenoja.se        # username + a Gitea personal access token
docker buildx build --platform linux/amd64,linux/arm64 \
  -t gitea.langenoja.se/zegit-zoo/zegit-forgejo-runner:12.11.1-ci --push .

The Gitea package is public, so the forgejo-runner-system namespace pulls it without an imagePullSecret.

Wire it into the cluster

After the push succeeds, in flux-config applications/forgejo-runner/base/deployment-forgejo-runner.yaml set the image: on both the register initContainer and the forgejo-runner daemon to gitea.langenoja.se/zegit-zoo/zegit-forgejo-runner:12.11.1-ci, then commit (Flux reconciles). Do this only after the image exists, or the pod ImagePullBackOffs.

Tag scheme

<base-runner-version>-ci (e.g. 12.11.1-ci). Must satisfy the cluster's Gatekeeper enforce-semantic-image-tags constraint — never :latest.

Publishing a new image

./push-image.sh 12.11.1-ci4

The registry hostname in the image reference must stay gitea.langenoja.se, because that is what the cluster pulls. The script therefore keeps the NAME and changes only the ROUTE: it pins that hostname to the Istio gateway on the LAN (10.40.0.10) for the duration of the push, then removes the pin.

That matters because gitea.langenoja.se resolves to Cloudflare, which caps request bodies below a registry layer and returns 413 Payload Too Large. The gateway serves a *.langenoja.se wildcard cert, so TLS still validates normally — no insecure-registries, no --tls-verify=false.

If a run is killed before it can clean up, the pin is left behind. It carries a marker comment, so the next run recognises it as its own and removes it — or you can clear it directly:

./push-image.sh --unpin

A pin you added yourself (no marker) is never touched, and the script refuses to run if an unmarked pin points somewhere other than the gateway.

Requirements: a Gitea PAT with write:package (read:package is pull-only), LAN reachability of the gateway, and qemu/binfmt registered for the arm64 build.

Multi-arch is not optional. forgejo-runner runs on arm64 nodes and zegit-runner on amd64, neither deployment sets a nodeSelector, and both use this single tag.

Two traps the script exists to prevent: pushing to the bare MagicDNS name (gitea-system-gitea-tailscale-http) makes Docker treat it as a Docker Hub namespace, since a registry host is only recognised when it contains a dot or colon; and docker push $_ pushes ., because $_ is the last ARGUMENT of the build command, not its tag.

S
Description
No description provided
Readme
164 KiB
0 Stars 4 Watchers 0 Forks
Languages
Dockerfile 59.4%
Shell 40.6%