diff --git a/nixos/modules/services/backup/syncoid.nix b/nixos/modules/services/backup/syncoid.nix index 779c71a6ba94..1e445f4bebed 100644 --- a/nixos/modules/services/backup/syncoid.nix +++ b/nixos/modules/services/backup/syncoid.nix @@ -16,11 +16,11 @@ let lib.concatMapStrings (s: if lib.isList s then "-" else s) (builtins.split "[^a-zA-Z0-9_.\\-]+" name); - # Function to build "zfs allow" commands for the filesystems we've - # delegated permissions to. It also checks if the target dataset - # exists before delegating permissions, if it doesn't exist we - # delegate it to the parent dataset. This should solve the case of - # provisoning new datasets. + # Function to build "zfs allow" commands for the filesystems we've delegated + # permissions to. It also checks if the target dataset exists before + # delegating permissions, if it doesn't exist we delegate it to the parent + # dataset (if it exists). This should solve the case of provisoning new + # datasets. buildAllowCommand = permissions: dataset: ( "-+${pkgs.writeShellScript "zfs-allow-${dataset}" '' # Here we explicitly use the booted system to guarantee the stable API needed by ZFS @@ -38,15 +38,17 @@ let (concatStringsSep "," permissions) dataset ]} - else - ${lib.escapeShellArgs [ - "/run/booted-system/sw/bin/zfs" - "allow" - cfg.user - (concatStringsSep "," permissions) - # Remove the last part of the path - (builtins.dirOf dataset) - ]} + ${lib.optionalString ((builtins.dirOf dataset) != ".") '' + else + ${lib.escapeShellArgs [ + "/run/booted-system/sw/bin/zfs" + "allow" + cfg.user + (concatStringsSep "," permissions) + # Remove the last part of the path + (builtins.dirOf dataset) + ]} + ''} fi ''}" ); @@ -67,14 +69,14 @@ let (concatStringsSep "," permissions) dataset ]} - ${lib.escapeShellArgs [ + ${lib.optionalString ((builtins.dirOf dataset) != ".") (lib.escapeShellArgs [ "/run/booted-system/sw/bin/zfs" "unallow" cfg.user (concatStringsSep "," permissions) # Remove the last part of the path (builtins.dirOf dataset) - ]} + ])} ''}" ); in diff --git a/nixos/tests/sanoid.nix b/nixos/tests/sanoid.nix index 3bdbe0a8d8db..97833c37e6ef 100644 --- a/nixos/tests/sanoid.nix +++ b/nixos/tests/sanoid.nix @@ -48,6 +48,9 @@ in { }; # Take snapshot and sync "pool/syncoid".target = "root@target:pool/syncoid"; + + # Test pool without parent (regression test for https://github.com/NixOS/nixpkgs/pull/180111) + "pool".target = "root@target:pool/full-pool"; }; }; }; @@ -105,6 +108,9 @@ in { source.systemctl("start --wait syncoid-pool-syncoid.service") target.succeed("cat /mnt/pool/syncoid/test.txt") + source.systemctl("start --wait syncoid-pool.service") + target.succeed("[[ -d /mnt/pool/full-pool/syncoid ]]") + assert len(source.succeed("zfs allow pool")) == 0, "Pool shouldn't have delegated permissions set after syncing snapshots" assert len(source.succeed("zfs allow pool/sanoid")) == 0, "Sanoid dataset shouldn't have delegated permissions set after syncing snapshots" assert len(source.succeed("zfs allow pool/syncoid")) == 0, "Syncoid dataset shouldn't have delegated permissions set after syncing snapshots"