about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorWill Fancher <elvishjerricco@gmail.com>2023-05-25 14:06:31 -0400
committerGitHub <noreply@github.com>2023-05-25 14:06:31 -0400
commitfe43923a70ecb7308cb15eef4844cff297193b65 (patch)
treef170b4137b9d176b077b1296ab0b41202033d29f /nixos
parenta941557fafe4f4c37e782613b346e90f96414971 (diff)
parentfeb5a3cdcd523e7884a5ff4635bac63d632197b1 (diff)
downloadnixlib-fe43923a70ecb7308cb15eef4844cff297193b65.tar
nixlib-fe43923a70ecb7308cb15eef4844cff297193b65.tar.gz
nixlib-fe43923a70ecb7308cb15eef4844cff297193b65.tar.bz2
nixlib-fe43923a70ecb7308cb15eef4844cff297193b65.tar.lz
nixlib-fe43923a70ecb7308cb15eef4844cff297193b65.tar.xz
nixlib-fe43923a70ecb7308cb15eef4844cff297193b65.tar.zst
nixlib-fe43923a70ecb7308cb15eef4844cff297193b65.zip
Merge pull request #229767 from mberndt123/mberndt123/stratis-rootfs
nixos/stratis: initrd support for stratis root volumes
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/release-notes/rl-2305.section.md2
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl21
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/system/boot/stratisroot.nix64
-rw-r--r--nixos/modules/tasks/filesystems.nix9
-rw-r--r--nixos/tests/installer-systemd-stage-1.nix1
-rw-r--r--nixos/tests/installer.nix35
7 files changed, 131 insertions, 2 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md
index 996714830d38..15715e31c786 100644
--- a/nixos/doc/manual/release-notes/rl-2305.section.md
+++ b/nixos/doc/manual/release-notes/rl-2305.section.md
@@ -567,6 +567,8 @@ In addition to numerous new and upgraded packages, this release has the followin
 
 - `boot.initrd.luks.device.<name>` has a new `tryEmptyPassphrase` option, this is useful for OEM's who need to install an encrypted disk with a future settable passphrase
 
+- there is a new `boot/stratisroot.nix` module that enables booting from a volume managed by the Stratis storage management daemon. Use `fileSystems.<name>.stratis.poolUuid` to configure the pool containing the fs.
+
 - Lisp gained a [manual section](https://nixos.org/manual/nixpkgs/stable/#lisp), documenting a new and backwards incompatible interface. The previous interface will be removed in a future release.
 
 - The `bind` module now allows the per-zone `allow-query` setting to be configured (previously it was hard-coded to `any`; it still defaults to `any` to retain compatibility).
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 5d3d0216d20c..c2a5ecbe9e2e 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -335,7 +335,7 @@ sub findStableDevPath {
 
     my $st = stat($dev) or return $dev;
 
-    foreach my $dev2 (glob("/dev/disk/by-uuid/*"), glob("/dev/mapper/*"), glob("/dev/disk/by-label/*")) {
+    foreach my $dev2 (glob("/dev/stratis/*/*"), glob("/dev/disk/by-uuid/*"), glob("/dev/mapper/*"), glob("/dev/disk/by-label/*")) {
         my $st2 = stat($dev2) or next;
         return $dev2 if $st->rdev == $st2->rdev;
     }
@@ -467,6 +467,17 @@ EOF
         }
     }
 
+    # is this a stratis fs?
+    my $stableDevPath = findStableDevPath $device;
+    my $stratisPool;
+    if ($stableDevPath =~ qr#/dev/stratis/(.*)/.*#) {
+        my $poolName = $1;
+        my ($header, @lines) = split "\n", qx/stratis pool list/;
+        my $uuidIndex = index $header, 'UUID';
+        my ($line) = grep /^$poolName /, @lines;
+        $stratisPool = substr $line, $uuidIndex - 32, 36;
+    }
+
     # Don't emit tmpfs entry for /tmp, because it most likely comes from the
     # boot.tmp.useTmpfs option in configuration.nix (managed declaratively).
     next if ($mountPoint eq "/tmp" && $fsType eq "tmpfs");
@@ -474,7 +485,7 @@ EOF
     # Emit the filesystem.
     $fileSystems .= <<EOF;
   fileSystems.\"$mountPoint\" =
-    { device = \"${\(findStableDevPath $device)}\";
+    { device = \"$stableDevPath\";
       fsType = \"$fsType\";
 EOF
 
@@ -484,6 +495,12 @@ EOF
 EOF
     }
 
+    if ($stratisPool) {
+        $fileSystems .= <<EOF;
+      stratis.poolUuid = "$stratisPool";
+EOF
+    }
+
     $fileSystems .= <<EOF;
     };
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index ff06a72ff9dd..6d05e6b7b09d 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -1345,6 +1345,7 @@
   ./system/boot/loader/raspberrypi/raspberrypi.nix
   ./system/boot/loader/systemd-boot/systemd-boot.nix
   ./system/boot/luksroot.nix
+  ./system/boot/stratisroot.nix
   ./system/boot/modprobe.nix
   ./system/boot/networkd.nix
   ./system/boot/plymouth.nix
diff --git a/nixos/modules/system/boot/stratisroot.nix b/nixos/modules/system/boot/stratisroot.nix
new file mode 100644
index 000000000000..241d044db2fe
--- /dev/null
+++ b/nixos/modules/system/boot/stratisroot.nix
@@ -0,0 +1,64 @@
+{ config, lib, pkgs, utils, ... }:
+let
+  requiredStratisFilesystems = lib.attrsets.filterAttrs (_: x: utils.fsNeededForBoot x && x.stratis.poolUuid != null) config.fileSystems;
+in
+{
+  options = {};
+  config = lib.mkIf (requiredStratisFilesystems != {}) {
+    assertions = [
+      {
+        assertion = config.boot.initrd.systemd.enable;
+        message = "stratis root fs requires systemd stage 1";
+      }
+    ];
+    boot.initrd = {
+      systemd = {
+        storePaths = [
+          "${pkgs.stratisd}/lib/udev/stratis-base32-decode"
+          "${pkgs.stratisd}/lib/udev/stratis-str-cmp"
+          "${pkgs.lvm2.bin}/bin/dmsetup"
+          "${pkgs.stratisd}/libexec/stratisd-min"
+          "${pkgs.stratisd.initrd}/bin/stratis-rootfs-setup"
+        ];
+        packages = [pkgs.stratisd.initrd];
+        extraBin = {
+          thin_check = "${pkgs."thin-provisioning-tools"}/bin/thin_check";
+          thin_repair = "${pkgs."thin-provisioning-tools"}/bin/thin_repair";
+          thin_metadata_size = "${pkgs."thin-provisioning-tools"}/bin/thin_metadata_size";
+          stratis-min = "${pkgs.stratisd}/bin/stratis-min";
+        };
+        services =
+          lib.attrsets.mapAttrs' (
+            mountPoint: fileSystem: {
+              name = "stratis-setup-${fileSystem.stratis.poolUuid}";
+              value = {
+                description = "setup for Stratis root filesystem";
+                unitConfig.DefaultDependencies = "no";
+                conflicts = [ "shutdown.target" "initrd-switch-root.target" ];
+                onFailure = [ "emergency.target" ];
+                unitConfig.OnFailureJobMode = "isolate";
+                wants = [ "stratisd-min.service" "plymouth-start.service" ];
+                wantedBy = [ "initrd.target" ];
+                after = [ "paths.target" "plymouth-start.service" "stratisd-min.service" ];
+                before = [ "initrd.target" "shutdown.target" "initrd-switch-root.target" ];
+                environment.STRATIS_ROOTFS_UUID = fileSystem.stratis.poolUuid;
+                serviceConfig = {
+                  Type = "oneshot";
+                  ExecStart = "${pkgs.stratisd.initrd}/bin/stratis-rootfs-setup";
+                  RemainAfterExit = "yes";
+                };
+              };
+            }
+          ) requiredStratisFilesystems;
+      };
+      availableKernelModules = [ "dm-thin-pool" "dm-crypt" ] ++ [ "aes" "aes_generic" "blowfish" "twofish"
+        "serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512"
+        "af_alg" "algif_skcipher"
+      ];
+      services.udev.packages = [
+        pkgs.stratisd.initrd
+        pkgs.lvm2
+      ];
+    };
+  };
+}
diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix
index 326862f836a5..2f032c3faf5c 100644
--- a/nixos/modules/tasks/filesystems.nix
+++ b/nixos/modules/tasks/filesystems.nix
@@ -36,6 +36,15 @@ let
         description = lib.mdDoc "Location of the mounted file system.";
       };
 
