storage-refactor #9

Open
jan-leila wants to merge 40 commits from storage-refactor into main
4 changed files with 196 additions and 96 deletions
Showing only changes of commit 757a3892e1 - Show all commits

View file

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

View file

@ -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";

View file

@ -1,26 +1,65 @@
{
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
config = lib.mkMerge [
(
lib.mkIf config.storage.zfs.enable (lib.mkMerge [
{
storage.zfs.datasets = {
"persist" = {
type = "zfs_fs";
}: 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;
};
"persist/local" = {
type = "zfs_fs";
};
"persist/replicate" = {
type = "zfs_fs";
impermanenceDatasetEval = lib.evalModules {
modules = [impermanenceDatasetSubmodule];
specialArgs = args;
};
"persist/local/nix" = {
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 {
# 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 = "/";
};
snapshot = {
blankSnapshot = true;
};
};
};
local = {
"nix" = {
type = "zfs_fs";
mount = {
enable = true;
@ -32,56 +71,16 @@
atime = "off";
relatime = "off";
};
"persist/replicate/system/var/log" = {
};
replicate = {
"system/var/log" = {
type = "zfs_fs";
mount = {
enable = true;
mountPoint = "/var/log";
};
};
};
}
(lib.mkIf (!config.storage.impermanence.enable) {
storage.zfs.rootDataset = {
type = "zfs_fs";
mount = {
enable = true;
mountPoint = "/";
};
compression = "lz4";
acltype = "posixacl";
relatime = "on";
xattr = "sa";
snapshot = {
autoSnapshot = true;
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";
};
"ephemeral/system/root" = {
type = "zfs_fs";
mount = {
enable = true;
mountPoint = "/";
};
snapshot = {
blankSnapshot = true;
};
};
};
storage.impermanence.datasets = {
"persist/replicate/system/root" = {
"system/root" = {
mount = {
enable = true;
mountPoint = "/persist/replicate/system/root";
@ -97,7 +96,7 @@
"/etc/machine-id".enable = true;
};
};
"persist/replicate/home" = {
"home" = {
mount = {
enable = true;
mountPoint = "/persist/replicate/home";
@ -107,14 +106,116 @@
};
};
};
};
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;
mountPoint = "/";
};
compression = "lz4";
acltype = "posixacl";
relatime = "on";
xattr = "sa";
snapshot = {
autoSnapshot = true;
blankSnapshot = true;
};
};
"nix" = {
type = "zfs_fs";
mount = {
enable = true;
mountPoint = "/nix";
};
snapshot = {
autoSnapshot = false;
};
atime = "off";
relatime = "off";
};
};
replicate = {
"" = {
type = "zfs_fs";
};
"system/var/log" = {
type = "zfs_fs";
mount = {
enable = true;
mountPoint = "/var/log";
};
};
};
};
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.<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 = {
# 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";