NixOS on ARM/Raspberry Pi: Difference between revisions

Tennox (talk | contribs)
Add Raspberry Pi 5 to tables (it's already described below)
Replace outdated Raspberry Pi guidance with current images, nixos-hardware profiles, the U-Boot/extlinux boot flow, firmware management, and declarative config.txt
 
Line 1: Line 1:
{{ARM/breadcrumb}}
{{ARM/breadcrumb}}
<div class="infobox">
<div class="infobox">
{|class="table"
{| class="table"
!colspan="2" class="title"|Raspberry Pi Family
! colspan="2" class="title" | Raspberry Pi family
|-
|-
|colspan="2"|[[File:raspberry_pi_3_glamour.jpg|frameless|256px|A Raspberry Pi 3 with enclosure.]]
| colspan="2" | [[File:raspberry_pi_3_glamour.jpg|frameless|256px|A Raspberry Pi 3 with enclosure.]]
|-
|-
!colspan="2" class="title"|Raspberry Pi
! Manufacturer
| Raspberry Pi Ltd
|-
|-
!Architecture
! Recommended architecture
|ARMv6
| AArch64 on 64-bit boards
|-
|-
!colspan="2" class="title"|Raspberry Pi 2
! Boot method
|-
| Raspberry Pi firmware and U-Boot
!Architecture
|ARMv7
|-
!colspan="2" class="title"|Raspberry Pi 3
|-
!Architecture
|AArch64 + ARMv7
|-
!colspan="2" class="title"|Raspberry Pi 4
|-
!Architecture
|AArch64 + ARMv7
|-
! colspan="2" |Raspberry Pi 5
|-
!Architecture
|AArch64 + ARMv7
|}
|}
</div>
</div>
The Raspberry Pi family of devices is a series of single-board computers made by the Raspberry Pi Foundation. They are all based on Broadcom System-on-a-chip (SOCs).
== Status ==


Only the ''Raspberry Pi 3 Family'' is supported upstream, with the AArch64 effort. Other Raspberry Pis are part of '''@dezgeg''''s porting efforts to ARMv6 and ARMv7.
'''Raspberry Pi''' boards use Broadcom systems-on-chip and a board-specific boot process. For 64-bit models, the generic AArch64 SD image is the usual starting point. Raspberry Pi firmware starts U-Boot, which reads the extlinux configuration generated by NixOS. The [https://github.com/NixOS/nixos-hardware/tree/master/raspberry-pi nixos-hardware repository] provides profiles for Raspberry Pi 2, 3, 4, and 5. These profiles select Raspberry Pi downstream kernels and support declarative <code>config.txt</code> generation.<ref name="hardware-readme">[https://github.com/NixOS/nixos-hardware/blob/master/raspberry-pi/README.md nixos-hardware: Raspberry Pi profiles and modules]</ref>


The Linux kernel in use, except for the Raspberry Pi 1 family, is the mainline Linux kernel, and not the Raspberry Pi Foundation's fork. This could reduce compatibility with some add-on boards or third-party libraries<sup>[expanded explanation needed]</sup>.
== Support ==


The following table is intended to be updated by the NixOS contributors with the current status of the boards. For a list of products, [https://www.raspberrypi.org/products/ see the ''Products Archive]''.
AArch64 has an official NixOS binary cache. ARMv6 and ARMv7 can still be built from Nixpkgs, but NixOS does not publish binary caches for them.<ref name="arm-cache">[[NixOS on ARM#Binary caches|NixOS on ARM: binary caches]]</ref>


{|class="wikitable"
{| class="wikitable"
! Board family
! Recommended architecture
! NixOS image
! <code>nixos-hardware</code> profile
! Notes
|-
|-
! Board name
| Raspberry Pi 1, Zero, and Zero W
! Architecture
| ARMv6
! Support
| Build from Nixpkgs or use a community image
| None
| No official binary cache
|-
|-
!colspan="3" style="text-align: left;"|Raspberry Pi 1
| Raspberry Pi 2
| ARMv7
| Build from Nixpkgs or use a community image
| <code>raspberry-pi-2</code>
| No official binary cache. The profile targets 32-bit ARMv7 and enables OpenSSH by default. Later BCM2837-based revisions can run AArch64, but there is no dedicated 64-bit profile.
|-
|-
| Raspberry Pi 1 Model B
| Raspberry Pi Zero 2 W
|rowspan="5" style="vertical-align: middle;"| armv6
| AArch64
| C
| Generic AArch64 SD image
| None
| The image contains Zero 2 W boot files, but there is no dedicated board profile.
|-
|-
| Raspberry Pi 1 Model A+
| [[NixOS on ARM/Raspberry Pi 3|Raspberry Pi 3]]
| C*
| AArch64
| Generic AArch64 SD image
| <code>raspberry-pi-3</code>
| ARMv7 is a best-effort alternative.
|-
|-
| Raspberry Pi 1 Model B+
| [[NixOS on ARM/Raspberry Pi 4|Raspberry Pi 4, Pi 400, and CM4]]
| C
| AArch64
| Generic AArch64 SD image
| <code>raspberry-pi-4</code>
| The profile includes optional modules for several peripherals and HATs.
|-
|-
| Raspberry Pi Zero
| [[NixOS on ARM/Raspberry Pi 5|Raspberry Pi 5, Raspberry Pi 500, Raspberry Pi 500+, and Compute Module 5]]
| C*
| AArch64
|-
| Generic AArch64 SD image on unstable
| Raspberry Pi Zero W
| <code>raspberry-pi-5</code>
| C
| NixOS 26.05 images do not include the Pi 5 boot files. Use an image from <code>nixos-unstable</code>.<ref name="pi5-image">[https://github.com/NixOS/nixpkgs/pull/537862 nixpkgs PR #537862: sd-image-aarch64: support rpi5]</ref>
|-
!colspan="3" style="text-align: left;"|Raspberry Pi 2
|-
| Raspberry Pi 2 Model B
| armv7
| C
|-
!colspan="3" style="text-align: left;"|Raspberry Pi 3
|-
| Raspberry Pi 3 Model B
|rowspan="3" style="vertical-align: middle;"| AArch64<br /> ''+ armv7''
| YES
|-
| Raspberry Pi 3 Model B+
| YES
|-
| Raspberry Pi 3 Model A+
| ?
|-
!colspan="3" style="text-align: left;"|Raspberry Pi 4
|-
| Raspberry Pi 4 Model B
| AArch64<br /> ''+ armv7''
| YES
|-
!colspan="3" style="text-align: left;"|Raspberry Pi 400
|-
| Raspberry Pi 400
| AArch64<br /> ''+ armv7''
| Yes (only with kernel >= 6.1)
|-
! colspan="3" |Raspberry Pi 5
|-
|Raspberry Pi 5
|AArch64<br /> ''+ armv7''
|C*
|}
|}


''Support''
Peripheral support depends on the selected kernel, device tree, firmware, and board revision.
* YES: Supported architecture by Nixpkgs downstream and tested to be working.
* C: Community supported, and tested to be working.
* C*: Community supported, unverified but should be working.
* ? : Unverified, unknown if it will work.


The Raspberry Pi 3 Family is only supported as '''AArch64'''. Use as armv7 is community supported.
== Installation ==


== Board-specific installation notes ==
=== Generic AArch64 image ===


First follow the [[NixOS_on_ARM#Installation|generic installation steps]] to get the installer image and install using the [[NixOS_on_ARM#NixOS_installation_.26_configuration|installation and configuration steps]].
For the Zero 2 W, Pi 3, and Pi 4 families, download a current AArch64 SD image from the [[NixOS on ARM/Installation#SD card images (SBCs and similar platforms)|ARM installation page]]. For Pi 5, use a <code>nixos-unstable</code> image containing PR #537862. NixOS 26.05 images do not contain the required boot files.<ref name="pi5-image" /> The standard installation path uses an ARM SD image rather than the PC-oriented NixOS ISO. UEFI is a separate advanced setup.


=== Raspberry Pi (1) ===
Write the decompressed image to a microSD card as described on the ARM installation page. Check the destination device carefully because writing the image erases it. The SD image contains a mutable NixOS system, so after the first boot you can create a configuration and use <code>nixos-rebuild</code> without running a separate installer.


The ARMv6 image boots out-of-the-box.
The stock image uses the generic NixOS kernel. Import a board profile if you need the Raspberry Pi downstream kernel or the board-specific options described below.


=== Raspberry Pi 2 ===
=== Custom SD image ===


The ARMv7 image should boot out-of-the-box, though the author hasn't personally tested this.
A custom image can combine the Nixpkgs AArch64 image module with a <code>nixos-hardware</code> profile. When a custom image imports both modules, the profile's firmware module replaces the stock firmware population hook. Enable U-Boot explicitly so that the image contains <code>u-boot.bin</code> and the corresponding <code>kernel=</code> entry in <code>config.txt</code>.


=== Raspberry Pi 3 / 3B+ ===
<syntaxhighlight lang="nix">
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nixos-hardware = {
      url = "github:NixOS/nixos-hardware/master";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };


Both the AArch64 and ARMv7 images boot out-of-the-box. Using the 64-bit AArch64 image is highly recommended, as the availability of binaries is much better and allows the use of the 64-bit instruction set.
  outputs = { nixpkgs, nixos-hardware, ... }: {
 
    nixosConfigurations.rpi4-image = nixpkgs.lib.nixosSystem {
For the UART console, edit <code>/extlinux/extlinux.conf</code> on the boot partition of the SD card to set <code>console=ttyS1,115200n8</code> in the kernel boot parameters, and use the following GPIO Pins with an USB-TTL connector:
      system = "aarch64-linux";
<syntaxhighlight>
      modules = [
GND         - 3rd in top row, black cable
        "${nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
GPIO 14 TXD - 4th in top row, white cable
         nixos-hardware.nixosModules.raspberry-pi-4
GPIO 15 RXD - 5th in top row, green cable
        ({ lib, ... }: {
</syntaxhighlight>
          # The pinned Raspberry Pi kernel does not build the ZFS module.
Use <code>nix-shell -p screen --run "screen /dev/ttyUSB0 115200"</code> to connect to the console.  
          boot.supportedFilesystems.zfs = lib.mkForce false;
{{note|The mainline kernel (tested with nixos kernel 4.18.7) [https://github.com/raspberrypi/linux/wiki/Upstreaming#downstream-drivers does not include support for cpu frequency scaling] on the Raspberry Pi. To get higher clock speed, set [https://www.raspberrypi.org/documentation/configuration/config-txt/overclocking.md <code><nowiki>force_turbo=1</nowiki></code>] in <code>/boot/config.txt</code> }}
          hardware.raspberry-pi.firmware.uboot.enable = true;
 
        })
<syntaxhighlight lang=nix>
        ./configuration.nix
{
      ];
  hardware.enableRedistributableFirmware = true;
    };
   networking.wireless.enable = true;
   };
}
}
</syntaxhighlight>
</syntaxhighlight>


==== HDMI output issue with kernel 5.4 (NixOS 20.03 or NixOS unstable) ====
Build <code>nixosConfigurations.rpi4-image.config.system.build.sdImage</code>. The ZFS override stops the base NixOS image profile from building an incompatible out-of-tree module. This ext4 image does not use ZFS. A system that requires ZFS must select a kernel supported by the packaged ZFS module.


(Unverified for 5.5 or 5.6)
A board profile does not define a disk layout. Its firmware population step supports cross-compilation, but support in other packages varies.<ref name="cross-image">[https://github.com/NixOS/nixos-hardware/pull/1945 nixos-hardware PR #1945: fix cross-compiled SD images]</ref>


Some users have reported that the 5.4 kernel "hung at Starting kernel..." {{issue|82455}}. In all cases where it was possible to investigate, it was found that the device did boot, but that the HDMI out didn't function as expected.
== Board profiles ==


It looks like it may be a setup-dependent issue, as a 20.03 image with 5.4 was verified as working.
The flake module names are:


If your setup is having the issue, first report on {{issue|82455}} with the Raspberry Pi model (important to note whether it is a plus or non-plus) and the kind of display used with the HDMI out, including whether it is using adapters or not.
{| class="wikitable"
! Board
! Flake module
! Channel import
|-
| Raspberry Pi 2
| <code>nixos-hardware.nixosModules.raspberry-pi-2</code>
| <code>&lt;nixos-hardware/raspberry-pi/2&gt;</code>
|-
| Raspberry Pi 3
| <code>nixos-hardware.nixosModules.raspberry-pi-3</code>
| <code>&lt;nixos-hardware/raspberry-pi/3&gt;</code>
|-
| Raspberry Pi 4
| <code>nixos-hardware.nixosModules.raspberry-pi-4</code>
| <code>&lt;nixos-hardware/raspberry-pi/4&gt;</code>
|-
| Raspberry Pi 5
| <code>nixos-hardware.nixosModules.raspberry-pi-5</code>
| <code>&lt;nixos-hardware/raspberry-pi/5&gt;</code>
|}


Then, you can work around the issue by configuring your system to use the 4.19 kernel (previous LTS) using one of the following tricks.
A flake configuration for a Pi 4 can import the profile as follows:


# Use the serial console to configure the system, and <code>nixos-rebuild boot</code> it.
<syntaxhighlight lang="nix">
# Use a 19.09 image, specify the kernel in its configuration and upgrade to 20.03
# Boot the image, poweroff blindly using a keyboard, edit on another computer <code>/home/nixos/.ssh/authorized_keys</code> from the SD to add your key file, chmod as 600, unmount, boot the Raspberry Pi and find it on your network by some means.
 
<syntaxHighlight>
{
{
   boot.kernelPackages = pkgs.linuxPackages_4_19;
   inputs = {
}
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
</syntaxHighlight>
    nixos-hardware = {
      url = "github:NixOS/nixos-hardware/master";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };


=== Raspberry Pi 4 ===
  outputs = { nixpkgs, nixos-hardware, ... }: {
''See'' [[NixOS on ARM/Raspberry Pi 4]]
     nixosConfigurations.rpi4 = nixpkgs.lib.nixosSystem {
 
      system = "aarch64-linux";
=== Raspberry Pi 5===
      modules = [
''See'' [[NixOS on ARM/Raspberry Pi 5]]
        nixos-hardware.nixosModules.raspberry-pi-4
 
        ./configuration.nix
== Audio ==
       ];
 
In addition to the usual config, it might be required to enable audio support explicitly in the firmwareConfig.
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
  sound.enable = true;
  hardware.pulseaudio.enable = true;
 
  boot.loader.raspberryPi.firmwareConfig = ''
    dtparam=audio=on
  '';
</nowiki>}}
 
== Serial console==
 
Your <code>configuration.nix</code> will need to add <code>console=ttyS1,115200n8</code> to the <code>boot.kernelParams</code> configuration to use the serial console.
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{ config, pkgs, lib, ... }:
{
  boot.kernelParams = [
     "console=ttyS1,115200n8"
  ];
}
</nowiki>}}
 
If the Raspberry Pi downstream kernel is used the serial interface is named <code>serial0</code> instead.
 
== Bluetooth ==
 
The bluetooth controller is by default connected via a UART device (<code>/dev/ttyAMA0</code> on the RPi4) and needs to be enabled through <code>btattach</code>:
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{ pkgs, ... }:
{
  systemd.services.btattach = {
    before = [ "bluetooth.service" ];
    after = [ "dev-ttyAMA0.device" ];
    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
       ExecStart = "${pkgs.bluez}/bin/btattach -B /dev/ttyAMA0 -P bcm -S 3000000";
     };
     };
   };
   };
}
}
</nowiki>}}
</syntaxhighlight>


== Camera ==
With channels, add <code>nixos-hardware</code> and import the matching path:


For the camera to work, you will need to add the following code to your configuration.nix:
<syntaxhighlight lang="nix">
 
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{ config, pkgs, lib, ... }:
{
{
   boot.loader.raspberryPi.enable = true;
   imports = [
  # Set the version depending on your raspberry pi.
    <nixos-hardware/raspberry-pi/4>
  boot.loader.raspberryPi.version = 3;
   ];
  # We need uboot
  boot.loader.raspberryPi.uboot.enable = true;
  # These two parameters are the important ones to get the
  # camera working. These will be appended to /boot/config.txt.
  boot.loader.raspberryPi.firmwareConfig = ''
    start_x=1
    gpu_mem=256
   '';
}
}
</nowiki>}}
</syntaxhighlight>
{{note| A reboot is required to load the new firmware configuration.}}
 
To make the camera available as v4l device under <code>/dev/video0</code> the <code>bcm2835-v4l2</code> kernel module need to be loaded. This can be done by adding the following code to your configuration.nix:


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
Pin the <code>nixos-hardware</code> revision with the rest of the system inputs rather than following its moving <code>master</code> branch indefinitely.
{ config, pkgs, lib, ... }:
{
  boot.kernelModules = [ "bcm2835-v4l2" ];
}
</nowiki>}}
== Binary Cache ==
 
Depending on the architecture used, binary caches availability varies. Binary caches instructions are on the main [[NixOS on ARM#Binary cache|NixOS on ARM]] page. The following table describes the architectures supported by each board.  
 
{|class="wikitable"
|-
! Raspberry Pi 1
| armv6
|-
! Raspberry Pi 2
| armv7
|-
!rowspan="2" style="vertical-align: middle;"|Raspberry Pi 3
| armv7
|-
| AArch64
|-
!rowspan="2" style="vertical-align: middle;"|Raspberry Pi 4
| armv7
|-
| AArch64
|}


== Kernel selection ==
The stock image enables redistributable firmware. The Pi 4 profile also installs a pinned Wi-Fi and Bluetooth firmware package. The Pi 3 and Pi 5 profiles do not add wireless firmware themselves, so a custom system based only on either profile may need <code>hardware.enableRedistributableFirmware</code> or an explicit firmware package.


By default NixOS uses the official Linux kernel released by kernel.org (a "mainline" kernel, e.g. <code>pkgs.linuxPackages</code>). This works fine on a Raspberry Pi, and is the better-tested option.
== Boot process ==


It is also possible to use a kernel released by the Raspberry Pi Foundation (a "vendor" kernel, e.g. <code>pkgs.linuxPackages_rpi3</code>). This may be preferable if you're using an add-on board that the mainline kernel does not have drivers for.
The official AArch64 image uses this path:


You can select your kernel by setting <code>boot.kernelPackages</code>.
<code>ROM or EEPROM &rarr; Raspberry Pi firmware &rarr; U-Boot &rarr; extlinux.conf &rarr; NixOS generation</code>


== Notes about the boot process ==
The Raspberry Pi firmware reads the FAT firmware partition and starts U-Boot. <code>boot.loader.generic-extlinux-compatible</code> generates the <code>extlinux.conf</code> file that U-Boot reads. Its entries provide the NixOS generation menu and rollback support.


The Raspberry Pi's stage 1 bootloader (in ROM) loads the stage 2 bootloader (bootcode.bin) from the first VFAT partition on the SD card. The NixOS aarch64 SD card image includes a VFAT partition (labelled <code>FIRMWARE</code>) with the stage 2 bootloader and configuration that loads U-Boot. U-Boot then continues from the second partition (labelled <code>NIXOS_SD</code>).
Board profiles enable extlinux generation and import the Raspberry Pi firmware module. They do not define a disk layout. When an <code>sdImage</code> module is also imported, the firmware module populates the image's firmware partition automatically. Include U-Boot by setting <code>hardware.raspberry-pi.firmware.uboot.enable</code>. On a running system, firmware-partition updates require <code>hardware.raspberry-pi.firmware.enable</code>.


It takes approximately 1 minute to boot a Pi 3B.
The <code>nixos-hardware</code> repository does not provide a <code>boot.loader.raspberry-pi</code> module for direct firmware-to-kernel boot. Its firmware module supplies files for the existing U-Boot and extlinux path.<ref name="firmware-source">[https://github.com/NixOS/nixos-hardware/blob/master/raspberry-pi/common/firmware.nix nixos-hardware firmware module source]</ref>


There are 2 primary options for booting a Raspberry Pi:
== Firmware partition ==


=== Boot option 1: <code>boot.loader.generic-extlinux-compatible</code> ===
The <code>hardware.raspberry-pi.firmware</code> module installs Raspberry Pi boot firmware, device trees, overlays, a rendered <code>config.txt</code>, and optionally U-Boot. Custom images use it at build time. On a running system, it acts only when <code>hardware.raspberry-pi.firmware.enable</code> is true. The option is disabled by default.


This configuration is the most similar to the way that NixOS works on other devices. The downside is that NixOS won't attempt to manage anything associated with the first and second stage bootloaders (e.g. config.txt).
The stock generic image instead uses the static Nixpkgs firmware population hook. Later <code>nixos-rebuild</code> operations do not refresh its FAT partition. Enable the firmware module when the partition contents must follow the system configuration.


You can feel better about this by thinking about this configuration as similar to BIOS settings.
To manage the partition during <code>nixos-rebuild switch</code>, mount its FAT filesystem at <code>/boot/firmware</code> and enable both firmware installation and U-Boot:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
boot.loader.grub.enable = false;
{
boot.loader.generic-extlinux-compatible.enable = true;
  hardware.raspberry-pi.firmware = {
    enable = true;
    uboot.enable = true;
  };
}
</syntaxhighlight>
</syntaxhighlight>


=== Boot option 2: <code>boot.loader.raspberryPi</code> ===
Set <code>hardware.raspberry-pi.firmware.path</code> if the partition is mounted elsewhere. The activation script checks that the path is a mount point and skips the update with a warning if it is not mounted.


{{warning| This option has been deprecated in https://github.com/NixOS/nixpkgs/pull/241534}}
{{warning|The firmware module owns the files it copies. On every switch it replaces <code>config.txt</code>, copied device trees, copied overlays, and selected GPU firmware files. It removes stale <code>*.dtb</code> files from the partition root and unrecognised entries under <code>overlays/</code>. Do not keep manual changes or unrelated overlay files in those locations.}}


This configuration assumes that the VFAT firmware partition is mounted to /boot. If it isn't, options like <code>boot.loader.raspberryPi.firmwareConfig</code> will write their configuration to the wrong partition and have no effect.
The default U-Boot package is <code>pkgs.ubootRaspberryPiAarch64</code>, which covers the 64-bit profiles. A 32-bit Pi 2 configuration must select its matching package:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
boot.loader.grub.enable = false;
{ pkgs, ... }:
boot.loader.raspberryPi.enable = true;
{
boot.loader.raspberryPi.uboot.enable = true;
  hardware.raspberry-pi.firmware.uboot = {
    enable = true;
    package = pkgs.ubootRaspberryPi2;
  };
}
</syntaxhighlight>
</syntaxhighlight>


=== Raspberry Pi (all versions) ===
This module updates files on the firmware partition. It does not create partitions and does not update the Pi 4 or Pi 5 bootloader EEPROM.
 
USB keyboards and HDMI displays should work, though some issues have been reported (see Troubleshooting below).
 
Using the 3.3v serial port via the pin headers (exact location depends on hardware version) will get u-boot output and, when configured, a Linux kernel console.
 
== Device trees ==


Raspberry Pi add-on hardware often requires a device tree overlay. On other OSes this is usually set up using a <code>dtoverlay=</code> option in config.txt on the firmware partition. This approach can be made to work on NixOS with some combination of bootloader and kernel, but it may be easier and more explicit to use NixOS' <code>hardware.deviceTree</code> option to compile the overlay directly into the device tree.
== Declarative config.txt ==


A device tree config looks something like this:
Board profiles generate <code>config.txt</code> from <code>hardware.raspberry-pi.configtxt.settings</code>.<ref name="config-source">[https://github.com/NixOS/nixos-hardware/blob/master/raspberry-pi/common/config-txt.nix nixos-hardware config.txt module source]</ref> Top-level attributes are Raspberry Pi conditional filters such as <code>all</code>, <code>pi4</code>, <code>pi5</code>, and <code>cm4</code>. Lists render the same key more than once.


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
hardware.deviceTree = {
{ lib, ... }:
     enable = true;
{
    overlays = [
  hardware.raspberry-pi.configtxt.settings = {
      {
     all = {
         name = "hifiberry-dacplus";
      dtparam = [
         dtsText = ''
         "audio=on"
/dts-v1/;
         "i2c_arm=on"
/plugin/;
      ];
/ {
      dtoverlay = [
      compatible = "brcm,bcm2835";
        "vc4-kms-v3d"
 
        "disable-bt"
// ... etc.
      ];
'';
      arm_boost = lib.mkForce null;
      };
    };
     ];
     pi5.arm_freq = 2400;
   };
   };
}
</syntaxhighlight>
</syntaxhighlight>


This will apply the overlay to all <code>.dtb</code> files with a matching <code>compatible</code> line.
Booleans render as <code>1</code> or <code>0</code>. Use <code>lib.mkForce null</code> to remove a default. An ordinary assignment supersedes the profile's lower-priority <code>mkDefault</code> list, while equal-priority list definitions may concatenate. Retain any default entries that are still required. To provide a complete custom file instead, set <code>hardware.raspberry-pi.configtxt.file</code> to a path.


After rebooting you can check if the overlay has been applied by looking for it in the output of <code>dtc --sort /proc/device-tree</code>.
Changes reach a running board only when an image builder or the enabled firmware module writes the generated file to the mounted firmware partition.


dtoverlay may fail with <code>FDT_ERR_NOTFOUND</code> on some Raspberry Pi device tree overlays. In this case dtmerge should be used instead. There is a Nix overlay to use dtmerge for applying device tree overlays: https://github.com/NixOS/nixos-hardware/blob/429f232fe1dc398c5afea19a51aad6931ee0fb89/raspberry-pi/4/apply-overlays-dtmerge.nix
== Kernels and device trees ==


== Troubleshooting ==
The generic AArch64 image uses the generic NixOS kernel. The <code>nixos-hardware</code> profiles instead select a pinned kernel from Raspberry Pi's downstream Linux tree. The downstream kernel may support Raspberry Pi-specific hardware that the mainline kernel does not. The mainline kernel follows the normal NixOS update and maintenance path. Choose the kernel that supports the required hardware and test it on the target board.


=== Power issues ===
Two mechanisms apply device-tree overlays:


Especially with the power-hungry Raspberry Pi 3, it is important to have a [https://www.raspberrypi.org/documentation/hardware/raspberrypi/power/README.md sufficient enough power supply] or unexpected behaviour may occur; this may include:
* <code>hardware.raspberry-pi.configtxt.settings</code> asks the Raspberry Pi firmware to apply overlays at boot.
* <code>hardware.deviceTree.overlays</code> merges overlays into kernel device trees while building the system.


* Lightning bolt on HDMI output "breaking" the display.
The mechanisms can conflict. Loading a generation device tree can discard firmware overlays and runtime fixups, whereas retaining the firmware-provided tree can omit build-time overlays. [https://github.com/NixOS/nixos-hardware/issues/1946 nixos-hardware issue #1946] tracks work on a single firmware-managed mechanism. Test configurations that use both mechanisms and verify the final device tree seen by Linux.
* Screen switching back to u-boot text
** Fixable temporarily when power is sufficient by switching VT (alt+F2 / alt+F1)
* Random hangs


This is a hard problem. It is caused by the Raspberry Pi warning about power issues, but the current drivers (as of
== Operational notes ==
Linux 4.14) have a hard time dealing with it properly. If the power supply is rated properly AND the cable is not incurring too much power losses, it may be required to disable the lightning bolt indicator so the display driver isn't messed up.<ref>https://logs.nix.samueldr.com/nixos/2017-12-20#1513784657-1513784714;</ref> The lightning bolt indicator can be disabled by adding the line <code>avoid_warnings=1</code> in config.txt<ref>https://www.raspberrypi.org/documentation/configuration/config-txt/README.md</ref>


{{note|A ''properly rated'' USB power supply, AND a good cable are necessary. The cable has to be short enough to not incur power losses through the length. Do note that thin and cheap cables usually have thinner copper wires, which in turn accentuates power losses.}}
=== EEPROM updates ===


===WiFi / WLAN===
Pi 4 and Pi 5 use a rewritable bootloader EEPROM. Its version and boot order affect USB, network, and NVMe boot behaviour. Use the <code>raspberrypi-eeprom</code> package and follow the [https://www.raspberrypi.com/documentation/computers/configuration.html#update-bootloader-version official Raspberry Pi bootloader update instructions]. Point <code>BOOTFS</code> at the mounted firmware partition when the tool cannot find it automatically.
For a possible solution to 802.11 wireless connectivity issues, see: https://github.com/NixOS/nixpkgs/issues/82462#issuecomment-604634627


===HDMI===
Updating the EEPROM alone does not provide the complete NixOS boot chain. Released U-Boot 2026.07 cannot read a Pi 5 NVMe device during the extlinux stage. The Pi 5 page describes this limitation.


HDMI issues have been observed on the 18.09 AArch64 image. The display would hang on "Starting Kernel...", then act as if the HDMI cable was unplugged. Re-plugging the HDMI cable after boot fixed the issue, as did a different monitor and HDMI cable.
=== Wi-Fi power saving ===


==== Early boot messages ====
If a board becomes slow or unreachable over Wi-Fi, disable NetworkManager power saving and test again:


To show boot messages from initrd with the mainline kernel, add this to <code>configuration.nix</code>.
<syntaxhighlight lang="nix">
 
<syntaxhighlight lang=nix>
{
{
   boot.initrd.kernelModules = [ "vc4" "bcm2835_dma" "i2c_bcm2835" ];
   networking.networkmanager.wifi.powersave = false;
}
}
</syntaxhighlight>
</syntaxhighlight>


=== Raspberry Pi 3B+ HDMI output issues ===
=== Power supply ===
 
Undervoltage can cause storage errors, USB resets, display failures, or unexpected reboots. Use a supply and cable rated for the board and attached peripherals. See the [https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#power-supply Raspberry Pi power-supply documentation].
 
=== No output after U-Boot ===
 
<code>Starting kernel ...</code> is normally the last message printed by U-Boot. If the system continues to boot without visible kernel messages, check the kernel <code>console=</code> parameters. Add <code>console=tty0</code> for display output or configure the serial console used by the board.
 
== Alternative implementations ==
 
The [https://github.com/nvmd/nixos-raspberrypi nvmd/nixos-raspberrypi] project is a separate community implementation for Zero 2 W and Raspberry Pi 3, 4, and 5. It publishes images and a binary cache. Its direct firmware-to-kernel boot path uses matched kernel and firmware bundles. Pi 5-specific modules include separate VC4 and RP1 display paths. Its module API and bootloader are not part of Nixpkgs or <code>nixos-hardware</code>.


As of 2019/08/19, the u-boot build and kernel build can disagree about the name of the dtb file for the Raspberry Pi 3B+. This happens because the upstream filename has changed, and the built u-boot has hardcoded expectations for the filename to load.
The [https://github.com/nix-community/raspberry-pi-nix nix-community/raspberry-pi-nix] community implementation was archived in March 2025 and is now read-only. For third-party UEFI firmware on Pi 5, see the [[NixOS on ARM/Raspberry Pi 5#UEFI|Pi 5 UEFI notes]].


For now, do not use <tt>linuxPackages_latest</tt>, use the default <tt>linuxPackages</tt> which is the latest LTS, 4.19, which is known to be compatible.
== See also ==


See {{issue|66960}}.
* [[NixOS on ARM/Installation]]
* [[NixOS on ARM/Building Images]]
* [[U-Boot#Using NixOS with U-Boot|Using NixOS with U-Boot]]
* [https://www.raspberrypi.com/documentation/computers/config_txt.html Raspberry Pi <code>config.txt</code> documentation]


===Additional Troubleshooting===
== References ==


Additional troubleshooting information may be found [https://elinux.org/R-Pi_Troubleshooting at elinux.org].
<references />


<hr />
[[Category:NixOS on ARM]]