From adda550db2a937fa2b2847a596c73121a7f86c1b Mon Sep 17 00:00:00 2001 From: Dmitriy Kholkin Date: Sat, 7 Jun 2025 17:20:39 +0300 Subject: [PATCH] feat: split persist module onto nixos and home ones --- hosts/andromedae/default.nix | 7 +++ modules/home/persist/default.nix | 80 ++++++++++++++++++++++--- modules/nixos/persist/default.nix | 99 ++++++------------------------- 3 files changed, 99 insertions(+), 87 deletions(-) diff --git a/hosts/andromedae/default.nix b/hosts/andromedae/default.nix index 2e77841..ebafd99 100644 --- a/hosts/andromedae/default.nix +++ b/hosts/andromedae/default.nix @@ -38,6 +38,13 @@ in # Home-manager home-manager.users.${defaultUser} = { ataraxia.defaults.role = "desktop"; + + persist.state.directories = [ + ".config/sops/age" + "nixos-config" + "projects" + ]; + home.stateVersion = "25.05"; }; diff --git a/modules/home/persist/default.nix b/modules/home/persist/default.nix index b0182d7..af573a3 100644 --- a/modules/home/persist/default.nix +++ b/modules/home/persist/default.nix @@ -1,17 +1,23 @@ { config, lib, + pkgs, ... }: let inherit (lib) + escapeShellArg mkEnableOption mkIf mkOption recursiveUpdate ; inherit (lib.types) listOf path str; + inherit (builtins) concatMap; cfg = config.persist; + username = config.home.username; + homeDir = config.home.homeDirectory; + absoluteHomePath = map (x: "${homeDir}/${x}"); in { options = @@ -32,7 +38,7 @@ in enable = mkEnableOption "A tmpfs root with explicit opt-in state"; persistRoot = mkOption { type = path; - default = "/persist"; + default = "/persist${config.home.homeDirectory}"; }; # Stuff that matters # TODO backups @@ -53,11 +59,71 @@ in }; }; - config = mkIf cfg.enable { - # Persist by default - persist.cache.directories = [ ".cache" ]; - persist.state = { - directories = [ ".local/share/nix" ]; + # TODO: filter persist paths like in nixos module + config = + let + takeAll = what: concatMap (x: x.${what}); + persists = with cfg; [ + state + cache + ]; + allFiles = takeAll "files" persists; + allDirs = takeAll "directories" persists; + in + mkIf cfg.enable { + home.persistence.${cfg.persistRoot} = { + allowOther = true; + directories = allDirs; + files = allFiles; + }; + + # Persist by default + persist.cache.directories = [ ".cache" ]; + persist.state = { + directories = [ + "Downloads" + "Documents" + "Music" + "Pictures" + "Videos" + ".config/dconf" + ".local/share/nix" + ".ssh" + # { directory = ".ssh"; mode = "0700"; } + ]; + }; + + systemd.user = mkIf cfg.cache.clean.enable { + services."persist-cache-cleanup-${username}" = { + Unit = { + Description = "Cleaning up cache files and directories for user ${username}"; + Wants = [ "modprobed-db.timer" ]; + }; + Service = { + ExecStart = pkgs.writeShellScript "" '' + ${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) + )} + ''; + Type = "simple"; + }; + Install.WantedBy = [ "default.target" ]; + }; + timers."persist-cache-cleanup-${username}" = { + Unit = { + Description = "Run persist-cache-cleanup-${username} service by set schedule"; + PartOf = [ "persist-cache-cleanup-${username}.service" ]; + }; + Timer = { + Persistent = true; + OnCalendar = cfg.cache.clean.dates; + }; + Install.WantedBy = [ "timers.target" ]; + }; + }; }; - }; } diff --git a/modules/nixos/persist/default.nix b/modules/nixos/persist/default.nix index e1b953a..d89df3e 100644 --- a/modules/nixos/persist/default.nix +++ b/modules/nixos/persist/default.nix @@ -7,28 +7,25 @@ let inherit (lib) escapeShellArg - filterAttrs - mapAttrs - mapAttrs' + hasPrefix + hasSuffix mkEnableOption + mkDefault mkIf - mkMerge mkOption - nameValuePair - optionalAttrs - pipe + optionalString recursiveUpdate - removePrefix - subtractLists unique ; inherit (lib.types) listOf path str; - inherit (builtins) concatMap; + inherit (builtins) any concatMap filter; cfg = config.persist; btrfs = config.ataraxia.filesystems.btrfs.mountpoints; zfs = config.ataraxia.filesystems.zfs.mountpoints; - mountpoints = unique (btrfs ++ zfs); + mountpoints = map (x: "${x}${optionalString (!(hasSuffix "/" x)) "/"}") (unique (btrfs ++ zfs)); + + subtractListsPrefix = a: filter (dir: !(any (pref: hasPrefix pref dir) a)); in { imports = [ inputs.impermanence.nixosModules.impermanence ]; @@ -74,12 +71,6 @@ in 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 @@ -88,79 +79,27 @@ in allFiles = takeAll "files" persists; allDirectories = takeAll "directories" persists; # Remove btrfs + zfs mountpoints from list of dirs to persist - filteredDirs = subtractLists mountpoints allDirectories; - - userPersists = mapAttrs (_: cfg: cfg.persist) ( - { } // optionalAttrs (builtins.hasAttr "home-manager" config) config.home-manager.users - ); - usersFlatten = mapAttrs ( - name: cfg: - let - persists = with cfg; [ - state - cache - ]; - allHomeFiles = takeAll "files" persists; - allHomeDirectories = takeAll "directories" persists; - # Remove btrfs + zfs mountpoints from list of dirs to persist - home = "/home/${name}"; - filteredDirs = pipe allHomeDirectories [ - (map (x: "${home}/${x}")) - (xs: subtractLists mountpoints xs) - (map (x: removePrefix home x)) - ]; - in - { - inherit home; - directories = filteredDirs; - files = allHomeFiles; - } - ) userPersists; + filteredDirs = subtractListsPrefix mountpoints allDirectories; in mkIf cfg.enable { environment.persistence.${cfg.persistRoot} = { hideMounts = true; directories = filteredDirs; files = allFiles; - users = usersFlatten; + # 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) - )} + programs.fuse.userAllowOther = mkDefault true; - ${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)} + systemd.services.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; - }; - } - ]; + ${builtins.concatStringsSep "\n" (map (x: "rm -rf ${escapeShellArg x}") cfg.cache.directories)} + ''; + startAt = cfg.cache.clean.dates; + }; fileSystems.${cfg.persistRoot}.neededForBoot = true; # Persist by default