4.1.0 — Apple Silicon first: the M2 Max restore, one restore pipeline, a test bed that needs no spare drive
4.1.0 — Apple Silicon first: the M2 Max restore, one restore pipeline, a test bed that needs no spare drive
Found on the M2 Max, fixed
- Fedora Asahi Remix: shim on the removable path had no GRUB beside it.
restore-rebuild-boot.shtook os-release'sIDfor the ESP's vendor
directory. Asahi hasID=fedora-asahi-remixand ships its loaders in
EFI/fedora, so the Fedora-shim branch was never taken,grub2-install
was tried (and refused, on an EFI Secure Boot build), andEFI/BOOT/BOOTAA64.EFI
(shim) was left with nogrubaa64.efito load: the restored system stopped
atFailed to open \EFI\BOOT\grubaa64.efi. Caught by the test bed's VM boot
before any reboot. The rebuild now finds the directory that actually holds
this arch's shim or GRUB (ID, eachID_LIKEtoken, then whichever
directory has a shim, then one with a GRUB image; neverEFI/BOOT), and
testbed.sh finishchecks the removable path's shim has its GRUB beside it
before it lets anyone boot. Seven x86 bare-metal restores had passed without
exercising this. - The VM boot on aarch64 had no display:
-vga stdis not an option of
thevirtmachine. It gets avirtio-gpu-pcithere.
The restore test bed without a spare drive
TB_TARGET_IMAGE=<file>— a sparse disk image on the backup drive (no
CoW, never on one of this machine's own disks), attached as a loop device
and used exactly like a test drive: partitioned like the host, LUKS with the
host's KDF, restored, fingerprinted, booted in a VM. A file is nothing the
firmware can boot, so its verdict isPASS-VMfromtestbed.sh collect --vm: proof of the restore, not of the Bare-metal restore column, which
stays⚠️ until a drive has really booted.TB_TARGET_ESP=<PARTUUID>— the same-disk mode for machines whose
firmware boots nothing external (Apple Silicon): a spare ESP on the running
disk plus the free space after it — on a Mac, the ESP of a second "UEFI
environment only" Asahi install. The test bed adds its partitions there
(explicit numbers and sectors, onesgdiskcall each, the free region
re-verified at write time,partx -abecause a disk in use cannot re-read
its table, never a zap), keeps the ESP and its stub files (onlyEFI/is
cleared), and the restored system is picked at power-on. The boot logger
then goes by partition PARTUUID, not disk serial; U-Boot'subootefi.var
(this machine's boot order, restored onto the spare ESP) is parked so the
stub boots its own ESP; the restored boot chain is checked to name test
partitions only; the VM boot gets a read-only device-mapper disk made of the
test partitions alone under a GPT with their real PARTUUIDs and the disk's
sector size;TB_DELETE_TARGET=1 testbed.sh revertremoves the partitions
(never the ESP). Written and unit-tested; not yet run on metal — it needs
the second stub installed from macOS.TB_BACKUP_MOUNT=<mount>— the test archive goes to another mounted
drive (another machine's production backup drive plugged in for the test);
the suite's wrong-drive guard is told that drive's UUID for the test only.- 4096-byte-sector targets: the VM's virtual disk now carries the
target's logical sector size (Apple NVMe is 4Kn; at 512 the GPT is read at
the wrong offsets). - The USB transfer-size workaround (
TB_SECTORS_KB) applies to USB drives
only — no longer to NVMe, SATA or loop devices.
One restore pipeline: lib-restore.sh
borg-restore.sh and backintime-restore.sh carried 1,100 identical lines
each, and they had drifted: Back In Time's copy lacked the volume-group name
bridge, the tolerance for an ESP GRUB stub with no grub.cfg, and the check
that a Debian initramfs carries the root container's crypttab entry. The shared
pipeline — target checks, the new disk's ids, fstab / crypttab / command-line
rewrite, swapfiles and the SELinux relabel, the chroot boot rebuild, the
verification — is now lib-restore.sh, eleven stages both front ends run in
order. The front ends keep what differs: archive or snapshot selection and
the extraction. Installed to /usr/local/sbin and copied to the backup
drive's recovery-scripts/ with the rest. Proven by the M2 Max restore, which
ran the refactored pipeline.
The README, split
The README is 200 lines: what it is, the quick start, Apple Silicon, the
status summary, restore, the documentation table. Everything else moved
verbatim into docs/: STATUS.md (the tested / untested tables, the test
bed, what is not yet universal), INSTALL.md (deploy, drive set-up and
sizing, dependencies, scheduling, retention, the tray, every file),
RESTORE.md, TROUBLESHOOTING.md (logs, the report, USB bridge drops,
hand-rolling a fix), LAYERS.md, FAQ.md. Every cross-reference in
CONTRIBUTING, SECURITY, the issue templates and the scripts' own hints was
repointed. deploy.sh copies RESTORE.md and TROUBLESHOOTING.md to the
backup drive's recovery-scripts/ too.
The report a new setup is added from
backup-diag.sh opens with a setup fingerprint: one screen of the facts
every decision is made from, gathered without assuming any of them —
ID/ID_LIKE, which package managers exist (apt, dnf, zypper, pacman, apk,
xbps, emerge, slackpkg, nix, eopkg, rpm-ostree, …), the root filesystem and
the whole device stack under it, every real filesystem mounted (the fixed
type list that filtered an unknown root filesystem out of its own report is
gone), what the kernel supports, page and sector sizes, encryption and
volume management, the ESP's vendor directories and U-Boot's variable file
where there is one, every loader config found, the initramfs tools, what
could take snapshots — then the mkfs/fsck/tooling each filesystem has. That
section plus What the suite's own detection reports is what a distro,
filesystem or boot layout the suite has never met is added from, with nothing
else needed from the machine. "Universal" is the goal; this is how a report
from a setup nobody here owns turns into a fix.
Apple Silicon, said plainly
The FAQ now says what "run the Asahi installer from macOS" depends on — Apple
still serving the stub macOS image for that model — and what to protect on a
Mac that will outlive its macOS support: never delete the stub container,
keep macOS bootable (the installer runs from it and finishes in
recoveryOS), count on a restore over the existing
boot chain, and consider a second stub while Apple still serves the image.