Symptom

Ghost’s list_nodes on first contact after a “fresh” restart returned pre-existing nodes, including some whose IDs matched fixtures created during a prior verify run weeks earlier. krill.service’s ActiveEnterTimestamp confirmed a genuine restart running the new PR’s build, so the binary/restart machinery worked — only the database state failed to reset. First observed and root-caused on the krill-oss copy of the same workflow (Sautner-Studio-LLC/krill-oss#262 / #263); this repo’s .github/workflows/Verify Agent Ghost.yml had byte-identical content and the same bug.

Root cause

/srv/krill/data is created 0750 krill:krill by server/package/DEBIAN/postinst (install -d -o krill -g krill -m 0750 /srv/krill/data), and postinst’s adduser calls only ever add the krill system user itself to supplementary groups — the ghost runner’s own user is never added to the krill group. The wipe step’s sudo -n rm -f /srv/krill/data/*.db expands that glob in the calling, unprivileged shell before sudo ever runs (sudo only elevates the exec’d command, not the shell that built its argv). Against a directory the caller can’t read, the glob silently matches nothing, rm -f receives the literal nonexistent filename *.db, and -f suppresses the resulting error. The step logged success and deleted nothing — old DB state survived an ostensibly “fresh” restart.

Fix

Prevention