diff --git a/README.md b/README.md index 9e7bc14..d5de931 100644 --- a/README.md +++ b/README.md @@ -93,8 +93,8 @@ A simple disko configuration may look like this: ``` If you'd saved this configuration in /tmp/disk-config.nix, and wanted to create -a disk named /dev/sda, you would run the following command to partition, -format and mount the disk. +a disk named /dev/sda, you would run the following command to partition, format +and mount the disk. ```console sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko -- --mode disko /tmp/disk-config.nix diff --git a/docs/quickstart.md b/docs/quickstart.md index d9e6c95..1f38604 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -70,8 +70,8 @@ and made a note of its URL. Your configuration needs to be saved on the new machine for example asĀ /tmp/disk-config.nix. You can do this using the `curl` command to download from the url you noted above, using the `-o` option to save the file as -disk-config.nix. Your commands would look like this if you had chosen the -hybrid layout: +disk-config.nix. Your commands would look like this if you had chosen the hybrid +layout: ```console cd /tmp @@ -182,8 +182,8 @@ of the NixOS manual. The following configuration for `grub` works for both EFI and BIOS systems. Add this to your configuration.nix, commenting out the existing lines that configureĀ `systemd-boot`. The entries will look like this: -**Note:** Its not necessary to set `boot.loader.grub.device` here, since Disko will -take care of that automatically. +**Note:** Its not necessary to set `boot.loader.grub.device` here, since Disko +will take care of that automatically. ```nix # ... diff --git a/docs/reference.md b/docs/reference.md index 69e1f44..f28cf97 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -51,9 +51,11 @@ generate disk images: ### Generating the `.raw` VM Image -1. **Create a NixOS configuration that includes the disko and the disk configuration of your choice** +1. **Create a NixOS configuration that includes the disko and the disk + configuration of your choice** -In the this example we create a flake containing a nixos configuration for `myhost`. +In the this example we create a flake containing a nixos configuration for +`myhost`. ```nix # save this as flake.nix @@ -86,15 +88,15 @@ In the this example we create a flake containing a nixos configuration for `myho } ``` -2. **Build the disko image script:** Replace `myhost` in the command below with your - specific system configuration name: +2. **Build the disko image script:** Replace `myhost` in the command below with + your specific system configuration name: ```console nix build .#nixosConfigurations.myhost.config.system.build.diskoImagesScript ``` -3. **Execute the disko image script:** Execute the generated disko image script. Running - `./result --help` will output the available options: +3. **Execute the disko image script:** Execute the generated disko image script. + Running `./result --help` will output the available options: ```console ./result --help @@ -124,9 +126,10 @@ In the this example we create a flake containing a nixos configuration for `myho sudo ./result --build-memory 2048 ``` - The script will generate the actual image outside of the nix store in the current working directory. - The create image names depend on the names used in `disko.devices.disk` attrset in the NixOS configuration. - In our code example it will produce the following image: + The script will generate the actual image outside of the nix store in the + current working directory. The create image names depend on the names used in + `disko.devices.disk` attrset in the NixOS configuration. In our code example it will + produce the following image: ``` $ ls -la vdb.raw @@ -142,8 +145,8 @@ In the this example we create a flake containing a nixos configuration for `myho ``` - If the `.raw` image size is not optimal, use `--write-to-disk` to write - directly to a drive. This bypasses the `.raw` file generation, which saves on read/write operations - and is suitable for single disk setups. + directly to a drive. This bypasses the `.raw` file generation, which saves on + read/write operations and is suitable for single disk setups. ### Understanding the Image Generation Process diff --git a/flake.nix b/flake.nix index b4b1acd..a0b46c2 100644 --- a/flake.nix +++ b/flake.nix @@ -28,8 +28,8 @@ in { disko = pkgs.callPackage ./package.nix { }; - # alias to make `nix run` more convenient - disko-install = self.packages.${system}.disko.overrideAttrs (old: { + # alias to make `nix run` more convenient + disko-install = self.packages.${system}.disko.overrideAttrs (_old: { name = "disko-install"; }); default = self.packages.${system}.disko; diff --git a/lib/default.nix b/lib/default.nix index 1daa0fc..0ca2036 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -85,7 +85,7 @@ let else if match "/dev/mapper/.+" dev != null then "${dev}${toString index}" # /dev/mapper/vg-lv1 style else if match "/dev/loop[[:digit:]]+" dev != null - then "${dev}p${toString index}" # /dev/mapper/vg-lv1 style + then "${dev}p${toString index}" # /dev/mapper/vg-lv1 style else abort '' ${dev} seems not to be a supported disk format. Please add this to disko in https://github.com/nix-community/disko/blob/master/lib/default.nix @@ -191,10 +191,10 @@ let isAttrsOfSubmodule = o: o.type.name == "attrsOf" && o.type.nestedTypes.elemType.name == "submodule"; isSerializable = n: o: !( lib.hasPrefix "_" n - || lib.hasSuffix "Hook" n - || isAttrsOfSubmodule o - # TODO don't hardcode diskoLib.subType options. - || n == "content" || n == "partitions" || n == "datasets" || n == "swap" + || lib.hasSuffix "Hook" n + || isAttrsOfSubmodule o + # TODO don't hardcode diskoLib.subType options. + || n == "content" || n == "partitions" || n == "datasets" || n == "swap" ); in lib.toShellVars @@ -245,14 +245,17 @@ let internal = true; readOnly = true; type = diskoLib.jsonType; - default = lib.mapAttrsRecursive (name: value: if builtins.isString value then '' - ( - ${diskoLib.indent (diskoLib.defineHookVariables { inherit options; })} - ${config.preMountHook} - ${diskoLib.indent value} - ${config.postMountHook} - ) - '' else value) attrs.default; + default = lib.mapAttrsRecursive + (_name: value: + if builtins.isString value then '' + ( + ${diskoLib.indent (diskoLib.defineHookVariables { inherit options; })} + ${config.preMountHook} + ${diskoLib.indent value} + ${config.postMountHook} + ) + '' else value) + attrs.default; description = "Mount script"; }; diff --git a/lib/make-disk-image.nix b/lib/make-disk-image.nix index 01d70b4..7bbc021 100644 --- a/lib/make-disk-image.nix +++ b/lib/make-disk-image.nix @@ -8,10 +8,10 @@ }: let vmTools = pkgs.vmTools.override { - rootModules = ["9p" "9pnet_virtio" "virtio_pci" "virtio_blk"] ++ nixosConfig.config.disko.extraRootModules; + rootModules = [ "9p" "9pnet_virtio" "virtio_pci" "virtio_blk" ] ++ nixosConfig.config.disko.extraRootModules; kernel = pkgs.aggregateModules - (with nixosConfig.config.boot.kernelPackages; [ kernel ] - ++ lib.optional (lib.elem "zfs" nixosConfig.config.disko.extraRootModules) zfs); + (with nixosConfig.config.boot.kernelPackages; [ kernel ] + ++ lib.optional (lib.elem "zfs" nixosConfig.config.disko.extraRootModules) zfs); }; cleanedConfig = diskoLib.testLib.prepareDiskoConfig nixosConfig.config diskoLib.testLib.devices; systemToInstall = nixosConfig.extendModules { diff --git a/lib/tests.nix b/lib/tests.nix index 5859a9d..77c07ba 100644 --- a/lib/tests.nix +++ b/lib/tests.nix @@ -114,47 +114,49 @@ let }; installedTopLevel = ((if extendModules != null then extendModules else installed-system-eval.extendModules) { - modules = [({config, ...}: { - imports = [ - extraSystemConfig - ({ modulesPath, ... }: { - imports = [ - (modulesPath + "/testing/test-instrumentation.nix") # we need these 2 modules always to be able to run the tests - (modulesPath + "/profiles/qemu-guest.nix") - ]; - disko.devices = lib.mkForce testConfigBooted.disko.devices; - }) - ]; + modules = [ + ({ config, ... }: { + imports = [ + extraSystemConfig + ({ modulesPath, ... }: { + imports = [ + (modulesPath + "/testing/test-instrumentation.nix") # we need these 2 modules always to be able to run the tests + (modulesPath + "/profiles/qemu-guest.nix") + ]; + disko.devices = lib.mkForce testConfigBooted.disko.devices; + }) + ]; - # since we boot on a different machine, the efi payload needs to be portable - boot.loader.grub.efiInstallAsRemovable = efi; - boot.loader.grub.efiSupport = efi; - boot.loader.systemd-boot.graceful = true; + # since we boot on a different machine, the efi payload needs to be portable + boot.loader.grub.efiInstallAsRemovable = efi; + boot.loader.grub.efiSupport = efi; + boot.loader.systemd-boot.graceful = true; - # we always want the bind-mounted nix store. otherwise tests take forever - fileSystems."/nix/store" = lib.mkForce { - device = "nix-store"; - fsType = "9p"; - neededForBoot = true; - options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ]; - }; - boot.zfs.devNodes = "/dev/disk/by-uuid"; # needed because /dev/disk/by-id is empty in qemu-vms + # we always want the bind-mounted nix store. otherwise tests take forever + fileSystems."/nix/store" = lib.mkForce { + device = "nix-store"; + fsType = "9p"; + neededForBoot = true; + options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ]; + }; + boot.zfs.devNodes = "/dev/disk/by-uuid"; # needed because /dev/disk/by-id is empty in qemu-vms - # grub will install to these devices, we need to force those or we are offset by 1 - # we use mkOveride 70, so that users can override this with mkForce in case they are testing grub mirrored boots - boot.loader.grub.devices = lib.mkOverride 70 testConfigInstall.boot.loader.grub.devices; + # grub will install to these devices, we need to force those or we are offset by 1 + # we use mkOveride 70, so that users can override this with mkForce in case they are testing grub mirrored boots + boot.loader.grub.devices = lib.mkOverride 70 testConfigInstall.boot.loader.grub.devices; - assertions = [ - { - assertion = builtins.length config.boot.loader.grub.mirroredBoots > 1 -> config.boot.loader.grub.devices == []; - message = '' - When using `--vm-test` in combination with `mirroredBoots`, - it is necessary to configure `boot.loader.grub.devices` as an empty list by setting `boot.loader.grub.devices = lib.mkForce [];`. - This adjustment is crucial because the `--vm-test` mechanism automatically overrides the grub boot devices as part of the virtual machine test. - ''; - } - ]; - })]; + assertions = [ + { + assertion = builtins.length config.boot.loader.grub.mirroredBoots > 1 -> config.boot.loader.grub.devices == [ ]; + message = '' + When using `--vm-test` in combination with `mirroredBoots`, + it is necessary to configure `boot.loader.grub.devices` as an empty list by setting `boot.loader.grub.devices = lib.mkForce [];`. + This adjustment is crucial because the `--vm-test` mechanism automatically overrides the grub boot devices as part of the virtual machine test. + ''; + } + ]; + }) + ]; }).config.system.build.toplevel; in diff --git a/lib/types/btrfs.nix b/lib/types/btrfs.nix index 4b9fb6a..8b58801 100644 --- a/lib/types/btrfs.nix +++ b/lib/types/btrfs.nix @@ -32,9 +32,9 @@ let lib.concatMapStringsSep "\n" (file: '' - if ! test -e "${mountpoint}/${file.path}"; then - btrfs filesystem mkswapfile --size ${file.size} "${mountpoint}/${file.path}" - fi + if ! test -e "${mountpoint}/${file.path}"; then + btrfs filesystem mkswapfile --size ${file.size} "${mountpoint}/${file.path}" + fi '') (lib.attrValues swap); diff --git a/lib/types/gpt.nix b/lib/types/gpt.nix index b354aba..d66aa48 100644 --- a/lib/types/gpt.nix +++ b/lib/types/gpt.nix @@ -55,15 +55,17 @@ in }; label = lib.mkOption { type = lib.types.str; - default = let - # 72 bytes is the maximum length of a GPT partition name - # the labels seem to be in UTF-16, so 2 bytes per character - limit = 36; - label = "${config._parent.type}-${config._parent.name}-${partition.config.name}"; - in if (lib.stringLength label) > limit then - builtins.substring 0 limit (builtins.hashString "sha256" label) - else - label; + default = + let + # 72 bytes is the maximum length of a GPT partition name + # the labels seem to be in UTF-16, so 2 bytes per character + limit = 36; + label = "${config._parent.type}-${config._parent.name}-${partition.config.name}"; + in + if (lib.stringLength label) > limit then + builtins.substring 0 limit (builtins.hashString "sha256" label) + else + label; }; size = lib.mkOption { type = lib.types.either (lib.types.enum [ "100%" ]) (lib.types.strMatching "[0-9]+[KMGTP]?"); @@ -76,7 +78,7 @@ in }; alignment = lib.mkOption { type = lib.types.int; - default = if (builtins.substring (builtins.stringLength partition.config.start - 1) 1 partition.config.start == "s" || (builtins.substring (builtins.stringLength partition.config.end - 1) 1 partition.config.end == "s" )) then 1 else 0; + default = if (builtins.substring (builtins.stringLength partition.config.start - 1) 1 partition.config.start == "s" || (builtins.substring (builtins.stringLength partition.config.end - 1) 1 partition.config.end == "s")) then 1 else 0; description = "Alignment of the partition, if sectors are used as start or end it can be aligned to 1"; }; start = lib.mkOption { @@ -95,7 +97,7 @@ in }; content = diskoLib.partitionType { parent = config; device = partition.config.device; }; hybrid = lib.mkOption { - type = lib.types.nullOr (lib.types.submodule ({name, ...} @ hp: { + type = lib.types.nullOr (lib.types.submodule ({ ... } @ hp: { options = { mbrPartitionType = lib.mkOption { type = lib.types.nullOr lib.types.str; diff --git a/lib/types/lvm_vg.nix b/lib/types/lvm_vg.nix index 25195d0..5b76305 100644 --- a/lib/types/lvm_vg.nix +++ b/lib/types/lvm_vg.nix @@ -115,13 +115,14 @@ (lv: [ (lib.optional (lv.content != null) lv.content._config) (lib.optional (lv.lvm_type != null) { - boot.initrd.kernelModules = [(if lv.lvm_type == "mirror" then "dm-mirror" else "dm-raid")] + boot.initrd.kernelModules = [ (if lv.lvm_type == "mirror" then "dm-mirror" else "dm-raid") ] ++ lib.optional (lv.lvm_type == "raid0") "raid0" ++ lib.optional (lv.lvm_type == "raid1") "raid1" # ++ lib.optional (lv.lvm_type == "raid10") "raid10" - ++ lib.optional (lv.lvm_type == "raid4" || - lv.lvm_type == "raid5" || - lv.lvm_type == "raid6") "raid456"; + ++ lib.optional + (lv.lvm_type == "raid4" || + lv.lvm_type == "raid5" || + lv.lvm_type == "raid6") "raid456"; }) ]) diff --git a/lib/types/table.nix b/lib/types/table.nix index 72ef3bd..6ca18f6 100644 --- a/lib/types/table.nix +++ b/lib/types/table.nix @@ -6,155 +6,156 @@ If you encounter errors similar to: "error: The option `disko.devices.disk.disk1.content.partitions."[definition 1-entry 1]".content._config` is read-only, but it's set multiple times," this is likely due to the use of the legacy table type. - '' { - type = lib.mkOption { - type = lib.types.enum [ "table" ]; - internal = true; - description = "Partition table"; - }; - device = lib.mkOption { - type = lib.types.str; - default = device; - description = "Device to partition"; - }; - format = lib.mkOption { - type = lib.types.enum [ "gpt" "msdos" ]; - default = "gpt"; - description = "The kind of partition table"; - }; - partitions = lib.mkOption { - type = lib.types.listOf (lib.types.submodule ({ name, ... }@partition: { - options = { - part-type = lib.mkOption { - type = lib.types.enum [ "primary" "logical" "extended" ]; - default = "primary"; - description = "Partition type"; + '' + { + type = lib.mkOption { + type = lib.types.enum [ "table" ]; + internal = true; + description = "Partition table"; + }; + device = lib.mkOption { + type = lib.types.str; + default = device; + description = "Device to partition"; + }; + format = lib.mkOption { + type = lib.types.enum [ "gpt" "msdos" ]; + default = "gpt"; + description = "The kind of partition table"; + }; + partitions = lib.mkOption { + type = lib.types.listOf (lib.types.submodule ({ name, ... }@partition: { + options = { + part-type = lib.mkOption { + type = lib.types.enum [ "primary" "logical" "extended" ]; + default = "primary"; + description = "Partition type"; + }; + fs-type = lib.mkOption { + type = lib.types.nullOr (lib.types.enum [ "btrfs" "ext2" "ext3" "ext4" "fat16" "fat32" "hfs" "hfs+" "linux-swap" "ntfs" "reiserfs" "udf" "xfs" ]); + default = null; + description = "Filesystem type to use"; + }; + name = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "Name of the partition"; + }; + start = lib.mkOption { + type = lib.types.str; + default = "0%"; + description = "Start of the partition"; + }; + end = lib.mkOption { + type = lib.types.str; + default = "100%"; + description = "End of the partition"; + }; + flags = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "Partition flags"; + }; + bootable = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to make the partition bootable"; + }; + content = diskoLib.partitionType { parent = config; device = diskoLib.deviceNumbering config.device partition.config._index; }; + _index = lib.mkOption { + internal = true; + default = lib.toInt (lib.head (builtins.match ".*entry ([[:digit:]]+)]" name)); + }; }; - fs-type = lib.mkOption { - type = lib.types.nullOr (lib.types.enum [ "btrfs" "ext2" "ext3" "ext4" "fat16" "fat32" "hfs" "hfs+" "linux-swap" "ntfs" "reiserfs" "udf" "xfs" ]); - default = null; - description = "Filesystem type to use"; - }; - name = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "Name of the partition"; - }; - start = lib.mkOption { - type = lib.types.str; - default = "0%"; - description = "Start of the partition"; - }; - end = lib.mkOption { - type = lib.types.str; - default = "100%"; - description = "End of the partition"; - }; - flags = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - description = "Partition flags"; - }; - bootable = lib.mkOption { - type = lib.types.bool; - default = false; - description = "Whether to make the partition bootable"; - }; - content = diskoLib.partitionType { parent = config; device = diskoLib.deviceNumbering config.device partition.config._index; }; - _index = lib.mkOption { - internal = true; - default = lib.toInt (lib.head (builtins.match ".*entry ([[:digit:]]+)]" name)); - }; - }; - })); - default = [ ]; - description = "List of partitions to add to the partition table"; - }; - _parent = lib.mkOption { - internal = true; - default = parent; - }; - _meta = lib.mkOption { - internal = true; - readOnly = true; - type = lib.types.functionTo diskoLib.jsonType; - default = dev: - lib.foldr lib.recursiveUpdate { } (lib.imap - (_index: partition: - lib.optionalAttrs (partition.content != null) (partition.content._meta dev) - ) - config.partitions); - description = "Metadata"; - }; - _create = diskoLib.mkCreateOption { - inherit config options; - default = '' - if ! blkid "${config.device}" >/dev/null; then - parted -s ${config.device} -- mklabel ${config.format} - ${lib.concatStrings (map (partition: '' - ${lib.optionalString (config.format == "gpt") '' - parted -s ${config.device} -- mkpart ${partition.name} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} - ''} - ${lib.optionalString (config.format == "msdos") '' - parted -s ${config.device} -- mkpart ${partition.part-type} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} - ''} - # ensure /dev/disk/by-path/..-partN exists before continuing - partprobe ${config.device} - udevadm trigger --subsystem-match=block - udevadm settle - ${lib.optionalString partition.bootable '' - parted -s ${config.device} -- set ${toString partition._index} boot on - ''} - ${lib.concatMapStringsSep "" (flag: '' - parted -s ${config.device} -- set ${toString partition._index} ${flag} on - '') partition.flags} - # ensure further operations can detect new partitions - partprobe ${config.device} - udevadm trigger --subsystem-match=block - udevadm settle - '') config.partitions)} - fi - ${lib.concatStrings (map (partition: '' - ${lib.optionalString (partition.content != null) partition.content._create} - '') config.partitions)} - ''; - }; - _mount = diskoLib.mkMountOption { - inherit config options; - default = - let - partMounts = lib.foldr lib.recursiveUpdate { } (map - (partition: - lib.optionalAttrs (partition.content != null) partition.content._mount + })); + default = [ ]; + description = "List of partitions to add to the partition table"; + }; + _parent = lib.mkOption { + internal = true; + default = parent; + }; + _meta = lib.mkOption { + internal = true; + readOnly = true; + type = lib.types.functionTo diskoLib.jsonType; + default = dev: + lib.foldr lib.recursiveUpdate { } (lib.imap + (_index: partition: + lib.optionalAttrs (partition.content != null) (partition.content._meta dev) ) config.partitions); - in - { - dev = partMounts.dev or ""; - fs = partMounts.fs or { }; - }; + description = "Metadata"; + }; + _create = diskoLib.mkCreateOption { + inherit config options; + default = '' + if ! blkid "${config.device}" >/dev/null; then + parted -s ${config.device} -- mklabel ${config.format} + ${lib.concatStrings (map (partition: '' + ${lib.optionalString (config.format == "gpt") '' + parted -s ${config.device} -- mkpart ${partition.name} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} + ''} + ${lib.optionalString (config.format == "msdos") '' + parted -s ${config.device} -- mkpart ${partition.part-type} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} + ''} + # ensure /dev/disk/by-path/..-partN exists before continuing + partprobe ${config.device} + udevadm trigger --subsystem-match=block + udevadm settle + ${lib.optionalString partition.bootable '' + parted -s ${config.device} -- set ${toString partition._index} boot on + ''} + ${lib.concatMapStringsSep "" (flag: '' + parted -s ${config.device} -- set ${toString partition._index} ${flag} on + '') partition.flags} + # ensure further operations can detect new partitions + partprobe ${config.device} + udevadm trigger --subsystem-match=block + udevadm settle + '') config.partitions)} + fi + ${lib.concatStrings (map (partition: '' + ${lib.optionalString (partition.content != null) partition.content._create} + '') config.partitions)} + ''; + }; + _mount = diskoLib.mkMountOption { + inherit config options; + default = + let + partMounts = lib.foldr lib.recursiveUpdate { } (map + (partition: + lib.optionalAttrs (partition.content != null) partition.content._mount + ) + config.partitions); + in + { + dev = partMounts.dev or ""; + fs = partMounts.fs or { }; + }; + }; + _config = lib.mkOption { + internal = true; + readOnly = true; + default = + map + (partition: + lib.optional (partition.content != null) partition.content._config + ) + config.partitions; + description = "NixOS configuration"; + }; + _pkgs = lib.mkOption { + internal = true; + readOnly = true; + type = lib.types.functionTo (lib.types.listOf lib.types.package); + default = pkgs: + [ pkgs.parted pkgs.systemdMinimal ] ++ lib.flatten (map + (partition: + lib.optional (partition.content != null) (partition.content._pkgs pkgs) + ) + config.partitions); + description = "Packages"; + }; }; - _config = lib.mkOption { - internal = true; - readOnly = true; - default = - map - (partition: - lib.optional (partition.content != null) partition.content._config - ) - config.partitions; - description = "NixOS configuration"; - }; - _pkgs = lib.mkOption { - internal = true; - readOnly = true; - type = lib.types.functionTo (lib.types.listOf lib.types.package); - default = pkgs: - [ pkgs.parted pkgs.systemdMinimal ] ++ lib.flatten (map - (partition: - lib.optional (partition.content != null) (partition.content._pkgs pkgs) - ) - config.partitions); - description = "Packages"; - }; - }; } diff --git a/lib/types/zfs_fs.nix b/lib/types/zfs_fs.nix index 74527e2..ddc7d05 100644 --- a/lib/types/zfs_fs.nix +++ b/lib/types/zfs_fs.nix @@ -52,19 +52,20 @@ description = "Metadata"; }; - _create = diskoLib.mkCreateOption { - inherit config options; - # -u prevents mounting newly created datasets, which is - # important to prevent accidental shadowing of mount points - # since (create order != mount order) - # -p creates parents automatically - default = '' - if ! zfs get type ${config._name} >/dev/null 2>&1; then - zfs create -up ${config._name} \ - ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} - fi - ''; - } // { readOnly = false; }; + _create = diskoLib.mkCreateOption + { + inherit config options; + # -u prevents mounting newly created datasets, which is + # important to prevent accidental shadowing of mount points + # since (create order != mount order) + # -p creates parents automatically + default = '' + if ! zfs get type ${config._name} >/dev/null 2>&1; then + zfs create -up ${config._name} \ + ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} + fi + ''; + } // { readOnly = false; }; _mount = diskoLib.mkMountOption { inherit config options;