Raspberry Pi Headless Setup

1. Headless setup

This guide is outdated and Raspbian 12 Bookworm setups won't work. I will write a new guide soon.

The Backup and QEMU sections below should still work (I hope).


I've done this a couple of times already so I thought I should write it down.

How to setup the Raspberry Pi with Pi OS for ssh and wifi.

1.1. Flash

Flash the OS to the sd card. My favorite tool for this is Balana Etcher.

I like to use xzcat in combination with dd:

xzcat 2024-03-15-raspios-bookworm-armhf-lite.img.xz | sudo dd of=/dev/mmcbzz0 bs=1M oflag=sync status=progress

1.2. Mount

After the flash is complete, mount the sd card to apply modifications. I will use /tmp/sdcard/ as mounting point in this example.

1.3. SSH

cd /tmp/sdcard/boot/
touch ssh

1.4. WiFi

Create this file:

country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="your_real_wifi_ssid"
    psk="your_real_password"
    key_mgmt=WPA-PSK
}

1.5. Hostname

Edit /tmp/sdcard/rootfs/etc/hostname to change the hostname.

1.6. After first boot

Change your password (run this on the pi):

passwd

Add your ssh key (run this on your local machine, replace the hostname):

ssh-copy-id pi@raspberrypi

2. Backup and editing

2.1. Create a full backup of the SD card

sudo dd if=/dev/sdb of=./raspberrypi.raw.img bs=1M status=progress

2.2. Make the backup file immutable, if needed

sudo chattr +i raspberrypi.raw.img
lsattr raspberrypi.raw.img

2.3. Create devices for mounting partitions from the backup file

sudo kpartx -arv raspberrypi.raw.img

(-a: Add partition mappings, -r: Read-only partition mappings, -v: Operate verbosely)

You can now mount the partitions, read files, do changes if needed, and unmount them again.

Afterwords, delete the devices:

sudo kpartx -dv retropie.raw.img

(-d: Delete partition mappings)

3. QEMU testing

Taken from plembo and qemu-rpi-kernel.

3.1. Mount and edit ld.so.preload

Mount the .img file via kpartx to modify it, see above.

sudo nano /mnt/etc/ld.so.preload
# Comment out the only line

3.2. Unmount and convert (optional)

qemu-img convert -f raw -O qcow2 raspberrypi.raw.img raspberrypi.qcow2

3.3. Download kernel and run

wget https://github.com/dhruvvyas90/qemu-rpi-kernel/blob/9fb4fcf463df4341dbb7396df127374214b90841/kernel-qemu-4.14.79-stretch?raw=true
wget https://github.com/dhruvvyas90/qemu-rpi-kernel/blob/9fb4fcf463df4341dbb7396df127374214b90841/versatile-pb.dtb?raw=true
sudo qemu-system-arm -kernel kernel-qemu-4.14.79-stretch \
              -cpu arm1176 -m 256 \
              -M versatilepb -dtb versatile-pb.dtb \
              -no-reboot \
              -serial stdio \
              -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" \
              -hda raspberrypi.qcow2 \
              -net nic -net user \
              -net tap,ifname=vnet0,script=no,downscript=no

If you want to use a raw image instead of qcow2, you can pass -drive format=raw,file=raspberrypi.raw.img instead of the -hda option.

3.4. Convert QEMU image back to raw

qemu-img dd -f qcow2 -O raw bs=4M if=raspberrypi.qcow2 of=back-to.raw.img