Creating a Minimal Headless Raspberry Pi on Linux

Featured image

When setting up a Raspberry Pi (RPi), the Raspberry Pi Foundation features excellent authoritative documentation. But with its depth, you can easily catch yourself searching for particular information for some time. To streamline the process this document serves as a quick reference for setting up a headless RPi on Linux systems. Most tools used are already available in most linux distros.


Get the OS

For full compatability of hardware and operating system choose an official Raspberry Pi OS image on the offical site. The headless image is available under https://www.raspberrypi.com/software/operating-systems/ as Raspberry Pi OS Lite. If possible use the 64-bit version.

To verify the image from the website has reached your system correctly check the SHA256 hash of the file and compare it with the hash given on the website. This can be accomplished with the tool sha256sum (man sha256sum). The following oneliner can check whether a given hash and a given file, whose hash will be calculated in the process, match up.

Command:

echo "hash *fileToHash" | sha256sum -c -

Example:

$ echo "35f1d2f4105e01f4ca888ab4ced6912411e82a2539c53c9e4e6b795f25275a1f *2022-04-04-raspios-bullseye-arm64-lite.img.xz" | sha256sum -c -
2022-04-04-raspios-bullseye-arm64-lite.img.xz: OK

(!) Warning: Everyone is able to calculate a valid hash. This process does not guarantee that the image on the website is from the original creator as anyone can in theory hack the server hosting the website, replace the image with a malicious one, recompute the hash and place it on the website aswell. For a protection against attacks like this the image creator would need to verify the image with public key cryptography. A commonly used tool would be gpg. With public key cryptography only the original creator can create an authentic hash, called a certificate. Apparently the Raspberry Pi Foundation does not offer such protection.


Find the Correct Drive

Knowing the size of your SD-Card, its easy to find it with lsblk (man lsblk):

$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
...
sdX      8:_    0  14.8G  0 disk

Alternatively find it in the output of dmesg after having plugged the drive in. In my case the drive was named sdd.

$ sudo dmesg
...
[18417.043223] sdd: detected capacity change from 0 to 30818304
[18417.044845]  sdd: sdd1 sdd2

Delete Exisiting Partitions

(!) Warning: Choosing the wrong harddrive wipes it clean. Double check the commands you run.

If your SD-Card had a previous image and previous partitions then remove them with the partitioning tool of your choice, e.g. with parted:

$ sudo parted /dev/sdX
(parted) p
...Lists the partitions and their numbers
(parted) rm 1
(parted) rm 2
(parted) rm ...
(parted) quit

Unkompress and Write the Downloaded OS Image

Images can uncompressed with unxz and written to a drive using dd:

$ IMAGE=/path/to/image
$ DRIVE=/dev/sdX
$ unxz -c ${IMAGE} | sudo dd of=${DRIVE} bs=4M conv=fsync status=progress

The -c flag writes the uncompressed file to stdout, which gets piped directly into dd. With this method you never have to save an uncompressed image on your harddrive as you are passing it directly to the image writing software through standard output.

Access the Boot Partition

To be able to create and edit files in the boot partition, mount it. The boot partition is usually the first created partition, simply replace the X in the following mount command with the letter on your system:

$ mount /dev/sdX1 /mnt

Enable sshd

To have the ssh server daemon started on the RPi on its first boot, simply create an empty file named ‘ssh’ in the boot partition:

$ cd /path/to/mounted/boot/partition
$ touch ssh

Create a User

Create the file userconf.txt in the boot partition. Add a single line of text in the form of username:hashed_password.

A hashed representation of your password can be generated with openssl:

openssl passwd -6

Disable Bluetooth

Add:

dtoverlay=disable-bt

in the boot partitions config file: /boot/config.txt

After boot remove all bluetooth packages:

$ dpkg -l | grep -i bluetooth
ii  bluez             5.55-3.1+rpt1      arm64        Bluetooth tools and daemons
ii  bluez-firmware    1.2-4+rpt8         all          Firmware for Bluetooth devices
ii  pi-bluetooth      0.1.18             all          Raspberry Pi 3 bluetooth

https://forums.raspberrypi.com/viewtopic.php?t=280177#p1697081


Static IP Address

A clever way to manage static IP addresses centrally is in the settings of your DHCP server. DHCP servers allow you to assign static IP addresses to predefined MAC addresses.

The MAC address of the RPi’s Network Interface Card can be learned by booting it once and observe the machine appearing on your router’s web interface, or by listening on the wire with packet capture tools like wireshark for DHCP Requests. The OUI part of the MAC address gives it away as a Raspberry Pi (https://en.wikipedia.org/wiki/MAC_address).


Wireless Ethernet

If you want to use wireless ethernet, you can make the RPi join your wireless network at its first boot.

To do this, create the file wpa_supplicant.conf on the boot partition and fill it with:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
country=<Insert 2 letter ISO 3166-1 country code here>
update_config=1

network={
 ssid="<Name of your wireless LAN>"
 psk="<Password for your wireless LAN>"
}

Boot It

Unmount the boot partition from your filesystem:

$ sudo umount /dev/sdX1

Insert the SD-Card and boot the RPi.

Verify you can connect with SSH using your set user and password:

Do your final configuration in the context menu of sudo raspi-config, like changing your hostname.


References