From 13b49cf9ba821ea66849e3dfc2148d2d1d27a9b6 Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Sun, 6 Sep 2026 05:03:47 -0500 Subject: [PATCH] fix(os): #1931 the debug variant pins the test registry into /etc/environment too A pithead verb run by hand over SSH reads /etc/environment through PAM, never a unit's drop-in, so on the RC1 image `./pithead backup` restarted the stack from the org's registry (no 2.0.0 there) and left it down. The tar-append copies the rootfs's own /etc/environment out (it carries PITHEAD_ENGINE), appends the pin, and appends the file back as a leaf so mkimage's tar -xf lands it whole. verify-image --test asserts the pin beside the engine line; release mode refuses any PITHEAD_REGISTRY= line there. Measured: synthetic tar, both lines extracted; the new assertion on the RC1 image (built before this fix) fails exactly one row, 119/1 against the chain's 119/0. Positive control (an image built with the fix) waits for the bench. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01NeSaJPWy7AkhYcYpGVkxBJ --- docs/dev/appliance-release.md | 9 +++++---- os/build-image.sh | 8 ++++++++ tests/os/verify-image-variant.sh | 4 +++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/dev/appliance-release.md b/docs/dev/appliance-release.md index 3ea7f77f..5e06f364 100644 --- a/docs/dev/appliance-release.md +++ b/docs/dev/appliance-release.md @@ -174,10 +174,11 @@ Two build variants, chosen by one flag: over SSH. Verify with `tests/os/verify-image.sh IMAGE --test`. A bench that takes an A/B update to a *release* bundle loses SSH — deliberate, and worth remembering before pressing install. Built with `PITHEAD_REGISTRY` set to a non-default namespace, a debug image also - pins that registry into its boot units and tells podman how to trust it — the CA file named - by `PITHEAD_REGISTRY_CA` for a TLS registry, or an insecure entry without one — so a bench box - can provision from a registry on the LAN (#1892); the release variant never carries any of - those files, and `verify-image.sh` checks both ways. + pins that registry into its boot units and into `/etc/environment` (so a `pithead` verb run + by hand over SSH pulls from the same place, #1931) and tells podman how to trust it — the CA + file named by `PITHEAD_REGISTRY_CA` for a TLS registry, or an insecure entry without one — so + a bench box can provision from a registry on the LAN (#1892); the release variant never + carries any of that, and `verify-image.sh` checks both ways. The updater defaults to RAUC; an image built without it cannot take another update, and the only way to get one now is to set `PITHEAD_UPDATER` to something else on purpose. diff --git a/os/build-image.sh b/os/build-image.sh index 003350d4..39e975a2 100755 --- a/os/build-image.sh +++ b/os/build-image.sh @@ -159,6 +159,14 @@ if [ -n "$TEST_REGISTRY" ]; then printf '[Service]\nEnvironment=PITHEAD_REGISTRY=%s\n' "$TEST_REGISTRY" \ >"$stage/etc/systemd/system/$u.service.d/pithead-test-registry.conf" done + # An SSH shell running ./pithead by hand reads /etc/environment through PAM, never a unit's + # drop-in (#1931): the pin goes there too, appended to the file the rootfs already carries + # (PITHEAD_ENGINE, Dockerfile) so the later tar entry replaces it whole and loses nothing. + tar -xOf os/build/pithead-root.tar etc/environment >"$stage/etc/environment" || { + echo "build-image: the exported rootfs has no etc/environment to pin the registry into" >&2 + exit 1 + } + printf 'PITHEAD_REGISTRY=%s\n' "$TEST_REGISTRY" >>"$stage/etc/environment" # containers/image reads /etc/containers/certs.d//ca.crt for a TLS registry; the # insecure entry is the HTTP fallback. One or the other, never both. if [ -n "${PITHEAD_REGISTRY_CA:-}" ]; then diff --git a/tests/os/verify-image-variant.sh b/tests/os/verify-image-variant.sh index b8f6ea02..199ce97d 100644 --- a/tests/os/verify-image-variant.sh +++ b/tests/os/verify-image-variant.sh @@ -13,6 +13,8 @@ if [ "$MODE" = "--test" ]; then # #1892: built against a non-default registry, the boot units must carry it AND podman must trust it — one without the other is a first boot that cannot find its wizard image, or a provision that refuses the pull. if [ -n "${PITHEAD_REGISTRY:-}" ] && [ "$PITHEAD_REGISTRY" != ghcr.io/p2pool-starter-stack ]; then chk "all three boot units pinned to the test registry" '[ "$(grep -lxF "Environment=PITHEAD_REGISTRY=$PITHEAD_REGISTRY" "$ROOT"/etc/systemd/system/{pithead-boot,pithead-firstboot,pithead-setup-again}.service.d/pithead-test-registry.conf 2>/dev/null | wc -l)" = 3 ]' + # #1931: a PAM login (an SSH shell running ./pithead by hand) reads /etc/environment, not the drop-ins; the engine pin beside it proves the file was appended to, not replaced. + chk "/etc/environment pinned to the test registry, engine pin kept" 'grep -qxF "PITHEAD_REGISTRY=$PITHEAD_REGISTRY" "$ROOT/etc/environment" && grep -qxF "PITHEAD_ENGINE=podman" "$ROOT/etc/environment"' # The trust half is whichever the builder chose: the CA it was handed, byte for byte, or the insecure entry. if [ -n "${PITHEAD_REGISTRY_CA:-}" ]; then chk "podman trusts the test registry's CA, and no insecure entry" 'cmp -s "$PITHEAD_REGISTRY_CA" "$ROOT/etc/containers/certs.d/${PITHEAD_REGISTRY%%/*}/ca.crt" && [ ! -e "$ROOT/etc/containers/registries.conf.d/pithead-test-registry.conf" ]' @@ -23,7 +25,7 @@ if [ "$MODE" = "--test" ]; then else # The reason this script exists in versioned form: a leaked test key on a release image is a # backdoor, and ad-hoc eyeballing is how one ships. - chk "NO test marker, NO test registry pin or trust (#1892)" '[ ! -e "$ROOT/etc/pithead-test-marker" ] && [ ! -e "$ROOT/etc/containers/registries.conf.d/pithead-test-registry.conf" ] && [ ! -e "$ROOT/etc/containers/certs.d" ] && ! ls "$ROOT"/etc/systemd/system/*/pithead-test-registry.conf >/dev/null 2>&1' + chk "NO test marker, NO test registry pin or trust (#1892)" '[ ! -e "$ROOT/etc/pithead-test-marker" ] && [ ! -e "$ROOT/etc/containers/registries.conf.d/pithead-test-registry.conf" ] && [ ! -e "$ROOT/etc/containers/certs.d" ] && ! ls "$ROOT"/etc/systemd/system/*/pithead-test-registry.conf >/dev/null 2>&1 && ! grep -q "^PITHEAD_REGISTRY=" "$ROOT/etc/environment"' chk "NO SSH authorized_keys" '[ ! -s "$ROOT/root/.ssh/authorized_keys" ]' chk "ssh service disabled" '! ls "$ROOT"/etc/systemd/system/multi-user.target.wants/ssh.service' chk "variant stamp says release" '[ "$(cat "$ROOT/etc/pithead-variant")" = "release" ]'