Third of the design's three merge requests, landing before the second on purpose.
The execution change makes the runner refuse to start without a working podman — the design is explicit that a silent fallback to unsandboxed builds is worse than a stopped runner. That makes host preparation a prerequisite, not a follow-up: on an unprepared host the refusal stops every build on the instance. Landing this first means bay1 can be prepared, and then the execution merge request's podman-gated tests actually run in CI instead of skipping everywhere.
deploy/runner-podman-setup.sh— installs podman and uidmap, delegates a subuid/subgid range toci-runner, checksuser.max_user_namespacesrather than assuming Debian 13's default, enables lingering, and verifies rootless podman runs as that user. Idempotent.- The service drop-in gains
Delegate=yesfor rootless cgroup management andReadWritePathsfor podman's store under the runner's home, whichProtectSystem=fullwould otherwise make read-only. gitbay-runner-prune.timer/.serviceprune unused images weekly as the runner's user — rootless storage belongs to that user, and root's prune would not see it. The design calls an unpruned store on a 40GB host a slow outage.
Nothing here changes the running system: no code path reads any of it yet, and the script is run by an operator, not by a deploy. I have not touched bay1.
The Admin page documents the fixed order — prepare the host, then
make deploy-runner — and says plainly not to deploy an isolating runner to an
unprepared host.
The image: parsing and validation is written and tested but deliberately not in
this stack: a config field that silently does nothing is worse than an absent
one. It is parked on runner-podman-144 for the execution merge request.
Stacked on !289.
Ref #144
retargeted from runner-env-144 to main: !289 merged
2026-09-06 20:03 UTC