Files
nix-config/modules/nixos/impermanence.nix
Jordan Holt 65af220200
All checks were successful
Check flake / build-amd64-linux (push) Successful in 1m23s
treewide: impermanence configuration
2025-08-18 22:26:20 +01:00

145 lines
3.7 KiB
Nix

{
config,
pkgs,
lib,
...
}:
let
inherit (lib)
attrNames
flip
isAttrs
mapAttrs
mkIf
mkMerge
mkOption
optionals
types
;
in
{
boot.zfs.forceImportRoot = false;
boot.initrd.systemd.enable = true;
boot.initrd.systemd.services.impermanence-rollback =
mkIf
(config.environment.persistence."/persist".enable || config.environment.persistence."/state".enable)
{
description = "Rollback root filesystem";
wantedBy = [ "initrd.target" ];
after = [ "zfs-import-rpool.service" ];
before = [ "sysroot.mount" ];
unitConfig.DefaultDependencies = "no";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.zfs}/bin/zfs rollback -r rpool/local/root@blank";
};
};
age.identityPaths = [ "/persist/etc/ssh/ssh_host_ed25519_key" ];
fileSystems."/state" = mkIf config.environment.persistence."/state".enable {
neededForBoot = true;
};
environment.persistence."/state" = {
enable = false;
hideMounts = true;
directories = [
"/var/lib/systemd"
"/var/log"
"/var/spool"
];
};
fileSystems."/persist" = mkIf config.environment.persistence."/persist".enable {
neededForBoot = true;
};
environment.persistence."/persist" = {
enable = false;
hideMounts = true;
files = [
(mkIf (!config.boot.isContainer) "/etc/machine-id")
"/etc/adjtime"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
];
directories = [
"/var/lib/nixos"
]
++ optionals config.security.acme.acceptTerms [
{
directory = "/var/lib/acme";
user = "acme";
group = "acme";
mode = "0755";
}
]
++ optionals config.services.printing.enable [
{
directory = "/var/lib/cups";
mode = "0700";
}
]
++ optionals config.hardware.bluetooth.enable [
"/var/lib/bluetooth"
];
};
users.mutableUsers = !config.environment.persistence."/persist".enable;
# For each user that has a home-manager config, merge the locally defined
# persistence options that we defined above.
imports =
let
mkUserFiles = map (
x: { parentDirectory.mode = "700"; } // (if isAttrs x then x else { file = x; })
);
mkUserDirs = map (x: { mode = "700"; } // (if isAttrs x then x else { directory = x; }));
in
[
{
environment.persistence = mkMerge (
flip map (attrNames config.home-manager.users) (
user:
let
hmUserCfg = config.home-manager.users.${user};
in
flip mapAttrs hmUserCfg.home.persistence (
_: sourceCfg: {
users.${user} = {
files = mkUserFiles sourceCfg.files;
directories = mkUserDirs sourceCfg.directories;
};
}
)
)
);
}
];
home-manager.sharedModules = [
{
options.home.persistence = mkOption {
description = "Additional persistence config for the given source path";
default = { };
type = types.attrsOf (
types.submodule {
options = {
files = mkOption {
description = "Additional files to persist via NixOS impermanence.";
type = types.listOf (types.either types.attrs types.str);
default = [ ];
};
directories = mkOption {
description = "Additional directories to persist via NixOS impermanence.";
type = types.listOf (types.either types.attrs types.str);
default = [ ];
};
};
}
);
};
}
];
}