230 lines
6.2 KiB
Nix
230 lines
6.2 KiB
Nix
{ config, pkgs, lib, inputs, ... }:
|
|
let
|
|
cfg = config.persist;
|
|
|
|
takeAll = what: concatMap (x: x.${what});
|
|
|
|
persists = with cfg; [ state derivative cache ];
|
|
|
|
absoluteHomePath = map (x: "${cfg.homeDir}/${x}");
|
|
|
|
allFiles = takeAll "files" persists;
|
|
|
|
allHomeFiles = takeAll "homeFiles" persists;
|
|
|
|
allDirectories = takeAll "directories" persists;
|
|
|
|
allHomeDirectories = takeAll "homeDirectories" persists;
|
|
|
|
inherit (builtins) concatMap;
|
|
inherit (lib) mkIf;
|
|
|
|
homeDirectory = config.home-manager.users.${config.mainuser}.home.homeDirectory or /home/${config.mainuser};
|
|
in {
|
|
options = let
|
|
inherit (lib) mkOption mkEnableOption;
|
|
inherit (lib.types) listOf path str either submodule enum;
|
|
|
|
# defaultPerms = {
|
|
# mode = "0755";
|
|
# user = "root";
|
|
# group = "root";
|
|
# };
|
|
# dirPermsOpts = { user, group, mode }: {
|
|
# user = mkOption {
|
|
# type = str;
|
|
# default = user;
|
|
# };
|
|
# group = mkOption {
|
|
# type = str;
|
|
# default = group;
|
|
# };
|
|
# mode = mkOption {
|
|
# type = str;
|
|
# default = mode;
|
|
# };
|
|
# };
|
|
# fileOpts = perms: {
|
|
# options = {
|
|
# file = mkOption {
|
|
# type = str;
|
|
# };
|
|
# parentDirectory = dirPermsOpts perms;
|
|
# };
|
|
# };
|
|
# dirOpts = perms: {
|
|
# options = {
|
|
# directory = mkOption {
|
|
# type = str;
|
|
# };
|
|
# } // (dirPermsOpts perms);
|
|
# };
|
|
# userDefaultPerms = {
|
|
# inherit (defaultPerms) mode;
|
|
# user = config.mainuser;
|
|
# group = config.users.${userDefaultPerms.user}.group;
|
|
# };
|
|
# rootFile = submodule [
|
|
# (fileOpts defaultPerms)
|
|
# ];
|
|
# rootDir = submodule [
|
|
# (dirOpts defaultPerms)
|
|
# ];
|
|
# userFile = submodule [
|
|
# (fileOpts userDefaultPerms)
|
|
# ];
|
|
# userDir = submodule [
|
|
# (dirOpts userDefaultPerms)
|
|
# ];
|
|
|
|
common = {
|
|
directories = mkOption {
|
|
# type = listOf (either str (submodule {
|
|
# options = {
|
|
# directory = mkOption {
|
|
# type = str;
|
|
# default = null;
|
|
# };
|
|
# user = mkOption {
|
|
# type = str;
|
|
# default = "root";
|
|
# };
|
|
# group = mkOption {
|
|
# type = str;
|
|
# default = "root";
|
|
# };
|
|
# mode = mkOption {
|
|
# type = str;
|
|
# default = "0755";
|
|
# };
|
|
# };
|
|
# }));
|
|
# type = listOf (either str rootDir);
|
|
type = listOf str;
|
|
default = [ ];
|
|
};
|
|
files = mkOption {
|
|
# type = listOf (either str rootFile);
|
|
type = listOf str;
|
|
default = [ ];
|
|
};
|
|
homeFiles = mkOption {
|
|
# type = listOf (either str userFile);
|
|
type = listOf str;
|
|
default = [ ];
|
|
};
|
|
homeDirectories = mkOption {
|
|
# type = listOf (either str (submodule {
|
|
# options = {
|
|
# directory = mkOption {
|
|
# type = str;
|
|
# default = null;
|
|
# };
|
|
# method = mkOption {
|
|
# type = enum [ "bindfs" "symlink" ];
|
|
# default = "bindfs";
|
|
# };
|
|
# };
|
|
# }));
|
|
# type = listOf (either str userDir);
|
|
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 = homeDirectory;
|
|
};
|
|
|
|
# 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 ];
|
|
|
|
config = mkIf cfg.enable {
|
|
environment.persistence.${cfg.persistRoot} = {
|
|
hideMounts = true;
|
|
directories = allDirectories;
|
|
files = allFiles;
|
|
users.${config.mainuser} = {
|
|
home = "/home/${config.mainuser}";
|
|
directories = allHomeDirectories;
|
|
files = allHomeFiles;
|
|
};
|
|
};
|
|
|
|
fileSystems."/" = lib.mkIf (config.deviceSpecific.devInfo.fileSystem != "zfs") {
|
|
device = "none";
|
|
options = [ "defaults" "size=2G" "mode=755" ];
|
|
fsType = "tmpfs";
|
|
};
|
|
|
|
boot.initrd = lib.mkIf (config.deviceSpecific.devInfo.fileSystem != "zfs") {
|
|
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
|
|
'';
|
|
};
|
|
|
|
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}")
|
|
(cfg.cache.files
|
|
++ absoluteHomePath cfg.cache.homeFiles))}
|
|
|
|
${builtins.concatStringsSep "\n" (map (x: "rm -rf ${lib.escapeShellArg x}")
|
|
(cfg.cache.directories ++ absoluteHomePath cfg.cache.homeDirectories))}
|
|
'';
|
|
startAt = cfg.cache.clean.dates;
|
|
};
|
|
|
|
system.activationScripts = {
|
|
homedir.text = builtins.concatStringsSep "\n" (map (dir: ''
|
|
mkdir -p ${cfg.persistRoot}${dir}
|
|
chown ${config.mainuser}:users ${cfg.persistRoot}${dir}
|
|
'') (
|
|
(builtins.filter (lib.hasPrefix cfg.homeDir) allDirectories)
|
|
++ absoluteHomePath allHomeDirectories
|
|
));
|
|
};
|
|
};
|
|
}
|