๐ฉธ Gotchas โ
Save yourself the hours.
#1 โ bootcode.bin at FAT root, NOT in a subdir โ
Trap: Mirroring the Linux /boot/firmware/ convention onto the FAT partition. Your rootfs has /boot/firmware/bootcode.bin โ fine. The SD's FAT partition is NOT a Linux filesystem. The mask-ROM looks at the partition root.
Wrong:
/Volumes/BOOT/boot/bootcode.bin โ
/Volumes/BOOT/boot/start4.elf โRight:
/Volumes/BOOT/bootcode.bin โ
/Volumes/BOOT/start4.elf โ
/Volumes/BOOT/overlays/ โโ S01E13
#2 โ debootstrap --variant=minbase strips systemd โ
Trap: minbase is more aggressive than you think. It removes all Priority: important packages. systemd is one of them.
Fix: Add to --include:
systemd-sysv, dbus, openssh-server, wpasupplicant, wireless-tools,
ifupdown, isc-dhcp-client, rfkill, net-tools, kmod, parted, e2fsprogs#3 โ /etc/fstab defaults to "UNCONFIGURED" โ
Trap: debootstrap's default fstab is the comment # UNCONFIGURED FSTAB FOR BASE SYSTEM. Nothing mounts. Anything that depends on /boot/firmware/ (or /boot/) silently fails.
Fix: Write one explicitly:
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot/firmware vfat defaults,flush,nofail 0 0
/dev/mmcblk0p2 / ext4 defaults,noatime,errors=remount-ro 0 1#4 โ Mount FAT at /boot/firmware/, NOT /boot/ โ
Trap: Older Raspbian conventions mounted at /boot/. Bookworm switched to /boot/firmware/. The raspi-firmware apt package and kernel postinst hooks assume the new path. Using /boot/ breaks apt upgrades.
Right: /dev/mmcblk0p1 /boot/firmware vfat ...
#5 โ rfkill is soft-blocked at boot โ
Trap: The Pi kernel boots with wifi rfkill soft-blocked (regulatory safeguard). Setting country=PT in wpa_supplicant.conf does NOT auto-unblock. Pi OS unblocks via raspi-config do_wifi_country. minbase has no raspi-config.
Symptom: wpa_supplicant: rfkill: WLAN soft blocked, dhclient: send_packet: Network is down. Wifi looks like it should work but can't transmit.
Fix: A oneshot systemd unit:
# /etc/systemd/system/nosferato-rfkill.service
[Unit]
Description=Unblock wifi rfkill at boot
DefaultDependencies=no
Before=network-pre.target wpa_supplicant.service ifupdown-pre.service
After=local-fs.target
Wants=network-pre.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/rfkill unblock all
RemainAfterExit=yes
[Install]
WantedBy=sysinit.targetThen systemctl enable nosferato-rfkill.service.
#6 โ Wrong firmware filename for the chip โ
Trap: The Pi Zero 2 W's wifi chip has FOUR naming conventions:
BCM43436(Pi Foundation marketing)BCM43430(brcmfmac driver, silicon family)CYW43436s(Cypress,s= rev 1.0)cyfmac43430(Debian'sfirmware-brcm80211filename)
If you fetch the wrong name from a random GitHub URL, the driver loads it but the chip rejects โ HT Avail timeout.
Fix: Don't hand-pick. apt install firmware-brcm80211 from Pi Foundation's apt repo. apt resolves the rev-specific blob.
#7 โ journalctl -b -1 vs -b 0 โ
Trap: -b -1 means "the boot BEFORE the current one." If you capture the SD post-shutdown and run journalctl -D $JD -b -1, there's no "previous" boot โ the SD contains the LAST boot, accessible via -b 0.
Right: journalctl -D /path/to/var/log/journal -b 0 for "the boot that happened on this SD before shutdown."
#8 โ macOS reassigns /dev/diskN ordinal on each attach โ
Trap: Hardcoding /dev/disk5 in your build script. macOS reassigns based on attach order. Your SD might be disk4 today, disk6 tomorrow.
Fix: Parameterize the device path (env var or CLI arg). Auto-detect via partition label whitelist.
# safety-check that the target disk has one of YOUR labels
KNOWN_LABELS=(BOOT ROOT PI nosferato)#9 โ diskutil eject can be blocked by Spotlight indexing โ
Trap: After cp -R onto the BOOT partition, diskutil eject can fail with "dissented by PID NNNN (mdsync)". Spotlight is indexing your freshly-written FAT.
Symptom: "Unmount of disk6 failed: at least one volume could not be unmounted"
Fix: It's cosmetic โ the data is already synced (we ran sync before eject). Just diskutil eject -force or pull the SD card.
#10 โ Multipass VM clock drift breaks apt โ
Trap: Multipass VMs that suspend/resume across days have hours of wall-clock drift. apt refuses Release files dated "in the future" relative to the VM clock.
Symptom: E: Release file for ... is not valid yet (invalid for another 3h 17min 18s).
Fix: Pre-sync the VM clock inside build-rootfs.sh:
systemctl restart systemd-timesyncd
timedatectl set-ntp true
# wait a few sec for convergence
for i in 1 2 3 4 5; do
timedatectl status | grep -q 'System clock synchronized: yes' && break
sleep 1
donePlus belt-and-suspenders apt flag: apt-get -o Acquire::Check-Valid-Until=false update.
#11 โ iPhone hotspot proxy-ARPs the whole subnet โ
Trap: ping -c 1 172.20.10.X returns "alive" for ALL 13 IPs in an iPhone hotspot, because the iPhone responds to ARP for all of them with its own MAC.
Symptom: Looks like every IP is alive. Can't tell which one is the Pi.
Fix: TCP-scan port 22 instead:
for i in $(seq 2 14); do
nc -z -w 2 172.20.10.$i 22 2>&1 | grep succeeded && echo "ssh on .$i"
doneOr check the iPhone's hotspot UI under Settings โ Personal Hotspot for the connected device list.
#12 โ Pi Zero 2 W has ONE LED, not two โ
Trap: Some Pi models have two LEDs (red PWR + green ACT). The Pi Zero 2 W has only the green ACT LED. "No red light" doesn't mean "no power."
Fix: Use a USB power meter inline if you need to verify power. For boot status, look at the green LED's blink pattern: solid = panic, blinking = SD activity, off = idle.
#13 โ txcap_blob err=-2 is cosmetic โ
Trap: Looks alarming in dmesg. Easy to assume it's why brcmfmac isn't finishing init.
Reality: It's cosmetic. Per raspberrypi/linux#6317, the driver completes registration regardless.
Fix: Ignore it. Look elsewhere for the real bug.
#14 โ dtoverlay=dwc2 + gpu_mem=16 aren't wifi suspects โ
Trap: Modifying random config.txt parameters when wifi doesn't work, on the theory that "anything unfamiliar might be the problem."
Reality: dtoverlay=dwc2 only switches USB controller mode (host โ gadget). gpu_mem=16 is fine for headless (default is 76MB but Pi peripheral coprocessors don't actually run out of memory there). Neither affects wifi.
Fix: Don't change parameters you don't understand and can't justify. Document the suspect, dismiss it, move on.
โ The Recipe ยท Step-by-Step ยท Tools