Installing NixOS (headless) on a Rasberry Pi 3
2020.04.25 Nix NixOS Embeddedcontents
- Requirements
- Useful resources
- Download NixOS image
- Flash to SD
- Enabling SSH (optional)
- Configuration
- Configure and nixos-rebuild
- Upgrade
- Possible configuration additions
Installing NixOS on a Raspberry Pi, why? In my opinion, the experience of running NixOS on Raspberry Pi is pretty much flawless, and it's nice to have a deterministic, minimal, and easily (re)deployable OS image for your RPi, to make it do whatever it is you want it to do, from a local home server, to an embedded controller in a larger project.
Currently the Raspberry Pi version 3 is the only Pi with first class NixOS support, the previous Pis being ARMv6 and ARMv7 rather than AArch64/ARMv8. It seems it's possible to run NixOS on a Pi 1 or 2, but the path of least resistance is certainly using a Pi 3. It seems support for version 4 will arrive at some point.
Requirements¶
- Raspberry Pi 3
- Micro SD card (I used 16gb)
- HDMI cable and monitor, USB keyboard
Useful resources¶
Download NixOS image¶
You can download the NixOS image from Hydra, as stated here, for:
Download the image for the latest successful build.
Flash to SD¶
Untar the image and flash the SD card from your host system as follows.
Ensure device partitions are unmounted:
sudo umount /dev/mmcblk0*
Flash without monitoring progress:
bzip2 -cd nixos-sd-image-*-aarch64-linux.img.bz2 | sudo dd of=/dev/mmcblk0 bs=4M
Or flash while monitoring progress with pv
:
bzip2 -cd nixos-sd-image-*-aarch64-linux.img.bz2 | pv | sudo dd of=/dev/mmcblk0 bs=4M
Unmount:
sync sudo umount /dev/mmcblk0*
For me, the SD block device path was /dev/mmcblk0
, the image has to be
written to the whole device, rather than a partition, as the image contains a
complete disc image including partition table.
The image written to the SD card resizes itself automatically on first boot.
Enabling SSH (optional)¶
On boot, the system has no user passwords, and SSH is disabled. For this
reason, you will need to use a USB keyboard to set passwords using passwd
,
and enable SSH if you require:
sudo systemctl start sshd
If you start SSH in this way, it will only be temporary, however, and will not persist after reboot, until you add a nix configuration as shown below.
Configuration¶
The following takes inspiration from:
I have removed GPU memory since this is to be used as a headless server, rather than running any graphical environment.
{ config, pkgs, lib, ... }: { boot.loader.grub.enable = false; boot.kernelPackages = pkgs.linuxPackages_latest; #boot.kernelParams = ["cma=256M"]; boot.loader.generic-extlinux-compatible.enable = true; boot.loader.raspberryPi.uboot.enable = true; boot.loader.raspberryPi.enable = true; boot.loader.raspberryPi.version = 3; # System packages environment.systemPackages = with pkgs; [ vim ]; fileSystems = { "/" = { device = "/dev/disk/by-label/NIXOS_SD"; fsType = "ext4"; }; }; # Preserve space by disabling documentation and enaudo ling # automatic garbage collection documentation.nixos.enable = false; nix.gc.automatic = true; nix.gc.options = "--delete-older-than 30d"; boot.cleanTmpDir = true; # Configure SSH services.openssh.enable = true; services.openssh.permitRootLogin = "yes"; # Add users users.users = { root = {}; pi = { isNormalUser = true; home = "/home/nixos"; extraGroups = [ "wheel" ]; hashedPassword = "$6$JYcd0P.HQIE3ayRp$yNZYogMy99HUzmip3MAea78V9dMMoN7yXroOpkmOmLxvSjXpXpNNfOZF0VptJ7h5wvP5uZ.ASuzUkKwEhIJAJ1"; # consider adding a hashed password, or ssh key here, see: # https://eipi.xyz/blog/installing-nixos-on-a-rasberry-pi-3#? }; }; swapDevices = [ { device = "/swapfile"; size = 1024; } ]; }
The nixos
user's password will be qqcTch4m
.
If you want to change the user's password, change the string in
hashedPassword
to one generated by:
mkpasswd -m sha-512
In some distros, this tool can be found in the whois
package.
If you want to use the user nixos
and give it a password, so it's possible to
log in and the user is able to use sudo
, you may have some difficulties, I
did.
Configure and nixos-rebuild
¶
The easiest way to proceed is to attach a USB keyboard and an HDMI monitor to
the Pi, since even if you use SSH, you will need a keyboard and monitor to
start sshd
.
We need some way to apply an /etc/nixos/configuration.nix
to the SD card. I
used a USB flash device, copying the configuration below onto it, and mounting
and copying off the memory stick onto the RPi as follows:
mkdir /tmp/mnt sudo mount /dev/sda1 /tmp/mnt sudo cp /tmp/mnt/configuration.nix /etc/nixos/
And then rebuild:
sudo nixos-rebuild switch
If you want to log the rebuild log for any reason, you could use the already mounted flash stick:
sudo nixos-rebuild switch | sudo tee /tmp/mnt/rebuild-log
You don't need to set a password before doing this, as the nixos
user present
by default seems to be in the wheel
group, so has sudo
.
You need internet connectivity to be able to rebuild NixOS, for which the
easiest way is likely to connect it to Ethernet, test with ping 1.1.1.1
.
Upgrade¶
Once up and running, you may want to add a NixOS channel and upgrade:
nix-channel --add https://nixos.org/channels/nixos-unstable nixos nixos-rebuild switch --upgrade
Possible configuration additions¶
Static IP¶
If you want to give the Pi a static IP, add the following to the configuration.
{ networking = { usePredictableInterfaceNames = false; interfaces.eth0.ipv4.addresses = [{ address = "192.168.1.160"; prefixLength = 24; }]; defaultGateway = "192.168.1.1"; nameservers = [ "192.168.1.1" "1.1.1.1" "8.8.8.8" ]; }; }