Below is my minimal NixOS configuration for a Raspberry Pi 4B. It includes everything needed, ready to be loaded from a generic flake.nix.

First enable binfmt on your build machine:

boot.binfmt.emulatedSystems = [ "aarch64-linux" ];

Then build the SD card image with:

nix build '.#nixosConfigurations.YOUR_HOSTNAME.config.system.build.sdImage'

…and rebuild remotely with:

nixos-rebuild switch --flake .#YOUR_HOSTNAME --target-host RASPI_IP --use-remote-sudo

Below is the configuration.nix, with notes on how this all works after the fold:

{ lib, pkgs, modulesPath, ... }:
{
  imports = [
    # This module installs the firmware
    "${modulesPath}/installer/sd-card/sd-image-aarch64.nix"
  ];

  nix.settings = {
    # This is needed to allow building remotely
    trusted-users = [ "YOUR_USERNAME" ];

    # The nix-community cache has aarch64 builds of unfree packages,
    # which aren't in the normal cache
    substituters = [
      "https://nix-community.cachix.org"
    ];
    trusted-public-keys = [
      "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
    ];
  };

  nixpkgs = {
    hostPlatform = "aarch64-linux";
    config = {
      allowUnfree = true;
    };
  };

  # These options make the sd card image build faster
  boot.supportedFilesystems.zfs = lib.mkForce false;
  sdImage.compressImage = false;

  networking = {
    # Set your hostname
    hostName = "YOUR_HOSTNAME";
    useNetworkd = true;
  };

  # Replace networkd with NetworkManager at your discretion
  systemd = {
    network = {
      enable = true;

      networks."10-lan" = {
        # This is the correct interface name on my raspi 4b
        matchConfig.Name = "end0";

        networkConfig.DHCP = "yes";
        linkConfig.RequiredForOnline = "routable";
      };
    };
  };

  # Add your username and ssh key
  users.users.YOUR_USERNAME = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];
    openssh.authorizedKeys.keys = [ "YOUR_SSH_PUBLIC_KEY" ];
  };

  # Our user doesn't have a password, so we let them
  # do sudo without one
  security.sudo.wheelNeedsPassword = false;

  services = {
    openssh.enable = true;
  };

  # Set your timezone
  time.timeZone = "YOUR_TIMEZONE";

  environment.systemPackages = with pkgs; [
    libraspberrypi
    raspberrypi-eeprom
  ];

  hardware.enableRedistributableFirmware = true;

  system.stateVersion = "24.11";
}

Some notes:

sudo mkdir -p /boot/firmware
sudo mount /boot/firmware

and then edit config.txt normally. If you want to configure the firmware from nix, have a look at the raspberry-pi-nix flake. I haven’t tried it but it looks very swish.