Skip to content

feat(install): Tier-1 clean Tier-2 fall-through incl. no-systemd (#1222) - #485

Merged
aptracebloc merged 8 commits into
developfrom
feat/lpi-tier1-fallback
Jul 30, 2026
Merged

feat(install): Tier-1 clean Tier-2 fall-through incl. no-systemd (#1222)#485
aptracebloc merged 8 commits into
developfrom
feat/lpi-tier1-fallback

Conversation

@aptracebloc

@aptraceblocaptracebloc commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Slice #1222 — Tier 1: clean Tier-2 fall-through (no-systemd → prepare-host)

The last slice of #1177 (RFC 0001 least-privilege install) · Epic #1168. All behind the opt-in TB_TIER1_ROOTLESS flag — with it unset, behavior is unchanged.

Scope change (see the thread history)

This PR originally also added a no-systemd nohup fallback. That path drew six consecutive Bugbot rounds (async daemon start under set -e, curl|bash stdin inheritance, shared-home ~/.bashrcXDG_RUNTIME_DIR/DOCKER_HOST semantics) and can't be validated without a real HPC-style host. It's been descoped and deferred to tracebloc/backend#1354; this PR now ships the solid, testable parts.

What's in

  • Clean Tier-2 fall-through — a mid-flight rootless failure (setuptool/installer error, daemon never Ready) routes via _tier2_fallthrough to the Tier-2 prepare-host remedy instead of a bare set -e abort or proceeding on a broken socket. No false "Tier 1 succeeded."
  • No per-user systemd → Tier-2 — on a host where systemctl --user has no manager (hardened/HPC nodes), route to the prepare-host remedy rather than a blind bring-up. Honest + testable.
  • probe.sh tier classification is unchanged (a userns-disabled / cgroup-v1 host already classifies as Tier 2).

Descoped → #1354 (needs a real HPC host to validate)

  • The nohup dockerd-rootless.sh daemon bring-up + readiness poll on no-systemd hosts.
  • The $HOME-fallback XDG_RUNTIME_DIR + shell-rc persistence for that path.
  • The fuse-overlayfs perf measurement + flipping TB_TIER1_ROOTLESS default-on remain host-gated (spike §5), as before.

Testing

  • New/kept bats: no-systemd → Tier-2 fall-through; setuptool-failure → Tier-2; daemon-never-Ready → Tier-2. Verified on Linux + non-root: shellcheck --severity=error clean, full setup-linux + summary suites green (137 ok / 0 not ok). scripts/manifest.sha256 regenerated (R8).

After this lands, only #1179 (Windows/WSL2) remains in epic #1168, plus the deferred #1354.

🤖 Generated with Claude Code


Note

Medium Risk
Changes core Tier-1 rootless install branching and exit behavior behind TB_TIER1_ROOTLESS; mis-detection of user-systemd could wrongly push capable hosts to prepare-host, but failures are explicit rather than silent half-installs.

Overview
Tier-1 rootless install gains explicit failure routing to the Tier-2 prepare-host path (RFC #1222). The deferred no-systemd nohup bring-up is not in this slice.

New helpers _user_systemd_available and _tier2_fallthrough detect whether systemctl --user can run the daemon and, on failure, exit with TB_PREPARE_USER / tracebloc prepare-host <user> hints so admins actually provision the researcher.

install_rootless_docker checks user-systemd before any setuptool/install work (avoids partial ~/bin installs on HPC-style hosts). Setuptool/installer and docker info failures call _tier2_fallthrough instead of a bare set -e stop or continuing on a dead socket.

_persist_docker_host comments note persistence assumes the systemd XDG_RUNTIME_DIR socket path (no-systemd $HOME persistence deferred). Bats cover no-systemd, daemon-not-ready, setuptool failure, and researcher naming; scripts/manifest.sha256 updated.

Reviewed by Cursor Bugbot for commit 56b93be. Bugbot is set up for automated code reviews on this repo. Configure here.

@aptraceblocaptracebloc self-assigned this Jul 30, 2026
Comment threadscripts/lib/setup-linux.sh Outdated
aptracebloc added a commit that referenced this pull request Jul 30, 2026
…e dir (no-systemd path)
On the nohup fallback, /run/user/<uid> may be unwritable so the socket lands under
$HOME/.tracebloc-rootless-run. Before, the persisted DOCKER_HOST used the generic
${XDG_RUNTIME_DIR:-/run/user/$(id -u)} template (→ wrong socket in a fresh no-systemd
shell) and the restart guidance omitted XDG_RUNTIME_DIR (dockerd-rootless.sh refuses
without it), so the operator couldn't bring the daemon back. Now:
- _start_rootless_nohup records TB_ROOTLESS_RUNTIME_DIR and shows the full
'XDG_RUNTIME_DIR=<dir> nohup dockerd-rootless.sh &' restart command.
- _persist_docker_host persists 'export XDG_RUNTIME_DIR=<dir>' before DOCKER_HOST, so a
new shell resolves the SAME socket the install used AND can restart the daemon.
- summary.sh::_reboot_note carries the exact dir in the restart hint.
- Tests: rc sourced with XDG unset resolves DOCKER_HOST to the $HOME socket; the runtime
dir is recorded; the reboot-note hint carries the dir. manifest regenerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
aptraceblocand others added 2 commits July 30, 2026 10:22
Last slice of #1177 (LPI Tier 1) — the code hardening that completes the rootless
path. Everything stays behind the opt-in TB_TIER1_ROOTLESS flag; the §5 host-matrix
validation (fuse-overlayfs perf) and the flag flip to default-on are host-gated and
NOT in this PR (deferred, tracked on #1222).
- _user_systemd_available: detect a usable per-user systemd manager via
`systemctl --user is-system-running` (a state word => present, even on non-zero
exit; empty => no manager/bus) plus XDG_RUNTIME_DIR.
- _start_rootless_nohup: on hardened/HPC nodes with no user-systemd, start
dockerd-rootless.sh via nohup under an owned XDG_RUNTIME_DIR, poll the socket to
Ready, skip linger. Still user-space, no root. Sets TB_ROOTLESS_NO_LINGER.
- install_rootless_docker branches systemd-vs-nohup; the daemon-verify failure now
routes via _tier2_fallthrough (prepare-host remedy) instead of a bare error — no
proceeding on a broken socket, no false Tier-1.
- summary.sh::_reboot_note: honest "will NOT restart automatically" note on the
no-linger path (takes precedence over the autostart flag).
Tests: no-systemd nohup branch; daemon-never-Ready -> Tier-2 fall-through; the 5
existing install_rootless_docker tests updated to model is-system-running; the
reboot-note no-linger case. shellcheck clean; full bats suite green; manifest regen.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e dir (no-systemd path)
On the nohup fallback, /run/user/<uid> may be unwritable so the socket lands under
$HOME/.tracebloc-rootless-run. Before, the persisted DOCKER_HOST used the generic
${XDG_RUNTIME_DIR:-/run/user/$(id -u)} template (→ wrong socket in a fresh no-systemd
shell) and the restart guidance omitted XDG_RUNTIME_DIR (dockerd-rootless.sh refuses
without it), so the operator couldn't bring the daemon back. Now:
- _start_rootless_nohup records TB_ROOTLESS_RUNTIME_DIR and shows the full
'XDG_RUNTIME_DIR=<dir> nohup dockerd-rootless.sh &' restart command.
- _persist_docker_host persists 'export XDG_RUNTIME_DIR=<dir>' before DOCKER_HOST, so a
new shell resolves the SAME socket the install used AND can restart the daemon.
- summary.sh::_reboot_note carries the exact dir in the restart hint.
- Tests: rc sourced with XDG unset resolves DOCKER_HOST to the $HOME socket; the runtime
dir is recorded; the reboot-note hint carries the dir. manifest regenerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@aptracebloc
aptraceblocforce-pushed the feat/lpi-tier1-fallback branch from 62d13fc to ab2f03eCompareJuly 30, 2026 08:27
Comment threadscripts/lib/setup-linux.sh Outdated
Comment threadscripts/lib/setup-linux.sh
…tool Tier-2 fall-through
- _start_rootless_nohup: only claim "Started rootless Docker…" once the poll confirms the
daemon answered (_up). A bare "Started…" before a failed poll contradicted the shared
verify's "daemon never answered" fall-through moments later (Bugbot medium).
- install_rootless_docker: guard both install paths (dockerd-rootless-setuptool.sh /
get.docker.com/rootless) with '|| _tier2_fallthrough', so a setuptool/installer failure
routes to the prepare-host remedy instead of a bare set -e abort with the spinner log
tail — _tier2_fallthrough's documented setuptool coverage was not actually wired (Bugbot medium).
- Tests: nohup daemon-never-answers => no false "Started" + Tier-2; setuptool install failure
=> Tier-2 fall-through naming the setuptool. manifest regenerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment threadscripts/lib/setup-linux.sh Outdated
…NTIME_DIR
The r1 persist wrote 'export XDG_RUNTIME_DIR=<dir>' unconditionally into the shell rc.
~/.bashrc is sourced on every host sharing the home (HPC NFS), so that clobbered a
legitimate pam/systemd /run/user/<uid> on a systemd node and broke user-systemd there —
a regression from the r1 fix. Guard it: 'export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-<dir>}"',
supplying our dir only when the session hasn't set one. The test now also asserts a
pre-set XDG is preserved (not clobbered) alongside the no-systemd resolve case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment threadscripts/lib/setup-linux.sh Outdated
Comment threadscripts/lib/setup-linux.sh Outdated
…temd persist/launch path
- _launch_dockerd_rootless: add </dev/null so the backgrounded daemon can't inherit the
installer's `curl | bash` pipe stdin and consume the rest of the script (Bugbot High).
- _persist_docker_host: rewrite as an atomic BEGIN/END managed block, stripped + re-appended
each run. The prior per-line append landed a re-run's XDG line AFTER DOCKER_HOST, so it
never took effect (Bugbot medium). The runtime dir is now baked into the DOCKER_HOST
fallback (order-independent resolution); the guarded ${XDG_RUNTIME_DIR:-…} line supplies
it for the daemon restart without clobbering a systemd node's /run/user/<uid>.
- Self-review hardening: same-dir temp + `cat` (not `mv`) so a symlinked/stow'd rc + perms
survive and a full disk bails before touching the rc; strip only a WELL-FORMED block (both
markers) so a malformed rc isn't eaten past a missing END marker.
- Tests: systemd→nohup transition; </dev/null guard; unrelated-content/malformed-block safety.
full setup-linux + summary suites green; shellcheck clean; manifest regenerated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment threadscripts/lib/setup-linux.sh Outdated
…> Tier-2 (#1354)
Six consecutive Bugbot rounds landed on the no-systemd nohup fallback (async daemon +
set -e + curl|bash stdin + shared-home rc persistence), none validatable without a real
HPC host. Descope it: a host with no per-user systemd now routes to the Tier-2 prepare-host
remedy (honest + testable) instead of a blind nohup bring-up.
- Delete _start_rootless_nohup + _launch_dockerd_rootless; install_rootless_docker's
no-systemd branch now calls _tier2_fallthrough.
- Revert _persist_docker_host to the simple systemd-path form (pam sets XDG_RUNTIME_DIR;
no $HOME-fallback / atomic-block / XDG-persist complexity).
- Drop the now-dead TB_ROOTLESS_NO_LINGER branch in summary.sh::_reboot_note.
- Tests: no-systemd => Tier-2 fall-through; removed the nohup / persist-XDG / launch tests.
full setup-linux + summary suites green; shellcheck clean; manifest regenerated.
The nohup fallback is tracked for a host-available slice in #1354.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@aptraceblocaptracebloc changed the title feat(install): Tier-1 no-systemd fallback + Tier-2 fall-through (#1222)feat(install): Tier-1 clean Tier-2 fall-through incl. no-systemd (#1222)Jul 30, 2026
Comment threadscripts/lib/setup-linux.sh Outdated
install_rootless_docker checked _user_systemd_available only AFTER the setuptool install
+ the user proxy drop-in. The setuptool sets up a `systemctl --user` unit and fails first
on a no-systemd host, so the operator got a vague setuptool reason plus a partial ~/bin
install + drop-ins before the Tier-2 remedy. Move the gate to the TOP -> fail fast to
_tier2_fallthrough with the accurate "no per-user systemd" reason and no artifacts. The
later systemd branch is now unconditional (the redundant re-check is removed). Test now
also asserts the setuptool never runs on the no-systemd path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 19633e8. Configure here.

Comment threadscripts/lib/setup-linux.sh
…t remedy (Bugbot #485)
_tier2_fallthrough printed a bare `prepare-host` hint with no TB_PREPARE_USER / username.
run_prepare_host only grants docker-group access + provisions subuid ranges when the user
is named, so an admin who followed the bare hint prepared the host but NOT the researcher —
looping them back into the same fall-through. Name the researcher (id -un), matching
_ensure_subid_ranges' hand-off verbatim (export TB_PREPARE_USER=<user>, `prepare-host <user>`).
Test asserts the remedy names them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@aptracebloc
aptracebloc merged commit e201ad0 into developJul 30, 2026
59 of 60 checks passed
@cursorcursorBot mentioned this pull request Jul 30, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@aptracebloc@saadqbal@LukasWodka@divyasinghds