fix(rpi-image): patch the host OS automatically, unfreeze the Docker engine - #1001
Conversation
…engine Self-update covers only FTW's own containers; the flashed Pi never received an OS security update, and the image build deleted Docker's apt source, so even a manual `apt upgrade` could not patch the engine. - install unattended-upgrades: Debian security + the Raspberry Pi archive (the kernel/firmware source has no security pocket), with automatic reboots pinned off — a reboot stops dispatch - park docker.list as docker.list.disabled during the image build (same export-image OOM workaround) and restore it in ftw-firstboot, so engine patching becomes a normal operator apt action - document the self-update/host boundary and a retrofit for devices flashed from older images Fixes srcfl#770 Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com> Claude-Session: https://claude.ai/code/session_012taMkhFbYYNyVQmCTU26sn
Master moved from srcfl#756 to srcfl#998 under the branch; the only real conflict was firstboot.sh, where srcfl#980-era work made first boot try `docker compose up -d` on locally present images before falling back to the GHCR pull loop. Kept that up-first flow and placed the docker.list restore (srcfl#770) before it, right after cd /opt/ftw. Co-authored-by: HuggeK <48095810+HuggeK@users.noreply.github.com> Claude-Session: https://claude.ai/code/session_012taMkhFbYYNyVQmCTU26sn
miravoss26
left a comment
There was a problem hiding this comment.
Adds unattended-upgrades to the Pi image: Debian security + Raspberry Pi Foundation origins auto-patch daily, automatic reboot stays off (this is a dispatch-critical appliance), and Docker's engine is deliberately excluded from the auto-upgrade pattern (restored via firstboot instead of staying frozen at build time).
- The
docker.list→docker.list.disabledrename (build time) / restore (firstboot.sh) is correctly gated with[ -f ... ]— idempotent across a re-run or a reboot mid-provision. Origins-Patternappends to Debian's defaults rather than replacing them; Docker's own repo is correctly left out, matching the "engine upgrade = manual, operator-timed" comment.- No secrets, no new inbound surface. The Raspberry Pi Foundation archive isn't a new apt source here, just named for auto-upgrade scope.
- Worth flagging, not a blocker: kernel/firmware patches land but sit inert until an operator reboots. That gap between "patched" and "running patched" is real for fleet-exposure auditing, even though the reasoning (reboot stops dispatch) is sound.
Safe to merge from my read.
frahlg
left a comment
There was a problem hiding this comment.
Fixes the two real holes in #770: the host never got Debian/Raspberry Pi security updates, and deleting docker.list froze the engine for the life of the flash.
The park-and-restore (docker.list → docker.list.disabled at build, restore in firstboot) is the right shape — apt only reads *.list/*.sources, so the pi-gen OOM workaround stays, and the [ -f ] gate is idempotent across a reboot mid-provision. Automatic reboot stays off, which is the load-bearing appliance constraint.
Origins: listing Debian-Security again in 52ftw-unattended-upgrades is the safe form whether APT merges or replaces the list from 50unattended-upgrades. Raspberry Pi archive belongs there (no separate security pocket). Docker stays out of unattended-upgrades on purpose.
Accepted trade-off, not a blocker: kernel/firmware land but sit inert until an operator reboots. Retrofit block is docs-only, which is correct — core never touches the host.
Not tested on hardware here; validate installer scaffolding is green. Fine to land.
Fixes #770.
Pressing Update in the app updates Core, the Optimizer and drivers — and nothing else. A flashed Pi never received a host OS security update, and because the image build deletes Docker's apt source after installing the engine, not even a manual
sudo apt upgradecould patchdocker-ce. This PR implements options 1–3 from #770:unattended-upgradeson the appliance image. Origins: Debian security plus the Raspberry Pi archive, applied daily;Automatic-Reboot "false"is pinned explicitly — a reboot stops dispatch, so a staged kernel waits for an operator-chosen reboot.docker.listasdocker.list.disabled(apt only reads*.list/*.sources, so the pi-genexport-imageOOM workaround is preserved) andftw-firstbootrestores it on the device. Engine patching becomes a normalapt upgrade.docs/self-update.md,docs/operations.mdanddocs/rpi-image.mdnow say plainly that self-update never touches the host, andrpi-image.mdcarries a retrofit block for devices flashed from older images.Why the Raspberry Pi archive is in the origins, but Docker is not
The Raspberry Pi archive (
Origin: Raspberry Pi Foundation) is wherelinux-image-rpi-v8,raspi-firmwareand the bootloader packages come from, and it has no separate security pocket. Restricting unattended-upgrades to Debian's security pocket alone would leave exactly the packages the issue worries about — the kernel — permanently unpatched. Kernel updates install but only take effect at the next operator reboot, so including the archive costs no unplanned downtime.Docker's repository is deliberately not auto-upgraded: a
docker-ceupgrade restarts the daemon and with it every container, which is a dispatch interruption that should happen at a moment the operator picks, not at the apt-daily timer's. Restoring the source makes that manual action possible at all; the fragment's comment records the decision.Verification
bash -npasses on both modified scripts (same check thevalidate installer scaffoldingjob runs).archive.raspberrypi.com/debian/dists/trixie/ReleasereportsOrigin: Raspberry Pi Foundation/Codename: trixie;download.docker.com/linux/debian/dists/trixie/ReleasereportsOrigin: Docker.apt.conf.dfiles, so52ftw-unattended-upgradesextends the Debian defaults in50unattended-upgradesinstead of replacing them.rpi-image-build.ymlwithout publishing to get a flashable candidate.Option 4 from the issue (surfacing host patch state in Update Center) is deliberately left out: it crosses the core-has-no-host-visibility boundary and deserves its own discussion. Existing installations get the documented retrofit, not an automatic migration — core never touches the host.
🤖 Generated with Claude Code
https://claude.ai/code/session_012taMkhFbYYNyVQmCTU26sn