Operator decision on PR #81: no CI job may reach a privileged daemon. The act runner is untouched. - platform/buildkit (+ clusters/base/buildkit.yaml): moby/buildkit v0.34.1-rootless pinned by digest, uid 1000, not privileged; caps drop ALL + SETUID/SETGID, seccomp/AppArmor Unconfined, read-only rootfs (each measured under podman). cert-manager CA + server/client certs, ClusterIP :1234, default-deny with ingress only from the act-runner pod (DinD masquerades jobs to it). No Kyverno exception: every applied policy matches app-namespace=true only. - Each Containerfile names its shipped stage and ends in a `verify` stage holding every former `docker run` assertion (uid 65532, RUN --network=none, writable-path inventory standing in for the read-only rootfs). The old `&& echo` checks that could never fail are real assertions now. - images.sh drives buildkitd with a pinned buildx (sha256-checked) via bake; PRs build verify targets with agent-runner FROM the in-run toolbox (target: context); main verifies, then pushes. Fails loudly when the builder secrets are absent or buildkitd is unreachable. - infra/gitea/buildkit-client-secret.sh copies the client cert into Actions secrets. Co-Authored-By: Claude Opus 5.5 <[email protected]>
27 lines
1.5 KiB
YAML
27 lines
1.5 KiB
YAML
---
|
|
# buildkit — the image builder for CI (.gitea/workflows/images.yaml). Operator decision on PR #81
|
|
# (2026-10-29): images are built by a ROOTLESS BuildKit daemon reached over mTLS, and NO CI job
|
|
# may reach a privileged daemon. See README.md for the whole design.
|
|
#
|
|
# A NAMESPACE OF ITS OWN, deliberately NOT `gitea-actions`:
|
|
# * The act-runner namespace exists to hold a PRIVILEGED DinD sidecar. Putting the builder
|
|
# beside it would put a TLS server key next to a privileged container for no benefit.
|
|
# * Its NetworkPolicies, Secrets and quota then belong to one component, and the ingress rule
|
|
# ("only the act-runner pod may connect") can be written from the outside.
|
|
#
|
|
# NO `app-namespace` LABEL, like gitea-actions: this is CI plumbing, not a user-facing app. That
|
|
# is also why NO Kyverno exception is needed — every applied ClusterPolicy
|
|
# (platform-config/kustomization.yaml) matches only namespaces labelled
|
|
# homelab.keithjackson.dev/app-namespace: "true", and none of the job-shape policies match here.
|
|
#
|
|
# NO pod-security.kubernetes.io LABEL, on purpose. Rootless BuildKit needs seccomp AND AppArmor
|
|
# `Unconfined` (measured — see deployment.yaml), which PSS `baseline` forbids; there is no
|
|
# cluster-wide PSA default here, so an unlabelled namespace admits it. It is NOT privileged and
|
|
# the deployment's securityContext is the boundary — read it before relaxing anything.
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: buildkit
|
|
labels:
|
|
homelab.keithjackson.dev/ci: buildkit
|