route runner build container clones via public URL with CF Access

The Gitea Actions runners on Legion need build containers to be able
to clone repos. They run with network: host so they can't resolve
gitea.git.svc.cluster.local — they have to use the public URL. The
public URL sits behind Cloudflare Access, which is why the previous
naive switch (#3) had to be reverted.

This change keeps the runner daemon registered against the in-cluster
URL (no CF Access on the polling loop) but rewrites
http://gitea.git.svc.cluster.local:3000/ to
https://git.neuralplatform.ai/ inside the build container, with the
CF Access service-token headers injected via git extraHeader.

The redirect script is sourced before every job step via BASH_ENV;
the CF Access credentials reach the build container through
act_runner's container.env, which we now populate from the new
gitea-runner-cf-access Vault path that PR #5's Terraform writes.

Known limitation documented in the init script: actions/checkout's
per-job auth header is keyed to the in-cluster URL and gets dropped
after the insteadOf rewrite. Public repos work; private repos that
need that token will need a follow-up.
This commit is contained in:
Will Anderson
2026-05-04 16:19:35 -05:00
parent cbb564ccf5
commit bec948bcca
4 changed files with 119 additions and 7 deletions
@@ -1,12 +1,20 @@
---
# gitea-runner-secret — neural-platform org runner token
#
# GITEA_INSTANCE_URL stays as the in-cluster URL — the act_runner daemon
# polls it constantly and we don't want every poll to hit Cloudflare Access.
# Build containers, however, need the public URL because they run with
# network: host and can't resolve gitea.git.svc.cluster.local. The
# git-cf-access-init.sh entrypoint in the ci-base image rewrites the
# in-cluster URL to https://git.neuralplatform.ai with the CF Access
# headers from CF_ACCESS_CLIENT_ID / CF_ACCESS_CLIENT_SECRET below.
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: gitea-runner-secret
namespace: ci
annotations:
force-sync: "2026-04-23"
force-sync: "2026-05-04-cf-access"
spec:
refreshInterval: 1h
secretStoreRef:
@@ -19,11 +27,21 @@ spec:
data:
GITEA_INSTANCE_URL: "http://gitea.git.svc.cluster.local:3000"
GITEA_RUNNER_REGISTRATION_TOKEN: "{{ .runner_token }}"
CF_ACCESS_CLIENT_ID: "{{ .cf_access_client_id }}"
CF_ACCESS_CLIENT_SECRET: "{{ .cf_access_client_secret }}"
data:
- secretKey: runner_token
remoteRef:
key: secret/data/gitea
property: runner_token
- secretKey: cf_access_client_id
remoteRef:
key: secret/data/gitea-runner-cf-access
property: client_id
- secretKey: cf_access_client_secret
remoteRef:
key: secret/data/gitea-runner-cf-access
property: client_secret
---
# neuron-technologies-runner-secret — neuron-technologies org runner token
apiVersion: external-secrets.io/v1beta1
@@ -31,6 +49,8 @@ kind: ExternalSecret
metadata:
name: neuron-technologies-runner-secret
namespace: ci
annotations:
force-sync: "2026-05-04-cf-access"
spec:
refreshInterval: 1h
secretStoreRef:
@@ -43,8 +63,18 @@ spec:
data:
GITEA_INSTANCE_URL: "http://gitea.git.svc.cluster.local:3000"
GITEA_RUNNER_REGISTRATION_TOKEN: "{{ .runner_token }}"
CF_ACCESS_CLIENT_ID: "{{ .cf_access_client_id }}"
CF_ACCESS_CLIENT_SECRET: "{{ .cf_access_client_secret }}"
data:
- secretKey: runner_token
remoteRef:
key: secret/data/gitea
property: neuron_technologies_runner_token
- secretKey: cf_access_client_id
remoteRef:
key: secret/data/gitea-runner-cf-access
property: client_id
- secretKey: cf_access_client_secret
remoteRef:
key: secret/data/gitea-runner-cf-access
property: client_secret