Cannot get ZFS module to automatically load

No matter what I try, I cannot get the zfs-rollback service to not fail with the error “The ZFS modules cannot be auto-loaded.” This is the configuration I have regarding the boot sequence:

let
  zfsCompatibleKernelPackages = lib.filterAttrs (
    name: kernelPackages:
    (builtins.match "linux_[0-9]+_[0_9]+" name) != null
    && (builtins.tryEval kernelPackages).success
    && (!kernelPackages.${config.boot.zfs.package.kernelModuleAttribute}.meta.broken)
    ) pkgs.linuxKernel.packages;
    latestKernelPackage = lib.last (
      lib.sort (a: b: (lib.versionOlder a.kernel.version b.kernel.version)) (
      builtins.attrValues zfsCompatibleKernelPackages
      )
    );
in
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  nix = {
    settings = {
      experimental-features = [ "nix-command" "flakes" ];
      auto-optimise-store = true;
    };
    gc = {
      automatic = true;
      dates = "weekly";
      options = "--delete-older-than 7d";
    };
  };
  # Use the systemd-boot EFI boot loader.
  boot = {
    kernelPackages = latestKernelPackage;
    kernelModules = [ "zfs" ];
    supportedFilesystems = [ "zfs" "fat32" "exfat" ];
    initrd = {
      kernelModules = [ "zfs" ];
      supportedFilesystems = [ "zfs" "fat32" "exfat" ];
      systemd = {
      enable = true;
      services = {
        zfs-rollback = {
          description = "Rollback ZFS root to blank state (Impermanence setup)";
          wantedBy = [ "initrd.target" ];
          after = [ "zfs-import-zroot.service" ];
          before = [ "sysroot.mount" ];
          path = with pkgs; [
            zfs
          ];
          unitConfig.DefaultDependencies = "no";
          serviceConfig.Type = "oneshot";
          script = ''
            zfs rollback -r zroot/local/root@blank && echo "zfs rollback complete"
          '';
        };
      };
    };
    };
    zfs.forceImportRoot = false;
    loader.grub = {
      enable = true;
      zfsSupport = true;
      efiSupport = true;
      mirroredBoots = [
        {devices = [ "nodev" ]; path = "/boot"; }
      ];
    };
  };

Any idea what might be the problem? Between only using compatible kernels, adding to the boot and initrd kernel modules, and the initrd and boot supported filesystems, I really don’t know what else I could change to force the module to be loaded

I tried to make a VM with a config as close as possible to that, but am not reproducing such an error: configuration.nix · GitHub Are there other differences in your config that might be relevant?

Huh, what a mess I got myself in if its not one of those options that blocking it. Heres the full configuration:


{ config, lib, inputs, pkgs, ... }:

let
  zfsCompatibleKernelPackages = lib.filterAttrs (
    name: kernelPackages:
    (builtins.match "linux_[0-9]+_[0_9]+" name) != null
    && (builtins.tryEval kernelPackages).success
    && (!kernelPackages.${config.boot.zfs.package.kernelModuleAttribute}.meta.broken)
    ) pkgs.linuxKernel.packages;
    latestKernelPackage = lib.last (
      lib.sort (a: b: (lib.versionOlder a.kernel.version b.kernel.version)) (
      builtins.attrValues zfsCompatibleKernelPackages
      )
    );
