Installing NixOS on a Raspberry Pi 3
- nixos rpi
The process of installing NixOS on a Raspberry Pi 3 is pretty straightforward, as they are fully supported upstream. However, the documentation is somewhat spread out and occasionally a bit outdated and/or confusing, so I thought it may be worthwhile to summarize my recent experience.
-
Download an image from Hydra, NixOS’ CI tool. For the Pi 3 you’ll use an AArch 64 image of the latest release (currently 20.03), which can be found here.
-
Flash the image on an SD card with a tool of your choice, e.g. Etcher or
dd
. If you don’t have an HDMI cable available you’ll also have to edit/extlinux/extlinux.conf
to configure the UART console. I had such a cable available and this post assumes you do to. -
The first type you boot from this card the NixOS installer will expand the volume, which can take a little bit of time.
-
Once the system booted, it’s time to get a basic configuration set up. I started from zupo’s config, who wrote one of the first comprehensive tutorials for NixPS on Raspberry Pi.
$ curl https://raw.githubusercontent.com/zupo/nix/master/rpi.nix > /etc/nixos/configuration.nix
There were two changes I needed to make: since NixOS 19.09 the first volume no longer holds
/boot
but only the Raspberry Pi firmware files, so it no longers needs to be resized. Also the configuration option determining whether or not documentation will be installed now has a different name. These are the changes I applied to/etc/nixos/configuration.nix
:# File systems configuration for using the installer's partition layout fileSystems = { - "/boot" = { - device = "/dev/disk/by-label/NIXOS_BOOT"; - fsType = "vfat"; - }; "/" = { device = "/dev/disk/by-label/NIXOS_SD"; fsType = "ext4"; @@ -31,17 +31,23 @@ }; # Preserve space by sacrificing documentation and history - services.nixosManual.enable = false; + documentation.nixos.enable = false; nix.gc.automatic = true;
The file should now look like this:
{ config, pkgs, lib, ... }: { # NixOS wants to enable GRUB by default boot.loader.grub.enable = false; # if you have a Raspberry Pi 2 or 3, pick this: boot.kernelPackages = pkgs.linuxPackages_latest; # A bunch of boot parameters needed for optimal runtime on RPi 3b+ boot.kernelParams = ["cma=256M"]; boot.loader.raspberryPi.enable = true; boot.loader.raspberryPi.version = 3; boot.loader.raspberryPi.uboot.enable = true; boot.loader.raspberryPi.firmwareConfig = '' gpu_mem=256 ''; environment.systemPackages = with pkgs; [ raspberrypi-tools ]; # File systems configuration for using the installer's partition layout "/" = { device = "/dev/disk/by-label/NIXOS_SD"; fsType = "ext4"; }; }; # Preserve space by sacrificing documentation and history documentation.nixos.enable = false; nix.gc.automatic = true; nix.gc.options = "--delete-older-than 30d"; boot.cleanTmpDir = true; # Configure basic SSH access services.openssh.enable = true; services.openssh.permitRootLogin = "yes"; # Use 1GB of additional swap memory in order to not run out of memory # when installing lots of things while running other things at the same time. swapDevices = [ { device = "/swapfile"; size = 1024; } ]; }
-
Time to build from the new minimal configuration, do some cleanup work and reboot just in case:
$ nixos-rebuild switch $ nix-collect-garbage -d $ nixos-rebuild switch # removes now unused boot loader entries $ reboot
-
Add a user account so we no longer need to SSH to the Pi as
root
. I opted for the declarative approach:users.users.pi = { isNormalUser = true; home = "/home/pi"; extraGroups = [ "wheel" "networkmanager" ]; openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... pi@other" ]; };
The extra groups allow the new user to execute commands as
root
viasudo
and to configure the network. If you want to allow members of thewheel
group to usesudo
without a password, add the following option to your Nix configuration:security.sudo.wheelNeedsPassword = false;
With this new user in place we can also disable the
permitRootLogin
option in/etc/nixos/configuration.nix
:- services.openssh.permitRootLogin = "yes";
-
Add some system packages. For basic necessities I prefer the declarative approach over installation with
nix-env
, e.g.:
environment.systemPackages = [
pkgs.vim
pkgs.git
];
That’s it, have fun with NixOS on your Raspberry Pi 3.