--- title: "Nixos on Raspberry Pi 4" date: 2022-04-07T12:20:02-05:00 draft: false tags: - Nix - NixOS --- So I've been playing around with NixOS on a Raspberry Pi 4 that I have at the house. NixOS seems like a great idea, but getting it onto the Raspberry Pi 4 is something of a beast of a process. So I wanted to document here how I did it. Most of the process is the normal NixOS installation process, with a few tweaks at the very end. # My Pi's Case is a Challenge Rather than having a plain Raspberry Pi 4 and writing the SD image provided by the NixOS team to that image, I have my Pi in an [Argon One m.2](some link here) case. That case allows me to mount an m.2 SSD to an RPi4 B device over USB3. They're pretty slick cases, decent quality, include full size HDMI ports and basic power management, and still allow GPIO header splitouts if you need them for your application. If you are looking for a handy little case that is metal, well built, functions as a heat sync, includes a tiny fan, and gives you the SSD USB3 split out, then I suggest you take a look at this case. They also have a version that does not have the SSD, but still gives you the port split out and is the same well built metal top enclosure. One downfall of the case is that, when closed, it does not leave the SD card slot accessible. You can load an SD card in before you put the Pi into the case if you plan to always boot off one, but I wanted the significantly better speed that the SSD over USB3 can give compared to a plain SD card. So, before I loaded the Pi into the case I used the SD card slot to update the Pi firmware (my 4s are pretty old) and set it to default boot from USB by default. I am going to operate under the assumption you have your Pi set to boot off of USB and already have a chosen device plugged in to the system. # NixOS Boot NixOS provides two main ways to install. There is a bootable ISO file, and for machines like the RPi4 there is a pre-built SD card image. While it's maybe possible to get the Aarch64 ISO to boot, I have not spent time working on that. I opted for a manual install based on the SD card image. But I did not use an SD card. ## Get the SD Image Get the latest version of the SD image. At the time of writing the latest release of NixOS is 21.11, so the latest versions of the images can be found [in Hydra](https://hydra.nixos.org/jobset/nixos/release-21.11-aarch64). From that page select the "Jobs" tab. Search the page for "sd\_image". I opted for the item called "nixos.sd\_image.aarch64-linux". There is also one that is called "sd\_image\_new\_kernel". I haven't tried it, so I cannot tell you if it works. Use your favorite tool to burn the image to a regular USB flash drive. I have used the Raspberry Pi Imager program as well as `dd` from the command line in Linux. There are other tools, but choose your favorite one to write it to a Flash Drive. With the RPi4 turned off, insert the prepared Flash Drive to the RPi4's USB port. I have one of the USB3 ports open, so that's the one I selected. If necessary, select this drive. In my case, this Flash Drive ends up as the default option. ## Parition the SSD The SD Image will boot you to a terminal and auto log in as the "nixos" user. Now you need to partition the drive. You should have access to the `lsblk` tool that can list the drives. In my case the flash drive is `/dev/sdb` and the SSD is `/dev/sda`. If you are on a different system, adjust these commands appropriately. I started by wiping the SSD with `wipefs`. ```bash sudo wipefs -f /dev/sda ``` Now you need to partition the SSD card. So let's enter our partition utility ```bash sudo fdisk /dev/sda ``` Create partition 1 starting from sector 2048, with size 500M. ``` n p 1 2048 +500M ``` Create other partitions the way you want them laid out. I create one large root partition that takes up from 500M to within 8GB of the end of the drive. The last 8GB I reserve for swap. So these commands create those two partitions. ``` n p 2 -8G n p 3 ``` Now set the partition types ``` t 1 0b t 3 82 ``` 0b is the code for W95 FAT32 and 82 is the type for Linux Swap. Now, save the partition table and exit the program with command `w`. Be sure the filesystems are synced. ```bash sudo sync ``` ## Format the drives Format the partitions you created. These are the ones I use: ```bash sudo mkfs.vfat /dev/sda1 sudo mkfs.ext4 /dev/sda2 sudo mkswap /dev/sda3 sudo swapon /dev/sda3 ``` Obviously you can use whatever format you want for your Linux partitions and you might have skipped a swap partition. But that first partition needs to be a vfat partition to store the UEFI code. ## Mount the drive Now, create the mountpoint where the target system will be installed. ```bash sudo mkdir -p /mnt sudo mount /dev/sda2 /mnt sudo mkdir -p /mnt/boot sudo mount /dev/sda1 /mnt/boot ``` ## Generate and Customize Config If you have your own way to fetch NixOS Configuration files, go ahead and fetch those to /mnt/etc/nixos. If you are new to NixOS, then just skip that bit. Generate the base configuration: ```bash sudo nixos-generate-config --root /mnt ``` The general process of configuration and is beyond this, but be sure you have at least a text editor of some kind in your installation! Now go to /mnt/etc/nixos/ and edit the configuration to your heart's desire. The following settings are great for a Raspberry Pi 4: ``` { boot = { # The Linux kernel version kernelPackages = pkgs.linuxPackages_rpi4; # Options to enable serial console and more kernelParams = [ "8250.nr_uarts=1" "console=tyAMA0,115200" "console=tty1" "cma=128M" ]; # The bootloader loader = { raspberryPi = { enable = true; version = 4; }; # Use extlinux, whereas the NixOS default is Grub grub.enable = false; # Enables the generation of /boot/extlinux/extlinux.conf generic-extlinux-compatible.enable = true; }; }; environment.systemPackages = with pkgs; [ raspberrypifw ]; } ``` ## Install Normally in NixOS you would now run the basic installer `sudo nixos-install --root /mnt`. However, the SD image does not have any of the NixOS channels installed and it lacks the space necessary to sync them in the default edition. So now we have to run the command in a slightly different way. ```bash sudo nixos-install --root /mnt -I https://channels.nixos.org/nixos-21.11-aarch64/nixexprs.tar.xz ``` ## Copy the firmware Raspberry Pis require special firmware. By default this does not get installed into the `/boot` partition where UEFI needs to find it. However, it is in the Flash drive that you are already running. So let's copy it over. In my system, remember that the Flash drive is `/dev/sdb`. So for me this process looks like this ```bash sudo mkdir -p /firmware sudo mount /dev/sdb1 /firmware sudo cp -r /firmware/* /mnt/boot ``` This should allow you to boot the system off of the SSD. Now power off the system, remove the Flash drive, and boot. # Enjoy Reboot into NixOS, login as root with the password you created during install, and set any password for users you may have created in your configuration.