feat: updated interface for storage

This commit is contained in:
Leyla Becker 2025-11-15 13:39:53 -06:00
parent f8edad75bf
commit 757a3892e1
4 changed files with 196 additions and 96 deletions

View file

@ -44,7 +44,7 @@ in {
}; };
}; };
}; };
"persist/system/jellyfin" = { "persist/replicate/system/jellyfin" = {
atime = "off"; atime = "off";
relatime = "off"; relatime = "off";

View file

@ -33,7 +33,7 @@ in {
group.name = "qbittorrent"; group.name = "qbittorrent";
}; };
}; };
"persist/system/qbittorrent" = { "persist/replicate/system/qbittorrent" = {
directories."${config.services.qbittorrent.mediaDir}" = { directories."${config.services.qbittorrent.mediaDir}" = {
owner.name = "qbittorrent"; owner.name = "qbittorrent";
group.name = "qbittorrent"; group.name = "qbittorrent";

View file

@ -1,49 +1,155 @@
{ args @ {
lib, lib,
config, config,
... ...
}: { }: let
# TODO: create all of the datasets from option and home-manager datasets datasetSubmodule = (import ./submodules/dataset.nix) args;
# TODO: set up datasets for systemd services that want a dataset created 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 [ config = lib.mkMerge [
( (lib.mkIf config.storage.zfs.enable {
lib.mkIf config.storage.zfs.enable (lib.mkMerge [ # Create ZFS datasets based on storage.datasets configuration
{ })
storage.zfs.datasets = { (lib.mkIf (config.storage.zfs.enable && config.storage.impermanence.enable) {
"persist" = { storage.datasets = {
type = "zfs_fs"; ephemeral = {
"" = {
type = "zfs_fs";
};
"system/root" = {
type = "zfs_fs";
mount = {
enable = true;
mountPoint = "/";
}; };
"persist/local" = { snapshot = {
type = "zfs_fs"; blankSnapshot = true;
};
"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";
};
}; };
}; };
} };
(lib.mkIf (!config.storage.impermanence.enable) { local = {
storage.zfs.rootDataset = { "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"; type = "zfs_fs";
mount = { mount = {
enable = true; enable = true;
@ -58,63 +164,58 @@
blankSnapshot = true; blankSnapshot = true;
}; };
}; };
}) "nix" = {
(lib.mkIf config.storage.impermanence.enable { type = "zfs_fs";
boot.initrd.postResumeCommands = lib.mkAfter '' mount = {
zfs rollback -r rpool/ephemeral/system/root@blank enable = true;
''; mountPoint = "/nix";
storage.zfs.datasets = {
"ephemeral" = {
type = "zfs_fs";
}; };
"ephemeral/system/root" = { snapshot = {
type = "zfs_fs"; autoSnapshot = false;
mount = { };
enable = true; atime = "off";
mountPoint = "/"; relatime = "off";
}; };
snapshot = { };
blankSnapshot = true; replicate = {
}; "" = {
type = "zfs_fs";
};
"system/var/log" = {
type = "zfs_fs";
mount = {
enable = true;
mountPoint = "/var/log";
}; };
}; };
};
};
storage.impermanence.datasets = { storage.zfs.datasets = lib.mkMerge [
"persist/replicate/system/root" = { (lib.mapAttrs' (name: dataset: {
mount = { name =
enable = true; if name == ""
mountPoint = "/persist/replicate/system/root"; then "persist/local"
}; else "persist/local/${name}";
snapshot = { value = builtins.removeAttrs dataset impermanenceOnlyOptions;
autoSnapshot = true; })
}; config.storage.datasets.local)
directories = { (lib.mapAttrs' (name: dataset: {
"/var/lib/nixos".enable = true; name =
"/var/lib/systemd/coredump".enable = true; if name == ""
}; then "persist/replicate"
files = { else "persist/replicate/${name}";
"/etc/machine-id".enable = true; value = builtins.removeAttrs dataset impermanenceOnlyOptions;
}; })
}; config.storage.datasets.replicate)
"persist/replicate/home" = { ];
mount = { })
enable = true;
mountPoint = "/persist/replicate/home";
};
snapshot = {
autoSnapshot = true;
};
};
};
# TODO: home-manager.users.<user>.storage.impermanence.enable
# is false then persist the entire directory of the user
# if true persist home-manager.users.<user>.storage.impermanence.datasets
# TODO: systemd.services.<name>.storage.datasets persists
})
])
)
# TODO: configure other needed storage modes here
]; ];
# TODO: set up datasets for systemd services that want a dataset created
# TODO: home-manager.users.<user>.storage.impermanence.enable
# is false then persist the entire directory of the user
# if true persist home-manager.users.<user>.storage.impermanence.datasets
# TODO: systemd.services.<name>.storage.datasets persists
# TODO: configure other needed storage modes here
} }

View file

@ -72,7 +72,6 @@
snapshot = { snapshot = {
# This option should set this option flag # This option should set this option flag
# "com.sun:auto-snapshot" = "false";
autoSnapshot = lib.mkEnableOption "Enable automatic snapshots for this dataset"; autoSnapshot = lib.mkEnableOption "Enable automatic snapshots for this dataset";
# Creates a blank snapshot in the post create hook for rollback purposes # 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"; blankSnapshot = lib.mkEnableOption "Should a blank snapshot be auto created in the post create hook";