Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

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 · 1h 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