forgejo-runner install does not check the Docker Engine, and its group warning understates a fatal condition #142
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/rig#142
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
forgejo-runner daemontreats a missing Docker Engine as fatal — it exits 1 immediately and never connects. From @andres's ci-box, 2026-08-01:rig installed it anyway, registered it against the instance, and said "installed and running".
Two defects
1. There is no Docker preflight.
commands/forgejo-runner-install.shchecks only for the group, at:270-278, and only warns. A box with no Docker at all sails through registration.2. The warning that does exist is wrong.
:277:"jobs using
docker://labels will fail" understates it by a category. Without Docker there are no jobs to fail — the daemon never starts, so the runner is Offline forever. An operator reading that line reasonably concludes they have a working runner that cannot run some workloads, and goes looking in the wrong place. @andres did exactly that, for thirteen minutes of crash-loop.The warning is also about the wrong thing: group membership is a permissions detail, whereas the daemon's hard requirement is a reachable socket. A box can have the group and no Engine.
Why it should refuse, not warn
The check happens before registration, and registration consumes a token the operator minted by hand. Installing a runner that provably cannot start, after spending their token, is the same shape as #139: a secret paid into a run that could never succeed.
rigrefuses rather than guessing elsewhere for exactly this reason —bootstrapon an unmet precondition, and nowrequire_admin_binson aPATHwithout/usr/sbin(#139).Spec
Refuse before registering when the Docker Engine is not reachable.
docker infosucceeding, or the socket existing and answering — group membership stays a separate, softer check.rig bootstrap ci-boxinstalls Docker; elsewhere, the operator installs it.:277so it states the real consequence — the runner will not start — rather than implying degraded operation.Tasks
test/cli.sh: a box with no reachable Engine refuses, and refuses before the token promptchangelog.d/<n>.mdAcceptance criteria
installexits non-zero naming the remedybash test/cli.shpasses; CI'sshellcheck -xstep is cleanTest plan
dockerabsent / failing and assert the refusal text and its ordering against the token prompt.Dependencies
Related to #141 — that assert is why this failure was reported as success. They are separable: #141 would have lied about any startup failure; this one is the specific precondition that caused it. Same doctrine as #139.
@andres — filed, not fixed, per your instruction.