Code change:
When multiple ZFS filesystems are present and configured to import, each individual attempts to load the keys for ALL pools/datasets, instead of just its own. A clear and concise description of what the bug is. Steps to reproduce the behavior: encrypted zfs filesystems in your NixOS configuration. & Reboot All targets complete successfully The below snippet from the services's script. It's 'ing, and just looping over all pools/datasets. Instead, it should just specify the name directly in the command. (Generated in ) Please run and paste the result. system: host os: multi-user?: sandbox: version: nixpkgs:
Can you post the relevant Nix config you used? Do you have set to anything?
Yep, here's my zfs config. uses (unlocked at boot) is unencrypted and have on-disk
Ok, I think this is fundamentally the same issue as . Basically, when there are multiple pools and is a list, we accidentally run with no dataset argument in the import service for pools that have no datasets in the list. So those services end up iterating over all datasets on all pools instead of none.

Related discussion:
text: makeTest { name = "zfs-" + name; meta = with pkgs.lib.maintainers; { <del> maintainers = [ adisbladis ]; </del> <ins> maintainers = [ adisbladis elvishjerricco ]; </ins> }; nodes.machine = { pkgs, lib, ... }: let usersharePath = "/var/lib/samba/usershares"; in { <del> virtualisation.emptyDiskImages = [ 4096 ]; </del> <ins> virtualisation = { emptyDiskImages = [ 4096 4096 ]; useBootLoader = true; useEFIBoot = true; }; boot.loader.systemd-boot.enable = true; boot.loader.timeout = 0; boot.loader.efi.canTouchEfiVariables = true; </ins> networking.hostId = "deadbeef"; boot.kernelPackages = kernelPackage; boot.supportedFilesystems = [ "zfs" ]; boot.zfs.enableUnstable = enableUnstable; <del> services.samba = { enable = true; extraConfig = '' registry shares = yes usershare path = ${usersharePath} usershare allow guests = yes usershare max shares = 100 usershare owner only = no ''; </del> <ins> environment.systemPackages = [ pkgs.parted ]; # /dev/disk/by-id doesn't get populated in the NixOS test framework boot.zfs.devNodes = "/dev/disk/by-uuid"; specialisation.samba.configuration = { services.samba = { enable = true; extraConfig = '' registry shares = yes usershare path = ${usersharePath} usershare allow guests = yes usershare max shares = 100 usershare owner only = no ''; }; systemd.services.samba-smbd.serviceConfig.ExecStartPre = "${pkgs.coreutils}/bin/mkdir -m +t -p ${usersharePath}"; virtualisation.fileSystems = { "/tmp/mnt" = { device = "rpool/root"; fsType = "zfs"; }; }; </ins> }; <del> systemd.services.samba-smbd.serviceConfig.ExecStartPre = "${pkgs.coreutils}/bin/mkdir -m +t -p ${usersharePath}"; environment.systemPackages = [ pkgs.parted ]; </del> <ins> specialisation.encryption.configuration = { boot.zfs.requestEncryptionCredentials = [ "automatic" ]; virtualisation.fileSystems."/automatic" = { device = "automatic"; fsType = "zfs"; }; virtualisation.fileSystems."/manual" = { device = "manual"; fsType = "zfs"; }; virtualisation.fileSystems."/manual/encrypted" = { device = "manual/encrypted"; fsType = "zfs"; options = [ "noauto" ]; }; }; </ins> <del> # Setup regular fileSystems machinery to ensure forceImportAll can be # tested via the regular service units. virtualisation.fileSystems = { "/forcepool" = { </del> <ins> specialisation.forcepool.configuration = { systemd.services.zfs-import-forcepool.wantedBy = lib.mkVMOverride [ "forcepool.mount" ]; systemd.targets.zfs.wantedBy = lib.mkVMOverride []; boot.zfs.forceImportAll = true; virtualisation.fileSystems."/forcepool" = { </ins> device = "forcepool"; fsType = "zfs"; options = [ "noauto" ]; }; }; <del> # forcepool doesn't exist at first boot, and we need to manually test # the import after tweaking the hostId. systemd.services.zfs-import-forcepool.wantedBy = lib.mkVMOverride []; systemd.targets.zfs.wantedBy = lib.mkVMOverride []; boot.zfs.forceImportAll = true; # /dev/disk/by-id doesn't get populated in the NixOS test framework boot.zfs.devNodes = "/dev/disk/by-uuid"; </del> }; testScript = '' <ins> machine.wait_for_unit("multi-user.target") </ins> machine.succeed( <del> "modprobe zfs", </del> "zpool status", <del> "ls /dev", "mkdir /tmp/mnt", "udevadm settle", "parted --script /dev/vdb mklabel msdos", "parted --script /dev/vdb -- mkpart primary 1024M -1s", "udevadm settle", "zpool create rpool /dev/vdb1", "zfs create -o mountpoint=legacy rpool/root", # shared datasets cannot have legacy mountpoint "zfs create rpool/shared_smb", "mount -t zfs rpool/root /tmp/mnt", "udevadm settle", # wait for samba services "systemctl is-system-running --wait", "zfs set sharesmb=on rpool/shared_smb", "zfs share rpool/shared_smb", "smbclient -gNL localhost | grep rpool_shared_smb", "umount /tmp/mnt", "zpool destroy rpool", "udevadm settle", </del> <ins> "parted --script /dev/vdc mklabel msdos", "parted --script /dev/vdc -- mkpart primary 1024M -1s", "parted --script /dev/vdd mklabel msdos", "parted --script /dev/vdd -- mkpart primary 1024M -1s", </ins> ) <del> machine.succeed( 'echo password | zpool create -o altroot="/tmp/mnt" ' + "-O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1", "zfs create -o mountpoint=legacy rpool/root", "mount -t zfs rpool/root /tmp/mnt", "udevadm settle", "umount /tmp/mnt", "zpool destroy rpool", "udevadm settle", ) </del> <ins> with subtest("sharesmb works"): machine.succeed( "zpool create rpool /dev/vdc1", "zfs create -o mountpoint=legacy rpool/root", # shared datasets cannot have legacy mountpoint "zfs create rpool/shared_smb", "bootctl set-default nixos-generation-1-specialisation-samba.conf", "sync", ) machine.crash() machine.wait_for_unit("multi-user.target") machine.succeed( "zfs set sharesmb=on rpool/shared_smb", "zfs share rpool/shared_smb", "smbclient -gNL localhost | grep rpool_shared_smb", "umount /tmp/mnt", "zpool destroy rpool", ) with subtest("encryption works"): machine.succeed( 'echo password | zpool create -O mountpoint=legacy ' + "-O encryption=aes-256-gcm -O keyformat=passphrase automatic /dev/vdc1", "zpool create -O mountpoint=legacy manual /dev/vdd1", "echo otherpass | zfs create " + "-o encryption=aes-256-gcm -o keyformat=passphrase manual/encrypted", "bootctl set-default nixos-generation-1-specialisation-encryption.conf", "sync", "zpool export automatic", "zpool export manual", ) machine.crash() machine.start() machine.wait_for_console_text("Starting password query on") machine.send_console("passwordn") machine.wait_for_unit("multi-user.target") machine.succeed( "zfs get keystatus manual/encrypted | grep unavailable", "echo otherpass | zfs load-key manual/encrypted", "systemctl start manual-encrypted.mount", "umount /automatic /manual/encrypted /manual", "zpool destroy automatic", "zpool destroy manual", ) </ins> with subtest("boot.zfs.forceImportAll works"): machine.succeed( "rm /etc/hostid", "zgenhostid deadcafe", <del> "zpool create forcepool /dev/vdb1 -O mountpoint=legacy", </del> <ins> "zpool create forcepool /dev/vdc1 -O mountpoint=legacy", "bootctl set-default nixos-generation-1-specialisation-forcepool.conf", "rm /etc/hostid", "sync", </ins> ) <del> machine.shutdown() machine.start() machine.succeed("udevadm settle") </del> <ins> machine.crash() machine.wait_for_unit("multi-user.target") </ins> machine.fail("zpool import forcepool") machine.succeed( <del> "systemctl start zfs-import-forcepool.service", "mount -t zfs forcepool /tmp/mnt", </del> <ins> "systemctl start forcepool.mount", "mount | grep forcepool", </ins> ) '' + extraTest;