Installing NixOS on RockPI 4C
tl;dr: use Tow-Boot on separate storage from your OS and use the UEFI image to install your OS. It's great all the SBC-specific pain is spent only on getting Tow-Boot to run — installing the OS becomes as easy as on x86 machines.
I have a RockPI 4C on which I store some files and run my Home Assistant. The problem is that I'm afraid to touch it as the current setup will be somewhat hard to replicate as it accumulated over the last two and a half years. As such I decided to reinstall it from scratch 🤓
To not end up in this situation again, I decided to install nixos on it. This blog post documents how to do that. There are probably multiple ways to achieve this, but I decided to go with UEFI, so that I can use as much mainline stuff as possible. Let's see how far it gets me.
Step one: installing the UEFI firmware
The SBC has built-in SPI storage and you can install a bootloader on it. U-Boot is the standard1 here. There is a Tow-Boot project which describes itself as a user-friendly u-boot distribution and supports various devices, including RockPI 4C. This seems like natural choice here.
Radxa (the maker of RockPI) has a guide on how to flash the SPI. As I already had something on the SPI, I needed to remove that. And as such I figured I'd install the Tow-Boot like this as well.
# Get rkdeveloptool
nix shell nixpkgs#rkdeveloptool
# list devices
rkdeveloptool ld
# Download the loader from the internet
wget https://dl.radxa.com/rockpi/images/loader/spi/rk3399_loader_spinor_v1.15.114.bin
# Download the loader from computer to SBC
sudo rkdeveloptool db rk3399_loader_spinor_v1.15.114.bin
# Create file filed with zeros
dd if=/dev/zero of=./zero.img bs=1M count=4
# Write it to the SBC
sudo rkdeveloptool wl 0 zero.img
# Restart the SBC
sudo rkdeveloptool rd
I don't know if this actually worked as I during debugging other issues I also created eMMC with normal Tow-Boot installer.
Make sure that you are connecting your SBC to display of reasonable resolution and that your keyboard is connected during the boot. Don't be like me :-)
Sidenote: to get the board working in USB OTG mode, USB A to USB C cable did not work. Instead, I had to use USB A (outie) to USB C adapter, plug in the C end of the cable, and plug that into USB C to USB A adapter. This unholy abomination was close enough to the abomination of USB A to USB A cable they suggest in the wiki.
Step two: Boot nixos installer
Now with the firmware installed, we can install nixos according to the official guide. Get the "NixOS unstable, new kernel" option. Exact version I used is here. While that was downloading I prepared the eMMC with GPT layout, EFI system partition (1GiB) and ext4 partition labelled nixos, so that I did not have to do this from cli after it boots (we are using the minimal image here).
The iso was written to my flash drive with dd if=path.iso of=/dev/sdX bs=1M oflag=direct,sync status=progress
After plugging the usb drive in, inserting the eMMC, plugging in ethernet cable
and then plugging in the power I was in nixos installer, the rest is a normal
nixos installation from minimal image.
Step three: Install nixos
Update: You might be interested in using nixos-anywhere for this step.
sudo -s
mount /dev/mmcblk0p2 /mnt
mkdir -p /mnt/boot
mount /dev/mmcblk0p1 /mnt/boot
nixos-generate-config --root /mnt
chmod o+rx /mnt
cd /mnt/etc/nixos
vim configuration.nix
In configuration.nix set the following:
# boot.loader.systemd-boot.enable = true; # comment this one out
boot.loader.efi.canTouchEfiVariables = false; # and disable this
# systemd-boot did not work for me, so grub it is
boot.loader.grub = {
enable = true;
efiSupport = true;
efiInstallAsRemovable = true;
device = "nodev";
};
# Also, I used the latest kernel, not sure if that's neccessary
boot.kernelPackages = pkgs.linuxPackages_latest;
maybe set a hostname, but the rest can be configured after you boot the installed system. Now install the system:
nixos-install
Footnotes
-
Standard as in "it's what I'm used to seeing in this context". It's used on my asahi laptop I used during this experiment as host system. I also vaguely remember it from when I was rooting my phone but that's been multiple phone refreshes ago now. ↩