2021-12-10 09:48:34 -05:00
---
2022-06-27 11:35:35 -04:00
myst:
html_meta:
"description lang=en": "Installing NixOS on a Raspberry Pi"
"keywords": "Raspberry Pi, rpi, NixOS, installation, image, tutorial"
2021-12-10 09:48:34 -05:00
---
# Installing NixOS on a Raspberry Pi
2023-08-01 14:49:32 -04:00
This tutorial assumes you have a [Raspberry Pi 4 Model B with 4GB RAM ](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/ ).
2021-12-10 09:48:34 -05:00
Before starting this tutorial, make sure you have
2023-08-01 14:49:32 -04:00
[all the necessary hardware ](https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up/1 ):
2021-12-10 09:48:34 -05:00
- HDMI cable/adapter.
- 8GB+ SD card.
2023-08-01 14:49:32 -04:00
- SD card reader (in case your machine doesn't have an SD slot).
2021-12-10 09:48:34 -05:00
- Power cable for your Raspberry Pi.
- USB keyboard.
:::{note}
2023-08-01 14:49:32 -04:00
This tutorial was written for the Raspberry Pi 4B. Using a previously supported model like the 3B or 3B+ is possible with some modifications to this tutorial.
2021-12-10 09:48:34 -05:00
:::
## Booting NixOS live image
:::{note}
Booting from USB may require an EEPROM firmware upgrade. This tutorial boots from an SD card to avoid such hiccups.
:::
2023-07-10 17:09:59 -04:00
To prepare the AArch64 image on another device with Nix, run the following commands:
2021-12-10 09:48:34 -05:00
```shell-session
$ nix-shell -p wget zstd
2022-11-08 11:37:41 -05:00
2023-07-10 17:09:59 -04:00
[nix-shell:~]$ wget https://hydra.nixos.org/build/226381178/download/1/nixos-sd-image-23.11pre500597.0fbe93c5a7c-aarch64-linux.img.zst
[nix-shell:~]$ unzstd -d nixos-sd-image-23.11pre500597.0fbe93c5a7c-aarch64-linux.img.zst
2022-11-08 11:37:41 -05:00
[nix-shell:~]$ dmesg --follow
2021-12-10 09:48:34 -05:00
```
:::{note}
2023-08-01 14:49:32 -04:00
You can download a recent image from [Hydra ](https://hydra.nixos.org/job/nixos/trunk-combined/nixos.sd_image.aarch64-linux ),
2023-07-10 17:09:59 -04:00
clicking on the latest successful build (marked with a green checkmark), and copying the link to the build product image.
2021-12-10 09:48:34 -05:00
:::
2023-07-20 13:13:57 -04:00
:::{note}
2023-07-21 14:30:39 -04:00
It may be more convenient to use a software like [Etcher ](https://www.balena.io/etcher/ ) to flash the image to your SD card if you are on a system where it's available.
2023-07-20 13:13:57 -04:00
:::
2021-12-10 09:48:34 -05:00
Your terminal should be printing kernel messages as they come in.
Plug in your SD card and your terminal should print what device it got assigned, for example `/dev/sdX` .
2023-08-01 14:49:32 -04:00
Press < kbd > Ctrl</ kbd > +< kbd > C</ kbd > to stop `dmesg --follow` .
2021-12-10 09:48:34 -05:00
2023-07-10 17:09:59 -04:00
Copy NixOS to your SD card by replacing `sdX` with the name of your device in the following command:
2021-12-10 09:48:34 -05:00
2022-11-08 11:37:41 -05:00
```console
2023-07-16 11:45:57 -04:00
[nix-shell:~]$ sudo dd if=nixos-sd-image-23.11pre500597.0fbe93c5a7c-aarch64-linux.img of=/dev/sdX bs=4096 conv=fsync status=progress
2021-12-10 09:48:34 -05:00
```
Once that command exits, **move the SD card into your Raspberry Pi and power it on** .
You should be greeted with a fresh shell!
2023-10-23 05:23:08 -04:00
In case the image doesn't boot, it's worth [updating the firmware ](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#bootloader_update_stable ) and booting the image again.
2021-12-10 09:48:34 -05:00
## Getting internet connection
Run `sudo -i` to get a root shell for the rest of the tutorial.
2023-08-01 14:49:32 -04:00
At this point you'll need an internet connection. If you can use an ethernet cable, plug it in and skip to the next section.
2021-12-10 09:48:34 -05:00
2022-04-11 08:52:24 -04:00
If you're connecting to wifi, run `iwconfig` to find the name of your wireless network interface. If it's `wlan0` , replace `SSID` and `passphrase` with your data and run:
2021-12-10 09:48:34 -05:00
```shell-session
# wpa_supplicant -B -i wlan0 -c <(wpa_passphrase 'SSID' 'passphrase') &
```
2022-04-11 08:52:24 -04:00
Once you see in your terminal that connection is established, run `host nixos.org` to check that the DNS resolves correctly.
2021-12-10 09:48:34 -05:00
In case you've made a typo, run `pkill wpa_supplicant` and start over.
## Updating firmware
To benefit from updates and bug fixes from the vendor, we'll start by updating Raspberry Pi firmware:
```shell-session
# nix-shell -p raspberrypi-eeprom
# mount /dev/disk/by-label/FIRMWARE /mnt
# BOOTFS=/mnt FIRMWARE_RELEASE_STATUS=stable rpi-eeprom-update -d -a
```
2023-07-10 17:09:59 -04:00
## Installing and Configuring NixOS
2023-08-01 14:49:32 -04:00
2023-07-10 17:09:59 -04:00
Now we'll install NixOS with our own configuration, here creating a `guest` user and enabling the SSH daemon.
2021-12-10 09:48:34 -05:00
2023-07-10 17:09:59 -04:00
In the `let` binding below, change the value of the `SSID` and `SSIDpassword` variables to the `SSID` and `passphrase` values you used previously:
2021-12-10 09:48:34 -05:00
```nix
{ config, pkgs, lib, ... }:
let
user = "guest";
password = "guest";
SSID = "mywifi";
SSIDpassword = "mypassword";
interface = "wlan0";
hostname = "myhostname";
in {
2023-07-10 17:09:59 -04:00
2023-07-11 17:26:53 -04:00
boot = {
kernelPackages = pkgs.linuxKernel.packages.linux_rpi4;
initrd.availableKernelModules = [ "xhci_pci" "usbhid" "usb_storage" ];
loader = {
grub.enable = false;
generic-extlinux-compatible.enable = true;
};
};
2021-12-10 09:48:34 -05:00
fileSystems = {
"/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
options = [ "noatime" ];
};
};
networking = {
hostName = hostname;
wireless = {
enable = true;
networks."${SSID}".psk = SSIDpassword;
interfaces = [ interface ];
};
};
environment.systemPackages = with pkgs; [ vim ];
services.openssh.enable = true;
users = {
mutableUsers = false;
users."${user}" = {
isNormalUser = true;
password = password;
extraGroups = [ "wheel" ];
};
};
2023-07-11 17:26:53 -04:00
hardware.enableRedistributableFirmware = true;
system.stateVersion = "23.11";
2021-12-10 09:48:34 -05:00
}
```
To save time on typing the whole configuration, download it:
```shell-session
2023-07-11 17:26:53 -04:00
# curl -L https://tinyurl.com/tutorial-nixos-install-rpi4 > /etc/nixos/configuration.nix
2021-12-10 09:48:34 -05:00
```
2023-07-10 17:09:59 -04:00
:::{note}
Credentials you write into a NixOS configuration will be stored in plain text in your `/nix/store` when that configuration is built.
If you **don't** want this to happen, you can enter your credentials at a console or use one of the community's solutions for encrypted secrets.
:::
2021-12-10 09:48:34 -05:00
2023-07-10 17:09:59 -04:00
Due to the way the `nixos-sd-image` is designed, NixOS is actually *already installed* at this point, so we only need to `nixos-rebuild` with our new configuration:
2021-12-10 09:48:34 -05:00
```shell-session
2023-07-10 17:09:59 -04:00
# nixos-rebuild boot
2021-12-10 09:48:34 -05:00
# reboot
```
2023-08-01 14:49:32 -04:00
If your system doesn't boot, select the oldest configuration in the bootloader menu to get back to the live image and start over.
2021-12-10 09:48:34 -05:00
## Making changes
It booted, congratulations!
To make further changes to the configuration, [search through NixOS options ](https://search.nixos.org/options ),
2022-04-11 08:52:24 -04:00
edit `/etc/nixos/configuration.nix` , and update your system:
2021-12-10 09:48:34 -05:00
```shell-session
$ sudo -i
# nixos-rebuild switch
```
## Next steps
2023-08-01 14:49:32 -04:00
- Once you have a working OS, try upgrading it with `nixos-rebuild switch --upgrade` to install more recent package versions, and reboot to the old configuration if something broke.
2023-08-14 16:10:44 -04:00
- To enable hardware acceleration for a nice graphical desktop experience, you can enable the [`nixos-hardware` module ](https://github.com/nixos/nixos-hardware ) by adding the following to your configuration:
```nix
imports = [
"${builtins.fetchGit { url = "https://github.com/NixOS/nixos-hardware.git"; }}/raspberry-pi/4"
];
```
2023-07-10 17:09:59 -04:00
- To tweak bootloader options affecting hardware, [see `config.txt` options ](https://www.raspberrypi.org/documentation/configuration/config-txt/ ). You can change these options by running `mount /dev/disk/by-label/FIRMWARE /mnt` and opening `/mnt/config.txt` .