diff --git a/content/posts/nixos-on-raspberry-pi-4.md b/content/posts/nixos-on-raspberry-pi-4.md new file mode 100644 index 0000000..e822c29 --- /dev/null +++ b/content/posts/nixos-on-raspberry-pi-4.md @@ -0,0 +1,215 @@ +--- +title: "Nixos on Raspberry Pi 4" +date: 2022-04-07T12:20:02-05:00 +draft: false +--- +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.