Raspberry Pi Headless Setup

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. Flash

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

2. Mount

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

3. SSH

cd /tmp/sdcard/boot/
touch ssh

4. WiFi

Create this file:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev


5. Hostname

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

6. After first boot

Change your password (run this on the pi):


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

ssh-copy-id pi@raspberrypi

7. Backup and editing

7.1. Create a full backup of the SD card

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

7.2. Make the backup file immutable, if needed

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

7.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)

8. QEMU testing

Taken from plembo and qemu-rpi-kernel.

8.1. Mount and edit ld.so.preload

Mount via kpartx, see above.

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

8.2. Unmount and convert (optional)

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

8.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.

8.4. Convert QEMU image back to raw

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