2 Commits
Author SHA1 Message Date
JMR-devandClaude Opus 5.5 90383ad1bd runners: fixes from the first deploy
Three things only a live cluster showed:

- dockerd crash-looped with `chmod /home/rootless/.local/share/docker:
  operation not permitted`. It chmods an existing data root, and the
  PVC mount point is owned by host root, which fsGroup does not change
  and which is unmapped inside rootlesskit's user namespace. data-root
  now points at a subdirectory dockerd creates itself.
- Pulumi reported the StatefulSet ready while that was happening: with
  no probe, a container is ready the moment it starts. A `docker info`
  readiness probe makes the await mean the daemon is up.
- DNS timed out in the runner pod. GKE enables NodeLocal DNSCache on new
  clusters, so the kube-dns Service IP is answered by node-local-dns,
  which the NetworkPolicy did not allow. The DNS rule now allows both.

Also: leaving privateClusterConfig.enablePrivateEndpoint unset was a
diff on every run (the provider reads it back as true with IP endpoints
disabled), so it is now set to true. docs/runners.md troubleshooting is
updated with what the deploy actually showed: COS supports rootless
dockerd, and Cloud NAT hairpins to the VM's external IP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:06:10 -05:00
JMR-devandClaude Opus 5.5 ec4de0c6c4 Run Gitea Actions jobs on a dedicated GKE cluster
gitea:runnersEnabled creates a zonal GKE Standard cluster, used for
nothing else, running the official gitea/runner image in rootless
Docker-in-Docker, so workflows can `docker build`. Off by default; with
the gate off the stack only gains the container API.

- private spot nodes, egress through Cloud NAT on a static IP; control
  plane reachable only through its IAM-gated DNS endpoint
- the registration token is a Secret Manager secret created by
  scripts/bootstrap.sh; Gitea reads it from a file, the runner pod
  mounts it through the Secret Manager CSI add-on with Workload
  Identity. Pulumi never sees the value
- a NetworkPolicy keeps job containers off the metadata server and
  private ranges, so jobs hold no GCP identity
- Caddy routes /api/actions, /api/actions_pipeline and the artifact
  service around the WAF (protobuf and PUT/PATCH uploads); fail2ban
  ignores the NAT address
- docs/runners.md: threat model, cost, enable/disable, token rotation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:31:15 +07:00