diff --git a/modules/nixos-modules/server/jellyfin/storage.nix b/modules/nixos-modules/server/jellyfin/storage.nix index 2854cb8..79d0605 100644 --- a/modules/nixos-modules/server/jellyfin/storage.nix +++ b/modules/nixos-modules/server/jellyfin/storage.nix @@ -44,7 +44,7 @@ in { }; }; }; - "persist/system/jellyfin" = { + "persist/replicate/system/jellyfin" = { atime = "off"; relatime = "off"; diff --git a/modules/nixos-modules/server/qbittorent/storage.nix b/modules/nixos-modules/server/qbittorent/storage.nix index 0bb01e3..32244ca 100644 --- a/modules/nixos-modules/server/qbittorent/storage.nix +++ b/modules/nixos-modules/server/qbittorent/storage.nix @@ -33,7 +33,7 @@ in { group.name = "qbittorrent"; }; }; - "persist/system/qbittorrent" = { + "persist/replicate/system/qbittorrent" = { directories."${config.services.qbittorrent.mediaDir}" = { owner.name = "qbittorrent"; group.name = "qbittorrent"; diff --git a/modules/nixos-modules/storage/storage.nix b/modules/nixos-modules/storage/storage.nix index be514d7..7d14dd7 100644 --- a/modules/nixos-modules/storage/storage.nix +++ b/modules/nixos-modules/storage/storage.nix @@ -1,49 +1,155 @@ -{ +args @ { lib, config, ... -}: { - # TODO: create all of the datasets from option and home-manager datasets - # TODO: set up datasets for systemd services that want a dataset created +}: let + datasetSubmodule = (import ./submodules/dataset.nix) args; + impermanenceDatasetSubmodule = (import ./submodules/impermanenceDataset.nix) args; + + # Get the option names from both submodules to automatically determine which are impermanence-specific + regularDatasetEval = lib.evalModules { + modules = [datasetSubmodule]; + specialArgs = args; + }; + impermanenceDatasetEval = lib.evalModules { + modules = [impermanenceDatasetSubmodule]; + specialArgs = args; + }; + + regularDatasetOptions = builtins.attrNames regularDatasetEval.options; + impermanenceDatasetOptions = builtins.attrNames impermanenceDatasetEval.options; + + # Find options that are only in impermanence datasets (not in regular ZFS datasets) + impermanenceOnlyOptions = lib.lists.subtractLists regularDatasetOptions impermanenceDatasetOptions; +in { + options.storage.datasets = { + ephemeral = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule datasetSubmodule); + default = {}; + }; + local = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule impermanenceDatasetSubmodule); + default = {}; + }; + replicate = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule impermanenceDatasetSubmodule); + default = {}; + }; + }; + config = lib.mkMerge [ - ( - lib.mkIf config.storage.zfs.enable (lib.mkMerge [ - { - storage.zfs.datasets = { - "persist" = { - type = "zfs_fs"; + (lib.mkIf config.storage.zfs.enable { + # Create ZFS datasets based on storage.datasets configuration + }) + (lib.mkIf (config.storage.zfs.enable && config.storage.impermanence.enable) { + storage.datasets = { + ephemeral = { + "" = { + type = "zfs_fs"; + }; + "system/root" = { + type = "zfs_fs"; + mount = { + enable = true; + mountPoint = "/"; }; - "persist/local" = { - type = "zfs_fs"; - }; - "persist/replicate" = { - type = "zfs_fs"; - }; - - "persist/local/nix" = { - type = "zfs_fs"; - mount = { - enable = true; - mountPoint = "/nix"; - }; - snapshot = { - autoSnapshot = false; - }; - atime = "off"; - relatime = "off"; - }; - - "persist/replicate/system/var/log" = { - type = "zfs_fs"; - mount = { - enable = true; - mountPoint = "/var/log"; - }; + snapshot = { + blankSnapshot = true; }; }; - } - (lib.mkIf (!config.storage.impermanence.enable) { - storage.zfs.rootDataset = { + }; + local = { + "nix" = { + type = "zfs_fs"; + mount = { + enable = true; + mountPoint = "/nix"; + }; + snapshot = { + autoSnapshot = false; + }; + atime = "off"; + relatime = "off"; + }; + }; + replicate = { + "system/var/log" = { + type = "zfs_fs"; + mount = { + enable = true; + mountPoint = "/var/log"; + }; + }; + "system/root" = { + mount = { + enable = true; + mountPoint = "/persist/replicate/system/root"; + }; + snapshot = { + autoSnapshot = true; + }; + directories = { + "/var/lib/nixos".enable = true; + "/var/lib/systemd/coredump".enable = true; + }; + files = { + "/etc/machine-id".enable = true; + }; + }; + "home" = { + mount = { + enable = true; + mountPoint = "/persist/replicate/home"; + }; + snapshot = { + autoSnapshot = true; + }; + }; + }; + }; + + storage.zfs.datasets = lib.mkMerge [ + (lib.mapAttrs' (name: dataset: { + name = + if name == "" + then "ephemeral" + else "ephemeral/${name}"; + value = dataset; + }) + config.storage.datasets.ephemeral) + ]; + + boot.initrd.postResumeCommands = lib.mkAfter '' + zfs rollback -r rpool/ephemeral/system/root@blank + ''; + + storage.impermanence.datasets = lib.mkMerge [ + (lib.mapAttrs' (name: dataset: { + name = + if name == "" + then "persist/local" + else "persist/local/${name}"; + value = dataset; + }) + config.storage.datasets.local) + (lib.mapAttrs' (name: dataset: { + name = + if name == "" + then "persist/replicate" + else "persist/replicate/${name}"; + value = dataset; + }) + config.storage.datasets.replicate) + ]; + }) + (lib.mkIf (config.storage.zfs.enable && !config.storage.impermanence.enable) { + storage.datasets = { + # Base organizational datasets (only needed when impermanence is disabled) + local = { + "" = { + type = "zfs_fs"; + }; + "root" = { type = "zfs_fs"; mount = { enable = true; @@ -58,63 +164,58 @@ blankSnapshot = true; }; }; - }) - (lib.mkIf config.storage.impermanence.enable { - boot.initrd.postResumeCommands = lib.mkAfter '' - zfs rollback -r rpool/ephemeral/system/root@blank - ''; - - storage.zfs.datasets = { - "ephemeral" = { - type = "zfs_fs"; + "nix" = { + type = "zfs_fs"; + mount = { + enable = true; + mountPoint = "/nix"; }; - "ephemeral/system/root" = { - type = "zfs_fs"; - mount = { - enable = true; - mountPoint = "/"; - }; - snapshot = { - blankSnapshot = true; - }; + snapshot = { + autoSnapshot = false; + }; + atime = "off"; + relatime = "off"; + }; + }; + replicate = { + "" = { + type = "zfs_fs"; + }; + "system/var/log" = { + type = "zfs_fs"; + mount = { + enable = true; + mountPoint = "/var/log"; }; }; + }; + }; - storage.impermanence.datasets = { - "persist/replicate/system/root" = { - mount = { - enable = true; - mountPoint = "/persist/replicate/system/root"; - }; - snapshot = { - autoSnapshot = true; - }; - directories = { - "/var/lib/nixos".enable = true; - "/var/lib/systemd/coredump".enable = true; - }; - files = { - "/etc/machine-id".enable = true; - }; - }; - "persist/replicate/home" = { - mount = { - enable = true; - mountPoint = "/persist/replicate/home"; - }; - snapshot = { - autoSnapshot = true; - }; - }; - }; - - # TODO: home-manager.users..storage.impermanence.enable - # is false then persist the entire directory of the user - # if true persist home-manager.users..storage.impermanence.datasets - # TODO: systemd.services..storage.datasets persists - }) - ]) - ) - # TODO: configure other needed storage modes here + storage.zfs.datasets = lib.mkMerge [ + (lib.mapAttrs' (name: dataset: { + name = + if name == "" + then "persist/local" + else "persist/local/${name}"; + value = builtins.removeAttrs dataset impermanenceOnlyOptions; + }) + config.storage.datasets.local) + (lib.mapAttrs' (name: dataset: { + name = + if name == "" + then "persist/replicate" + else "persist/replicate/${name}"; + value = builtins.removeAttrs dataset impermanenceOnlyOptions; + }) + config.storage.datasets.replicate) + ]; + }) ]; + + # TODO: set up datasets for systemd services that want a dataset created + # TODO: home-manager.users..storage.impermanence.enable + # is false then persist the entire directory of the user + # if true persist home-manager.users..storage.impermanence.datasets + # TODO: systemd.services..storage.datasets persists + # TODO: configure other needed storage modes here } diff --git a/modules/nixos-modules/storage/submodules/dataset.nix b/modules/nixos-modules/storage/submodules/dataset.nix index 5199f98..0b57886 100644 --- a/modules/nixos-modules/storage/submodules/dataset.nix +++ b/modules/nixos-modules/storage/submodules/dataset.nix @@ -72,7 +72,6 @@ snapshot = { # This option should set this option flag - # "com.sun:auto-snapshot" = "false"; autoSnapshot = lib.mkEnableOption "Enable automatic snapshots for this dataset"; # Creates a blank snapshot in the post create hook for rollback purposes blankSnapshot = lib.mkEnableOption "Should a blank snapshot be auto created in the post create hook";