148 lines
3.9 KiB
Nix

{
config,
lib,
inputs,
...
}:
let
inherit (lib)
escapeShellArg
filterAttrs
mapAttrs
mapAttrs'
mkEnableOption
mkIf
mkMerge
mkOption
nameValuePair
;
inherit (lib.types) listOf path str;
inherit (builtins) concatMap;
cfg = config.persist;
in
{
imports = [ inputs.impermanence.nixosModules.impermanence ];
options =
let
common = {
directories = mkOption {
type = listOf str;
default = [ ];
};
files = mkOption {
type = listOf str;
default = [ ];
};
};
in
{
persist = {
enable = mkEnableOption "A tmpfs root with explicit opt-in state";
persistRoot = mkOption {
type = path;
default = "/persist";
};
# Stuff that matters
# TODO backups
state = {
# backup = {...};
} // common;
# Stuff that's just there to speed up the system
cache = {
clean = {
enable = mkEnableOption "cleaning the cache files and directories";
dates = mkOption {
type = str;
default = "weekly";
description = "A systemd.time calendar description of when to clean the cache files";
};
};
} // common;
};
};
config =
let
# TODO: fix infinite recursion (can't get user home directory)
# userPersists = lib.mapAttrs (name: cfg:
# cfg.persist // {
# home = config.users.users.${name}.home;
# }
# ) config.home-manager.users;
takeAll = what: concatMap (x: x.${what});
persists = with cfg; [
state
cache
];
allFiles = takeAll "files" persists;
allDirectories = takeAll "directories" persists;
userPersists = mapAttrs (_: cfg: cfg.persist) config.home-manager.users;
usersFlatten = mapAttrs (
name: cfg:
let
persists = with cfg; [
state
cache
];
allHomeFiles = takeAll "files" persists;
allHomeDirectories = takeAll "directories" persists;
in
{
home = "/home/${name}";
directories = allHomeDirectories;
files = allHomeFiles;
}
) userPersists;
in
mkIf cfg.enable {
# Persist users uid by default
persist.state.directories = [ "/var/lib/nixos" ];
environment.persistence.${cfg.persistRoot} = {
hideMounts = true;
directories = allDirectories;
files = allFiles;
users = usersFlatten;
};
systemd.services =
let
filtered = filterAttrs (_: cfg: cfg.cache.clean.enable) userPersists;
in
mkMerge [
(mapAttrs' (
name: cfg:
let
absoluteHomePath = map (x: "/home/${name}/${x}");
in
nameValuePair "persist-cache-cleanup-${name}" {
description = "Cleaning up cache files and directories for user ${name}";
script = ''
${builtins.concatStringsSep "\n" (
map (x: "rm ${escapeShellArg x}") (absoluteHomePath cfg.cache.files)
)}
${builtins.concatStringsSep "\n" (
map (x: "rm -rf ${escapeShellArg x}") (absoluteHomePath cfg.cache.directories)
)}
'';
startAt = cfg.cache.clean.dates;
}
) filtered)
{
persist-cache-cleanup = mkIf cfg.cache.clean.enable {
description = "Cleaning up cache files and directories";
script = ''
${builtins.concatStringsSep "\n" (map (x: "rm ${escapeShellArg x}") cfg.cache.files)}
${builtins.concatStringsSep "\n" (map (x: "rm -rf ${escapeShellArg x}") cfg.cache.directories)}
'';
startAt = cfg.cache.clean.dates;
};
}
];
};
}