in
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  nixpkgs.config.allowUnfree = true;
  nix = {
    settings = {
      experimental-features = [ "nix-command" "flakes" ];
      auto-optimise-store = true;
    };
    gc = {
      automatic = true;
      dates = "weekly";
      options = "--delete-older-than 7d";
    };
  };
  # Use the systemd-boot EFI boot loader.
  boot = {
    kernelPackages = latestKernelPackage;
    kernelModules = [ "zfs" ];
    supportedFilesystems = [ "zfs" "fat32" "exfat" ];
    initrd = {
      kernelModules = [ "zfs" ];
      supportedFilesystems = [ "zfs" "fat32" "exfat" ];
      systemd = {
      enable = true;
      services = {
        zfs-rollback = {
          description = "Rollback ZFS root to blank state (Impermanence setup)";
          wantedBy = [ "initrd.target" ];
          after = [ "zfs-import-zroot.service" ];
          before = [ "sysroot.mount" ];
          path = with pkgs; [
            zfs
          ];
          unitConfig.DefaultDependencies = "no";
          serviceConfig.Type = "oneshot";
          script = ''
            zfs rollback -r zroot/local/root@blank && echo "zfs rollback complete"
          '';
        };
      };
    };
    };
    zfs.forceImportRoot = false;
    loader.grub = {
      enable = true;
      zfsSupport = true;
      efiSupport = true;
      mirroredBoots = [
        {devices = [ "nodev" ]; path = "/boot"; }
      ];
    };
  };

  hardware = {
    enableRedistributableFirmware = true;
    cpu.amd.updateMicrocode = true;
    bluetooth.enable = true;
    graphics = {
      enable = true;
      enable32Bit = true;
    };
  };

  fonts = {
    fontconfig = {
      useEmbeddedBitmaps = true;
      enable = true;
    };
    fontDir.enable = true;
  };
  #boot.loader.systemd-boot.enable = true;
  #boot.loader.efi.canTouchEfiVariables = true;

  gtk = {
    iconCache.enable = true;
  };

  xdg = {
    terminal-exec.enable = true;
    icons.enable = true;
    mime = {
      enable = true;
    };
    portal = {
      enable = true;
      wlr.enable = true;
    };
  };

  security = {
    polkit.enable = true;
  };
  networking = {
    hostId = "a359e14e";
    hostName = "nixos"; # Define your hostname.
    networkmanager = {
      enable = true;
      ensureProfiles = {
        profiles = {
          homeWifi = {
            connection = {
              id = "homeWifi";
              uuid = "6ec13bc2-5ebf-4c4e-a923-8d336c3e5cb4";
              type = "wifi";
              interface-name = "wlp191s0";
            };
            wifi = {
              mode = "infrastructure";
              ssid = "6GHz TV/Game UByFBqDXGMJDybf";
            };
            wifi-security = {
              auth-alg = "open";
              key-mgmt = "wpa-psk";
              psk = (builtins.readFile ./homeWifiPsk);
            };
            ipv4 = {
              method = "auto";
            };
            ipv6 = {
              addr-gen-mode = "default";
              method = "auto";
            };
          };
        };
      };
    };
  };

  # Configure network connections interactively with nmcli or nmtui.

  # Set your time zone.
  # time.timeZone = "Europe/Amsterdam";

  # Configure network proxy if necessary
  # networking.proxy.default = "http://user:password@proxy:port/";
  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";

  # Select internationalisation properties.
  # i18n.defaultLocale = "en_US.UTF-8";
  # console = {
  #   font = "Lat2-Terminus16";
  #   keyMap = "us";
  #   useXkbConfig = true; # use xkb.options in tty.
  # };

  # Enable the X11 windowing system.
  services = {
    xserver.enable = true;
    libinput.enable = true;
    dbus = {
      implementation = "broker";
      enable = true;
    };
    blueman.enable = true;
    chrony = {
      enable = true;
      enableNTS = true;
      servers = [ "virginia.time.system76.com" ];
    };
    pipewire = {
      enable = true;
      alsa.enable = true;
      alsa.support32Bit = true;
      pulse.enable = true;
      jack.enable = true;
      wireplumber.enable = true;
    };
    zfs.autoScrub.enable = true;
  };


  

  # Configure keymap in X11
  # services.xserver.xkb.layout = "us";
  # services.xserver.xkb.options = "eurosign:e,caps:escape";

  # Enable CUPS to print documents.
  # services.printing.enable = true;

  # Enable sound.
  # services.pulseaudio.enable = true;
  # OR
  # services.pipewire = {
  #   enable = true;
  #   pulse.enable = true;
  # };

  # Enable touchpad support (enabled default in most desktopManager).
  # services.libinput.enable = true;
  users = {
    users.aqua = {
      isNormalUser = true;
      extraGroups = [ "wheel" "networkmanager" "networking" "adm" ];
      hashedPasswordFile = "/etc/nixos/pw_file";
    };
  };
  # Define a user account. Don't forget to set a password with ‘passwd’.
  # users.users.alice = {
  #   isNormalUser = true;
  #   extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
  #   packages = with pkgs; [
  #     tree
  #   ];
  # };

  programs = {
    uwsm.enable = true;
    firefox.enable = true;
    hyprland = {
      enable = true;
      withUWSM = true;
      package = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.hyprland;
      portalPackage = inputs.hyprland.packages.${pkgs.stdenv.hostPlatform.system}.xdg-desktop-portal-hyprland;
    };
    dconf.enable = true;
    xwayland.enable = true;
  };

  # List packages installed in system profile.
  # You can use https://search.nixos.org/ to find more packages (and options).
  environment = {
    persistence."/persist" = {
      enable = true;
      hideMounts = true;
      directories = [
        "/etc/nixos"
        "/var/lib/nixos"
      ];
    };
    systemPackages = with pkgs; [
      hyprpaper
      hyprlock
      hypridle
      hyprpolkitagent
      fuzzel
      app2unit
      #xdg-terminal-exec
      zed-editor
      devenv
      ruffle
      blender
      rose-pine-cursor
      rose-pine-gtk-theme
      rose-pine-hyprcursor
      hyprcursor
      tor-browser
      zoom-us
      v4l-utils
      teams-for-linux
      kdePackages.okular
      brightnessctl
      gimp
      gnupg
      unrar
      mpv
      p7zip
      cmake
      ripgrep
      htop
      wineWow64Packages.stableFull
      wineWow64Packages.stagingFull
      winetricks
      protontricks
      texstudio
      texliveFull
      wl-clipboard
      kdePackages.dolphin
      firefox
      kitty
      vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
  #   wget
    ];
  };

  fileSystems."/" = {
    device = "zpool/local/root";
    fsType = "zfs";
  };
  
  fileSystems."/persist" = {
    device = "zpool/safe/persist";
    fsType = "zfs";
    neededForBoot = true;
  };

  fileSystems."/nix" = {
    device = "zpool/local/nix";
    fsType = "zfs";
  };

  fileSystems."/home/aqua/Documents" = {
    device = "zpool/safe/documents";
    fsType = "zfs";
  };
 
  fileSystems."/home/aqua/Desktop" = {
    device = "zpool/safe/desktop";
    fsType = "zfs";
  };
   
  fileSystems."/home/aqua/Music" = {
    device = "zpool/safe/music";
    fsType = "zfs";
  };

  fileSystems."/home/aqua/Downloads" = {
    device = "zpool/safe/downloads";
    fsType = "zfs";
  };

  fileSystems."/home/aqua/Videos" = {
    device = "zpool/safe/videos";
    fsType = "zfs";
  };

  fileSystems."/home/aqua/Pictures" = {
    device = "zpool/safe/pictures";
    fsType = "zfs";
  };

  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  # services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # Copy the NixOS configuration file and link it from the resulting system
  # (/run/current-system/configuration.nix). This is useful in case you
  # accidentally delete configuration.nix.
  # system.copySystemConfiguration = true;

  # This option defines the first version of NixOS you have installed on this particular machine,
  # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
  #
  # Most users should NEVER change this value after the initial install, for any reason,
  # even if you've upgraded your system to a new NixOS release.
  #
  # This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
  # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
  # to actually do that.
  #
  # This value being lower than the current NixOS release does NOT mean your system is
  # out of date, out of support, or vulnerable.
  #
  # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
  # and migrated your data accordingly.
  #
  # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
  system.stateVersion = "26.05"; # Did you read the comment?

}

