2022-04-07 13:29:41 -05:00
|
|
|
---
|
|
|
|
|
title: "Nixos on Raspberry Pi 4"
|
|
|
|
|
date: 2022-04-07T12:20:02-05:00
|
|
|
|
|
draft: false
|
2024-04-30 23:17:02 -05:00
|
|
|
tags:
|
|
|
|
|
- Nix
|
|
|
|
|
- NixOS
|
2022-04-07 13:29:41 -05:00
|
|
|
---
|
|
|
|
|
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
|
|
|
|
|
<enter>
|
|
|
|
|
-8G
|
|
|
|
|
|
|
|
|
|
n
|
|
|
|
|
p
|
|
|
|
|
3
|
|
|
|
|
<enter>
|
|
|
|
|
<enter>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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.
|