Single-Board Computers: Headless Setup for Raspberry Pi, Orange Pi, Radax
I still like to set up my SPCs headless. This way, I don't need to connect a monitor and keyboard. I simply prepare the SD card on my laptop, plug it into the target and it connects to my network, allowing me to SSH into it.
Since my old post is outdated, here is an updated guide on how to set up an operating system for a single-board computer like a Raspberry Pi, Orange Pi or Radax.
In all cases, it is assumed you have flashed the image to a sd card, like this:
xzcat ./2024-07-04-raspios-bookworm-armhf-lite.img.xz | sudo dd of=/dev/mmcbzz0 bs=1M oflag=sync status=progress
and the card is mounted into /mnt/sdcard/
.
1. Raspberry Pi OS / Rasbian
You can of course use the official rpi-imager or sdm, which both are great programs.
I prefer to do the setup manually though to see what changes on the filesystem.
General hint: cat /sys/firmware/devicetree/base/model
shows you which model you have.
1.1. Version 11 (bullseye)
Tested with 2024-07-04-raspios-bullseye-armhf-lite.img.xz
.
1.1.1. SSH
touch /mnt/sdcard/bootfs/ssh
1.1.2. 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
}
Change your country, the SSID and the password (psk).
1.1.3. Hostname
Edit the hostname in these files:
sudo nano /mnt/sdcard/rootfs/etc/hostname
sudo nano /mnt/sdcard/rootfs/etc/hosts
1.1.4. User
myuser:$6$1TQy0EikzkV4Ukzy$ceXxUzbGmWPrPyJILfbtvm4j1crojHqd7UFSv0O3oXKM6QsyEandc5YLGJqDZsBeWKXcMI3KIpqTQ9Q3HWHG10
The password in this case is mypassword
.
Generate your own via this command:
echo 'mypassword' | openssl passwd -6 -stdin
1.2. Version 12 (bookworm)
1.2.1. WTF?
Things get a bit complicated here and on my first installation I reluctantly went to use the official Raspberry Pi Imager. :(
But now I finally found how to prepare the sd card without it by this great article, which reverse-engineered the Imager.
The imager sets up a firstrun.sh
script and modifies the cmdline.txt
to run it on first boot.
After that, the script deletes itself and removes itself also from cmdline.txt
again.
The key program used is raspberrypi-sys-mods.
What I stumbled across during my reasearch, but things that were not useful for Raspberry Pi OS:
- cloud-init? I guess it is only used by Ubuntu
- netplan? This one is used by Armbian actually, see below
custom.toml
Didn't work for me.
1.2.2. Set up a new installation
I have copied the original firstrun.sh
the imager created with my settings
and tried to generalize it, in order to only have a simple firstrun.env
file,
which would be the only file to be changed for a new installation.
So here are my steps:
- Copy my modified firstrun.sh and firstrun.env to
/mnt/sdcard/bootfs/
. - Make changes to
firstrun.env
to match your desired config. Note:MY_USER_PASSWORD
is optional. I usually SSH via key into the machines and skip the password. - Modify
/mnt/sdcard/bootfs/cmdline.txt
and append this to the only long single line:cfg80211.ieee80211_regdom=DE systemd.run=/boot/firstrun.sh systemd.run_success_action=reboot systemd.unit=kernel-command-line.target
This references thefirstrun.sh
to be run at first boot. - Change the region code in
cmdline.txt
to match your country.
1.2.3. Other files than firstrun.sh
My goal was to have a firstrun.env
with all the related environment variables,
and only this file needs to be changed for future installations.
The firstrun.sh
should remain untouched.
This was problematic, because there is an imager_fixup which makes changes to the file on the first boot. What a hack, and it took me some hours to debug. :(
So what you could expect at /boot/*
is in reality mounted during the boot process at /boot/firmware/*
.
This whole setup process is a huge hack, and so much more complicated than before with bullseye.
2. Armbian
For Orange Pi Zero 2W and Radax Zero 3W I like to use Armbian, because they provide recent Debian images.
Tested with Armbian 24.8.1: Things are so much easier here.
2.1. General setup via .not_logged_in_yet
sudo cp .not_logged_in_yet /mnt/sdcard/root/
The file should have existed there already, but should have been empty.
Download my example file: .not_logged_in_yet
It covers WiFi, locale, timezone, root password and user creation.
It does not cover hostname, ssh key authentication, and sudo without password, see below.
2.2. Extra setup
2.2.1. Hostname
The file above does not cover the hostname.
Same as for bullseye:
Edit /mnt/sdcard/etc/hosts
and /mnt/sdcard/etc/hostname
.
2.2.2. SSH key
sudo install -o 1000 -d /mnt/sdcard/home/me/
sudo install -o 1000 -m 700 -d /mnt/sdcard/home/me/.ssh/
echo 'ssh-rsa AAAAB3... openpgp:0x01234567' | sudo install -o 1000 -m 600 /dev/stdin /mnt/sdcard/home/me/.ssh/authorized_keys
echo 'PasswordAuthentication no' | sudo tee --append /mnt/sdcard/etc/ssh/sshd_config
2.2.3. sudo without password
echo '%sudo ALL=(ALL) NOPASSWD: ALL' | sudo tee /mnt/sdcard/etc/sudoers.d/010_sudo-nopasswd
2.3. Note on DHCP
Important: You must set PRESET_NET_USE_STATIC
to 0
explicitly.
If you skip this config entry, DHCP is not enabled.
See here:
https://github.com/armbian/build/blob/d16f710e7eabdfd9b1911aa6cc7648c25d038208/packages/bsp/common/usr/lib/armbian/armbian-firstlogin#L54
2.4. Why in /root/ user folder?
What's confusing to me:
I would have guessed that /root/.not_logged_in_yet
is only executed after the first login via root.
That means WiFi settings would be obsolete here, because you could never login before the network connection is made.
However, some script somewhere writes a /etc/netplan/*.yaml
file, if WiFi entries are found in .not_logged_in_yet
.
Magic.
(Seems to happen around here https://github.com/armbian/build/blob/d16f710e7eabdfd9b1911aa6cc7648c25d038208/packages/bsp/common/usr/lib/armbian/armbian-firstlogin#L119)
2.5. What cost me time
All of this is not required:
FR_net_wifi_ssid
armbian_first_run.txt
- WiFi setup via
netplan
This is still an alternative, but will be set up automatically via the.not_logged_in_yet
file.
3. DietPi
I have tried the image DietPi_RadxaZERO3-ARMv8-Bookworm.img.xz
from 2024-09-13.
There is a extra config parition.
It is described here:
https://dietpi.com/docs/usage/#how-to-do-an-automatic-base-installation-at-first-boot-dietpi-automation
Edit the dietpi.txt
and dietpi-wifi.txt
to your needs.
Hostname, locale, timezone, and ssh key authentication is all covered. I couldn't find a setting in the config file for passwordless sudo, but it was activated automatically.
For my personal settings, I have changed:
AUTO_SETUP_KEYBOARD_LAYOUT
AUTO_SETUP_TIMEZONE
AUTO_SETUP_NET_WIFI_ENABLED
AUTO_SETUP_NET_WIFI_COUNTRY_CODE
AUTO_SETUP_HEADLESS
AUTO_SETUP_SSH_PUBKEY
SURVEY_OPTED_IN
SOFTWARE_DISABLE_SSH_PASSWORD_LOGINS
Everything worked on first try. However, I dislike that the real setup script is started when you boot up the SBC for the first time and login as root.
WHen I tried to login directly using the dietpi
user, I got a warning.
In the script which runs on first login as root
, you are asked several questions,
which can be answered during a UI. Then the system is updated and settings are applied.
That's exactly what I'd like to avoid in a headless setup. If I had to do it for like 20 installs, that would be boring and repetitive.
The extra tools for installing software might be neat for beginners, but I don't really need them.
Even though the headless installation was best documented out of the three operating systems I have tested, I will stick with Armbian.