+      stratis.poolUuid = lib.mkOption {
+        type = types.uniq (types.nullOr types.str);
+        description = lib.mdDoc ''
+          UUID of the stratis pool that the fs is located in
+        '';
+        example = "04c68063-90a5-4235-b9dd-6180098a20d9";
+        default = null;
+      };
+
       device = mkOption {
         default = null;
         example = "/dev/sda";
diff --git a/nixos/tests/installer-systemd-stage-1.nix b/nixos/tests/installer-systemd-stage-1.nix
index 03f0ec8d746b..05fb2b2ae89c 100644
--- a/nixos/tests/installer-systemd-stage-1.nix
+++ b/nixos/tests/installer-systemd-stage-1.nix
@@ -27,6 +27,7 @@
     simpleUefiGrub
     simpleUefiGrubSpecialisation
     simpleUefiSystemdBoot
+    stratisRoot
     # swraid
     zfsroot
     ;
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 28b93472263f..1ac164f4b816 100644
--- a/nixos/tests/installer.nix
+++ b/nixos/tests/installer.nix
@@ -989,4 +989,39 @@ in {
       )
     '';
   };
+} // optionalAttrs systemdStage1 {
+  stratisRoot = makeInstallerTest "stratisRoot" {
+    createPartitions = ''
+      machine.succeed(
+        "sgdisk --zap-all /dev/vda",
+        "sgdisk --new=1:0:+100M --typecode=0:ef00 /dev/vda", # /boot
+        "sgdisk --new=2:0:+1G --typecode=0:8200 /dev/vda", # swap
+        "sgdisk --new=3:0:+5G --typecode=0:8300 /dev/vda", # /
+        "udevadm settle",
+
+        "mkfs.vfat /dev/vda1",
+        "mkswap /dev/vda2 -L swap",
+        "swapon -L swap",
+        "stratis pool create my-pool /dev/vda3",
+        "stratis filesystem create my-pool nixos",
+        "udevadm settle",
+
+        "mount /dev/stratis/my-pool/nixos /mnt",
+        "mkdir -p /mnt/boot",
+        "mount /dev/vda1 /mnt/boot"
+      )
+    '';
+    bootLoader = "systemd-boot";
+    extraInstallerConfig = { modulesPath, ...}: {
+      config = {
+        services.stratis.enable = true;
+        environment.systemPackages = [
+          pkgs.stratis-cli
+          pkgs.thin-provisioning-tools
+          pkgs.lvm2.bin
+          pkgs.stratisd.initrd
+        ];
+      };
+    };
+  };
 }