I don’t think any thing else should be relevant, but I’m no nix expert. TBH, I’m 90% certain I’ve only gotten as far as I have because I’m a primarily a lisp programmer in my academic career and have just gotten lucky just squinting my eyes and trying to read it like its vaguely haskell

EDIT: This may actually matter, I’m using a framework 16 amd ai 300 series and I am using the nixos-hardware flake for it. I really hope its not the hardware support thats causing the bug…

So I have a fix. The first issue I fixed was that I actually had a misspelling that wasn’t being caught anywhere (I was using zroot and not zpool). So you may need to double check your spelling, because referencing services that don’t/shouldn’t exist doesn’t raise an obvious error? Fixing that didn’t solve my module loading though. Again, I have no idea why these fixes in particular were necessary, but adding the following

config.boot.extraModulePackages = [ config.boot.kernelPackages.zfs_2_4 ];

to the above config and swap the after portion of the service to

after = [ "systemd-modules-load.service" "zfs-import-zpool.service" ];

Seems to have fixed my system. If whoever reads this has a similar issue, you may find that you’re unable to login like I did because using a hashed password file doesn’t work for a reason I also don’t understand. A hashed password directly in the configuration does indeed work though, so theres that at least.

1 Like

Oh. Before you had zfs-import-zroot.service, not zfs-import-zpool.service. I see in your second comment that your fileSystems has e.g. device = "zpool/local/root";. So yea I think the whole issue was just that you ordered after zroot instead of zpool. The extraModulePackages and systemd-modules-load.service are not necessary.

2 Likes

Yeah that’s what I thought too but like I said I was still having issues with booting up after I fixed the typos. I agree with you that they shouldn’t be necessary, but I was still getting module loading errors with the proper names. I suspect theres still something “wrong" considering I just could not get the hashed password file to work, but I don’t want to spend more time on this, I can live with the hash being inside of my configuration file

I’m just saying, there’s no way that either the extraModulePackages or the After=systemd-modules-load.service are actually doing anything, because After=zfs-import-zpool.service intrinsically means the ZFS module has already successfully imported the pool. I am quite certain those can be removed.