runuser joins the admin-binary preflight — and runner remove gets the preflight it lacks #148
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:bootstrap
scope:coolify
scope:db
scope:docs
scope:drill
scope:installer
scope:labels
scope:platform
scope:runner
scope:users
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/rig#148
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Normalized from @andres's report (2026-08-04), kept verbatim:
Root cause, measured on Debian 13 (2026-08-17):
runuserships inutil-linux—Essential: yes, so it is on every Debian system — at/usr/sbin/runuser.apt-get install util-linuxis therefore a no-op; the binary was present. What was missing was/usr/sbinon the root shell's PATH (suwithout-, sanitisedsecure_path, some container images) — the exact family #139 named, whose fix (!140, merged 2026-08-02) postdates the0.3.1release the installer serves, so an installed rig had no preflight at all when this was hit.On
mainatcb4de44the install-time instance is largely fixed —commands/lib/admin-path.shrefuses a sbin-less PATH before any prompt. Two residues remain, and they are this issue:commands/runner-remove.shhas no preflight at all, yet callsrunuserat:101and:106. On a PATH-shorn root it dies mid-teardown with the same barecommand not found, after it has started changing state.runuserdo not name it.forgejo-runner-install.sh:244namesuseradd usermodbut callsrunuserat:478;runner-install.sh:93namesuseradd, callsrunuserat:190;bootstrap-tenant.sh:213namesusermod, callsrunuserat:406.admin-path.sh's own rule is "BOTH binaries this command goes on to call" — a preflight that names most of its call sites is the hole the next bug arrives through (#75's shape).runuseris same-directory/usr/sbin, so it belongs in the lists — unlikegpasswd, whose exclusion the lib's comment already defends.Spec
admin-path.sh's measured table gains therunuserrow:/usr/sbin, packageutil-linux(Essential — so its absence is always a PATH fact, never a missing package). The die message is already correct and does not change.runner-remove.shsourcesadmin-path.shand callsrequire_admin_bins runuserbeside its root check, before any state change — the same placement doctrine as the four existing call sites.forgejo-runner-install.sh,runner-install.sh,bootstrap-tenant.shaddrunuserto their existingrequire_admin_binsargument lists. No new call sites.users-close-root.shis out of scope: its soft-skip (:118) is deliberate, documented behaviour.forgejo-runner-remove.shcalls no/usr/sbinbinary — verified — and stays untouched.Tasks
commands/lib/admin-path.sh— add therunuser/util-linuxrow to the measured tablecommands/runner-remove.sh— source the lib,require_admin_bins runuserbeside the root checkcommands/forgejo-runner-install.sh:244→useradd usermod runuser;commands/runner-install.sh:93→useradd runuser;commands/bootstrap-tenant.sh:213→usermod runusertest/cli.sh— extend the#139block (:3337, theSBINLESSidiom) with arunner-removerefusal check; update any pinned caller-count the suite keeps onadmin-pathchangelog.d/148.mdAcceptance criteria
/usr/sbin,runner-remove.shexits non-zero namingrunuserand thePATH=/usr/sbin:/sbin:$PATHremedy, before touching unit, user, or directory staterunuser;grep -n 'require_admin_bins' commands/*.shshows it at every command that later callsrunuser(exceptusers-close-root.sh)users-close-root.shbehaviour is byte-unchangedshellcheckstep clean;bash test/cli.shpasseschangelog.d/148.mdsays what changed, one line per surfaceTest plan
Driven through
test/cli.sh's existing#139idiom (stubbedid -u=0,SBINLESSPATH):runner-remove.shunder the sbin-less PATH → exit non-zero, message namesrunuser, and no teardown side effect is observable in the sandbox.runuserfrom a widened list turns the new coverage red.Dependencies
Refs #139 (the family), !140 (the fix this extends). Not blocked: the 0.3.2 release ships the install-side fix regardless; this closes the family's remaining door.
Mising runuser command not found (using debian 13to runuser joins the admin-binary preflight — and runner remove gets the preflight it lacksNormalized to contract — and your
apt-getquestion answered@andres — triage here. Your report was real and is now the work order above; your original text is quoted verbatim in Context. The one correction worth stating:
sudo apt-get install util-linuxwould not have helped.util-linuxisEssential: yeson Debian —runuserwas already on the box, at/usr/sbin/runuser. The shell just could not see it, because that root shell's PATH carried no/usr/sbin(asuwithout-does this, and so do some container images).PATH=/usr/sbin:/sbin:$PATH rig …, orsu -instead ofsu, is the immediate remedy on any installed release.The install-time version of this is already fixed on
main— #139/!140 (merged 2026-08-02) refuses a sbin-less PATH before the token prompt, with that remedy in the message — and ships with the next release;0.3.1, which the installer currently serves, predates it, which is why you still hit the bare error on 2026-08-04. What this issue now owns is the residue:runner removehas no such guard at all, and the guards that exist don't namerunusereven where they go on to call it. Spec, tasks, and test plan above; labeledready.