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/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

#237

P1: the packaged runner unit cannot run rootless podman (NoNewPrivileges defeats setuid newuidmap)

closed · opened by keenan 22h ago

keenan opened this 22h ago

The packaged runner unit cannot run a job on a fresh Debian or Ubuntu machine. Following docs/deploy/runner.md exactly — install the package, create the account, fill in /etc/vole/runner.env — the first job dies before any workflow step runs:

time=2026-11-09T00:12:47Z level=error msg="running `/usr/bin/newuidmap 8515 0 1000 1 1 100000 65536`:
  newuidmap: write to uid_map failed: Operation not permitted"
Error: cannot set up namespace using "/usr/bin/newuidmap": exit status 1
building image-file "verify" exited 125

Ubuntu 24.04.5, podman 4.9.3, rootless. /usr/bin/newuidmap is setuid-root (-rwsr-xr-x, from the uidmap package), and vole-runner.service sets NoNewPrivileges=true, which prevents a setuid helper from gaining privilege. Rootless podman cannot write uid_map without it, so no container is ever created.

Why it matters

This is the shipped path, not a local arrangement: the unit in packaging/systemd/, the steps in docs/deploy/runner.md, and deploy/cloud-init/runner.yaml (which has no workaround either). A runner machine built by any of them is dead on arrival, and the first thing it does is fail a queued run.

What fixed it here

/etc/systemd/system/vole-runner.service.d/rootless.conf:

[Service]
NoNewPrivileges=false

The unit already says its sandboxing is deliberately lighter than vole.service because “the isolation a job gets is its container, and the runtime needs user namespaces and a writable home to build one”. NoNewPrivileges=true contradicts that note for any system where newuidmap is setuid rather than file-capability based.

Scope

  • Decide: ship the unit with NoNewPrivileges=false, or document the drop-in as a required step (and add it to deploy/cloud-init/runner.yaml).
  • If it stays on in the unit, say why next to the existing note, or the note is misleading.
  • Check the same interaction for docker and nerdctl runtime options, which share the account setup.

Acceptance criteria

A clean Ubuntu 24.04 (and Debian 13) machine, following only the documented steps, leases a job and runs it to completion with no manual unit edit.

Related: #239 and #241 are the next two failures in the same setup; a machine needs all three fixed before it finishes a job.

Comments (1)

keenan 4h ago

Taking this with #239 and #241 as one change: a machine needs all three before it finishes a job, and the three are one setup script, not three bugs.

Plan:

  • Ship the unit with NoNewPrivileges=false, and rewrite the sandboxing note rather than leaving it contradicting the setting. Rootless podman, Docker, and nerdctl all map the caller into the container through setuid newuidmap and newgidmap, so the same rule covers all three runtime options (--container-runtime).
  • Everything else in the unit stays: LimitCORE=0 is what keeps a core dump from being a copy of the runner’s key, and PrivateTmp, UMask, and Delegate=yes are not what defeats the mapping.
  • docs/deploy/runner.md says what the unit trades away and why, so the setting is a documented decision rather than a line that looks like an oversight.