Flake to create a simple SD image for RPI4 (cross)

I tried this:

boot.zfs.enabled = nixpkgs.lib.mkDefault false;

And got the same issue:

$ nix build .#packages.aarch64-linux.sdcard
error: The option `boot.zfs.enabled' is read-only, but it's set multiple times. Definition values:
       - In `/nix/store/kcmipm57ph9bpzz8bs80iiijiwbyzwy3-source/nixos/modules/tasks/filesystems/zfs.nix': true
       - In `/nix/store/kcmipm57ph9bpzz8bs80iiijiwbyzwy3-source/flake.nix': false
(use '--show-trace' to show detailed location information)

I also tried:

boot.supportedFilesystems = [ "ext4" ];

which didn’t trigger a rebuild, so it probably didn’t have any effect.

I answered both of those questions above. boot.zfs.enabled is readonly because it is merely indicative of whether ZFS is in supportedFilesystems, not prescriptive. Some of the installer modules do a kind of silly hack to cut ZFS out. You can copy that same trick. What you tried didn’t work because modules are merged and added, so you simply added ext4. You would have to mkForce that option to the exact list that you want. The silly hack in the installer modules is easier. I would like for this to be easier.

1 Like

But also, did you try the disabledModules idea I mentioned?

I think I saw that trick (hack) before, but I didn’t understand what it is doing.

I copied it now, and it a rebuild is happening, so it seems like it might work.

I haven’t gotten to the disableModules yet. Just wanted to start testing suggestions in chronological order :wink:

disableModules seems to work and is probably the nicest way to minimize the image.

For posterity sake, here is the full flake.nix, for a minimal system:

  description = "Base system for raspberry pi 4";
  inputs = {
    nixpkgs.url = "nixpkgs/nixos-unstable";
    nixos-generators = {
      url = "github:nix-community/nixos-generators";
      inputs.nixpkgs.follows = "nixpkgs";

  outputs = { self, nixpkgs, nixos-generators, ... }: 
    nixosModules = {
      system = {
        #boot.zfs.enabled = false; # error: The option `boot.zfs.enabled' is read-only, but it's set multiple times.
        #boot.zfs.enabled = nixpkgs.lib.mkDefault false; # error: The option `boot.zfs.enabled' is read-only, but it's set multiple times.
        #boot.supportedFilesystems = [ "ext4" ]; # Does not have any effect, because it only adds `ext4`, not deletes anything else from the array.

        # Copied from https://github.com/NixOS/nixpkgs/blob/f3565a2c088883636f198550eac349ed82c6a2b3/nixos/modules/installer/sd-card/sd-image-aarch64-new-kernel-no-zfs-installer.nix#L6 "
        # This works, however it is a hack:
        # Makes `availableOn` fail for zfs, see <nixos/modules/profiles/base.nix>.
        # This is a workaround since we cannot remove the `"zfs"` string from `supportedFilesystems`.
        # The proper fix would be to make `supportedFilesystems` an attrset with true/false which we
        # could then `lib.mkForce false`
        #nixpkgs.overlays = [(final: super: {
        #  zfs = super.zfs.overrideAttrs(_: {
        #    meta.platforms = [];
        #  });

        # Disabling the whole `profiles/base.nix` module, which is responsible
        # for adding ZFS and a bunch of other unnecessary programs:
        disabledModules = [

        system.stateVersion = "23.11";
      users = {
        users.users = {
          admin = {
            password = "admin";
            isNormalUser = true;
            extraGroups = [ "wheel" ];

    packages.aarch64-linux = {
      sdcard = nixos-generators.nixosGenerate {
        system = "aarch64-linux";
        format = "sd-aarch64";
        modules = [

I had some trouble cross-compiling because I had not read the section on cross-compiling in the README:

which says I need to set boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; in the host’s configuration.nix. This makes @pdevil’s examples of 2023-11-23 work.