nixos-config/modules/persist.nix

143 lines
3.8 KiB
Nix

{ config, pkgs, lib, inputs, ... }:
let
cfg = config.persist;
takeAll = what: concatMap (x: x.${what});
persists = with cfg; [ state derivative cache ];
absoluteHomeFiles = map (x: "${cfg.homeDir}/${x}");
allHomeFiles = takeAll "homeFiles" persists;
absoluteEtcFiles = map (x: "/etc/${x}");
allEtcFiles = absoluteEtcFiles (takeAll "etcFiles" persists);
allDirectories = takeAll "directories" persists;
inherit (builtins) concatMap;
inherit (lib) mkIf;
in {
options = let
inherit (lib) mkOption mkEnableOption;
inherit (lib.types) listOf path str;
common = {
directories = mkOption {
type = listOf path;
default = [ ];
};
etcFiles = mkOption {
type = listOf str;
default = [ ];
};
homeFiles = mkOption {
type = listOf str;
default = [ ];
};
};
in {
persist = {
enable = mkEnableOption "a tmpfs root with explicit opt-in state";
persistRoot = mkOption {
type = path;
default = "/persist";
};
homeDir = mkOption {
type = path;
default = "/home/balsoft";
};
# Stuff that matters
# TODO backups of this stuff
state = {
# backup = {...};
} // common;
# Stuff that can be computed from declarative+state, but is never invalidated (so shouldn't be cleaned up)
derivative = common;
# Stuff that's just there to speed up the system
# It's cleaned up regularly, to solve the cache invalidation problem once and for all
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;
};
};
imports = [
inputs.impermanence.nixosModules.impermanence
# Eugh
(let
module = (import "${inputs.impermanence}/home-manager.nix" {
inherit pkgs lib;
config = lib.recursiveUpdate config.home-manager.users.balsoft {
home.persistence."${cfg.persistRoot}${cfg.homeDir}" = {
directories = [ ];
files = allHomeFiles;
allowOther = false;
removePrefixDirectory = false;
};
};
});
in {
config.home-manager.users.balsoft = lib.mkIf cfg.enable module.config;
})
];
config = mkIf cfg.enable {
environment.persistence.${cfg.persistRoot} = {
directories = allDirectories;
files = allEtcFiles;
};
fileSystems."/" = {
device = "none";
options = [ "defaults" "size=4G" "mode=755" ];
fsType = "tmpfs";
};
boot.initrd.postMountCommands = assert config.fileSystems
? ${cfg.persistRoot}
&& config.fileSystems.${cfg.persistRoot}.neededForBoot; ''
mkdir -p /mnt-root/nix
mount --bind /mnt-root${cfg.persistRoot}/nix /mnt-root/nix
chmod 755 /mnt-root
'';
# Euuuugh
systemd.services.persist-cache-cleanup = lib.mkIf cfg.cache.clean.enable {
description = "Cleaning up cache files and directories";
script = ''
${builtins.concatStringsSep "\n" (map (x: "rm ${lib.escapeShellArg x}")
(absoluteEtcFiles cfg.cache.etcFiles
++ absoluteHomeFiles cfg.cache.homeFiles))}
${builtins.concatStringsSep "\n"
(map (x: "rm -rf ${lib.escapeShellArg x}") cfg.cache.directories)}
'';
startAt = cfg.cache.clean.dates;
};
system.activationScripts = {
homedir.text = builtins.concatStringsSep "\n" (map (dir: ''
mkdir -p ${cfg.persistRoot}${dir}
chown balsoft:users ${cfg.persistRoot}${dir}
'') (builtins.filter (lib.hasPrefix "/home/balsoft") allDirectories));
};
};
}