vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Make the packaged runner able to create a container on Debian and Ubuntu
9704d735dbcce94c67307e0ac4bbef76819768e8 · Keenan Nemetz · 2h ago · parent b7396a11
Make the packaged runner able to create a container on Debian and Ubuntu Three failures in a row stop a machine built exactly as docs/deploy/runner.md says, and each one is a setting the distributions either get wrong or leave out: - The unit sets NoNewPrivileges=true. Rootless podman, Docker, and nerdctl all map the caller into the container through setuid newuidmap and newgidmap, and that setting stops a setuid helper from gaining privilege, so the mapping fails before a container exists. Turn it off and say why: the isolation a job gets is its container, so the rest of the hardening stays. - Debian and Ubuntu ship /etc/containers/registries.conf entirely commented out, so a digest-pinned base image written as a short name has no registry to resolve against. Install unqualified-search-registries = ["docker.io"] as a drop-in. The reference's digest is the pin; the list only says where to ask, and a site can override it with a higher-numbered file. Chosen over qualifying the repository's own .vole/images, because a contributor adding a workflow later hits the same wall on a machine they cannot edit. - vole-runner runs as a system service, so the runner's account has no systemd user manager for podman to ask for a cgroup scope; crun falls back to sd-bus, which answers Interactive authentication required, and the first RUN step dies. Install [engine] cgroup_manager = "cgroupfs" as a drop-in, which writes into the subtree Delegate=yes already gives the service. Both drop-ins merge with the distribution's configuration instead of replacing it, and reach the runner's account because system configuration is read for rootless users too. Every install path installs the package, so the cloud-init template needs no second copy of either setting to drift. docs/deploy/runner.md says what each file is for and what the failure looks like without it, and names the user-unit-with-enable-linger arrangement as the alternative an operator may choose, including the /run/user/<uid> conflict with the unit's XDG_RUNTIME_DIR. scripts/check-deploy.py now fails when the package stops installing either drop-in, or when the unit goes back to defeating the uid mapping: a runner missing one takes a job and fails it before a step runs, which reads on the instance as a repository whose build broke. Closes 01M6YW9ZWB69GVFN7BR53SPWC6 Closes 01M6YWA3JX0WWHJ55JCVDZ2QTP Closes 01M6YWA79EWR97YYK5NR7R19CK
docs/deploy/runner.md +30
| @@ -83,6 +83,36 @@ sudo systemctl edit vole-runner # [Service] / TimeoutStopSec=30min | |||
| 83 | 83 | `systemctl status vole-runner` and `journalctl -u vole-runner` are where a runner | |
| 84 | 84 | that is not taking work says why. | |
| 85 | 85 | ||
| 86 | ## What the package configures in the container runtime | ||
| 87 | |||
| 88 | A rootless runtime needs two settings the distributions do not agree on, so the | ||
| 89 | package installs both as drop-ins. Each merges with the distribution's own file | ||
| 90 | instead of replacing it, and both reach the runner's account: system configuration | ||
| 91 | is read for rootless users too, so nothing has to be written into a home directory. | ||
| 92 | |||
| 93 | | File | What it sets, and why | | ||
| 94 | |---|---| | ||
| 95 | | `/etc/containers/registries.conf.d/50-vole-runner.conf` | `unqualified-search-registries = ["docker.io"]`. Debian and Ubuntu ship `registries.conf` entirely commented out, so a base image named as a short name has no registry to resolve against and the build fails with `short-name … did not resolve to an alias and no unqualified-search registries are defined`. The digest in `.vole/images` is the pin; this list only says where to ask. | | ||
| 96 | | `/etc/containers/containers.conf.d/50-vole-runner.conf` | `[engine] cgroup_manager = "cgroupfs"`. `vole-runner.service` is a system service, so the runner's account has no systemd user manager for podman to ask for a cgroup scope. It falls back to sd-bus, which answers `Interactive authentication required`, and the first `RUN` step of an image build fails. `cgroupfs` writes into the cgroup subtree `Delegate=yes` already gives the service. | | ||
| 97 | |||
| 98 | A site that wants a different registry list writes its own drop-in with a higher | ||
| 99 | number, such as `99-site.conf`, which is read after these. | ||
| 100 | |||
| 101 | The unit also runs with `NoNewPrivileges=false`, alone among the units this package | ||
| 102 | installs. Rootless podman, Docker, and nerdctl all map the calling user into the | ||
| 103 | container through setuid `newuidmap` and `newgidmap`; under `NoNewPrivileges=true` | ||
| 104 | a setuid helper cannot gain privilege, so the mapping fails before a container | ||
| 105 | exists (`newuidmap: write to uid_map failed: Operation not permitted`). The | ||
| 106 | isolation a job gets is its container, not the unit's sandbox, so the rest of the | ||
| 107 | hardening stays. | ||
| 108 | |||
| 109 | If you would rather give podman the systemd user manager it prefers, run the | ||
| 110 | runner as a user unit instead: `loginctl enable-linger ci-runner`, a unit in | ||
| 111 | `ci-runner`'s own `systemctl --user` session, and no `cgroup_manager` setting. That | ||
| 112 | session lives at `/run/user/<uid>`, so the unit's `RuntimeDirectory=vole-runner` and | ||
| 113 | `XDG_RUNTIME_DIR=/run/vole-runner` have to go with it — the two arrangements cannot | ||
| 114 | both be assumed, and this one is not what the shipped unit does. | ||
| 115 | |||
| 86 | 116 | ## Register the runner, then allow it on a repository | |
| 87 | 117 | ||
| 88 | 118 | The runner's key is not an admin key. It becomes a bot account, and the | |