๐ ๏ธ Tools โ
diagnose-sd.sh โ the SD inspector โ
Power down Pi โ pull SD โ plug into Mac โ run one command โ get a full report.
bash
bash infra/nosferato/bootstrap/diagnose-sd.shWhat it does:
- Auto-detects the SD card device (no
/dev/diskNguessing) ddcaptures the rootfs partition (3GB raw, ~30s)e2fsck -fyreplays the journal sodebugfsreads consistently- Static rootfs queries via
debugfs:- Does
/sbin/initexist? - Is
/lib/modules/<release>/present? - Are essential packages installed?
- What's in
/etc/fstab,/etc/network/interfaces,/etc/passwd? - Which systemd units are enabled in
multi-user.target.wants?
- Does
- Loopback-mounts inside Multipass VM and runs
journalctl -Dagainst the captured/var/log/journal/โ actual systemd logs from the failed boot - Tails
/var/log/syslog, dhcp leases, wpa_supplicant configs if present - Reads the BOOT FAT partition to confirm
wpa_supplicant.confetc. - Tees everything to
.build/diagnostic-<timestamp>.log+ adiagnostic-latest.logsymlink
Usage modes โ
bash
# Auto-detect + capture
bash diagnose-sd.sh
# Reuse last capture (skip the dd)
bash diagnose-sd.sh --no-capture
# Explicit device
bash diagnose-sd.sh /dev/disk6
# Help
bash diagnose-sd.sh --helpOutput format โ
Each section prefixed with โโ N. <title> headers. ANSI-colored if the terminal supports it. Plain in the log file (tee-stripped).
Critical sections to check:
5. Rootfs stateโ fs signature, init, modules, packages, fstab, interfaces, users, systemd wants6. Systemd journalโ-b 0for the boot just captured; ERRORS-only filtered separately7. BOOT (FAT) partition stateโ confirmswpa_supplicant.conf, marker file, config.txt
When to use โ
- ๐ Pi seems dead โ check section 5 (boot files present?)
- ๐ Pi blinks then stops โ check section 6 (kernel panic? init missing?)
- ๐ Pi boots but no wifi โ check section 6 errors (rfkill? brcmfmac probe?)
- ๐ Wifi up but no SSH โ check section 5 (ssh.service enabled? sshd config?)
Required environment โ
- macOS host (auto-detect uses
diskutil) - Multipass VM named
nosferato-builderrunning (or it'll start one) - The VM has
e2fsprogsinstalled (auto-installed during firstbuild.shrun)
Anti-patterns โ
- โ Don't tail the log file by hand โ it's tee'd to stdout already
- โ Don't pull SD before running (auto-detect needs it attached)
- โ Don't run while a build is mid-flight (will fail at the dd step or get inconsistent capture)
โ Source on GitHub
build.sh โ the SD card builder โ
Drives a Multipass VM to build the rootfs + boot files, then partitions and flashes the SD.
bash
# Full clean build (~30-45 min)
./infra/nosferato/bootstrap/build.sh /dev/disk6
# Reuse last build artifacts (skip debootstrap; ~3-5 min)
./infra/nosferato/bootstrap/build.sh --reuse-build /dev/disk6Key features:
- Positional CLI arg for device path (also
NOSFERATO_DEVICEenv var) - Sudo keepalive: refreshes sudo timestamp every 60s during the 30+ min run
- Safety check: refuses to run against disks lacking a recognized partition label (BOOT, ROOT, PI, nosferato)
--reuse-build: short-circuits VM debootstrap if cached artifacts exist- 9-step pipeline with colored progress
Internal pipeline โ
- Ensure Multipass VM running
- Mount shared dirs into VM
- Run
build-rootfs.shin VM (debootstrap, apt-install Pi packages, configure) - Generate boot config files (config.txt, cmdline.txt, wpa_supplicant.conf, marker)
- Partition the SD card (MBR, FAT32 BOOT 256MB + ROOT)
ddrootfs.img to ROOT partition (raw device, fast)- Note: resize2fs deferred to firstboot
- Mount BOOT, copy config files
- Eject
build-rootfs.sh โ
The Linux-side companion. Runs inside the Multipass VM. Does:
- VM clock sync (fixes apt date-skew)
- debootstrap with all
--includepackages - Pi Foundation apt repo + apt install of
linux-image-rpi-v8+raspi-firmware+firmware-brcm80211+raspberrypi-sys-mods - System identity (hostname, user, fstab, network/interfaces)
- rfkill-unblock service
- Persistent journal directory
- Boot.tgz packaged from
/boot/firmware/
โ The Recipe ยท Gotchas