2022-02-12 01:53:57 +00:00
|
|
|
{ lib, pkgs, inputs, config, ... }:
|
2022-02-09 20:41:51 +00:00
|
|
|
let
|
2022-02-12 01:53:57 +00:00
|
|
|
inherit (lib) concatStringsSep mkIf mkDefault mkMerge mkVMOverride;
|
2022-02-11 13:26:33 +00:00
|
|
|
inherit (lib.my) mkOpt mkBoolOpt mkVMOverride' dummyOption;
|
2022-02-09 20:41:51 +00:00
|
|
|
|
|
|
|
cfg = config.my.tmproot;
|
|
|
|
|
|
|
|
showUnsaved =
|
|
|
|
''
|
|
|
|
#!${pkgs.python310}/bin/python
|
|
|
|
import stat
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
|
|
|
|
ignored = [
|
|
|
|
${concatStringsSep ",\n " (map (p: "'${p}'") cfg.ignoreUnsaved)}
|
|
|
|
]
|
|
|
|
|
|
|
|
base = '/'
|
|
|
|
base_dev = os.stat(base).st_dev
|
|
|
|
|
|
|
|
def recurse(p, link=None):
|
|
|
|
try:
|
|
|
|
for ignore in ignored:
|
|
|
|
if p.startswith(ignore):
|
|
|
|
return
|
|
|
|
|
|
|
|
st = os.lstat(p)
|
|
|
|
if st.st_dev != base_dev:
|
|
|
|
return
|
|
|
|
|
|
|
|
if stat.S_ISLNK(st.st_mode):
|
|
|
|
target = os.path.realpath(p, strict=False)
|
|
|
|
if os.access(target, os.F_OK):
|
|
|
|
recurse(target, link=p)
|
|
|
|
return
|
|
|
|
elif stat.S_ISDIR(st.st_mode):
|
|
|
|
for e in os.listdir(p):
|
|
|
|
recurse(os.path.join(p, e))
|
|
|
|
return
|
|
|
|
|
|
|
|
print(link or p)
|
|
|
|
except PermissionError as ex:
|
|
|
|
print(f'{p}: {ex.strerror}', file=sys.stderr)
|
|
|
|
|
|
|
|
recurse(base)
|
|
|
|
'';
|
2022-02-11 01:15:24 +00:00
|
|
|
|
|
|
|
rootDef = {
|
|
|
|
device = "yeet";
|
|
|
|
fsType = "tmpfs";
|
|
|
|
options = [ "size=${cfg.size}" ];
|
|
|
|
};
|
2022-02-09 20:41:51 +00:00
|
|
|
in {
|
2022-02-12 01:53:57 +00:00
|
|
|
imports = [ inputs.impermanence.nixosModule ];
|
|
|
|
|
|
|
|
options = {
|
|
|
|
my.tmproot = with lib.types; {
|
|
|
|
enable = mkBoolOpt true;
|
|
|
|
persistDir = mkOpt str "/persist";
|
|
|
|
size = mkOpt str "2G";
|
|
|
|
ignoreUnsaved = mkOpt (listOf str) [
|
|
|
|
"/tmp"
|
|
|
|
];
|
|
|
|
};
|
2022-02-09 20:41:51 +00:00
|
|
|
|
2022-02-12 01:53:57 +00:00
|
|
|
# Forward declare options that won't exist until the VM module is actually imported
|
|
|
|
virtualisation = {
|
|
|
|
diskImage = dummyOption;
|
|
|
|
};
|
2022-02-11 13:26:33 +00:00
|
|
|
};
|
|
|
|
|
2022-02-12 01:53:57 +00:00
|
|
|
config = mkIf cfg.enable (mkMerge [
|
|
|
|
{
|
2022-02-11 01:15:24 +00:00
|
|
|
assertions = [
|
|
|
|
{
|
|
|
|
assertion = config.fileSystems ? "${cfg.persistDir}";
|
|
|
|
message = "The 'fileSystems' option does not specify your persistence file system (${cfg.persistDir}).";
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
environment.systemPackages = [
|
|
|
|
(pkgs.writeScriptBin "tmproot-unsaved" showUnsaved)
|
|
|
|
];
|
|
|
|
|
|
|
|
environment.persistence."${cfg.persistDir}" = {
|
|
|
|
hideMounts = mkDefault true;
|
|
|
|
directories = [
|
|
|
|
"/var/log"
|
|
|
|
];
|
|
|
|
files = [
|
|
|
|
"/etc/machine-id"
|
|
|
|
];
|
|
|
|
};
|
|
|
|
|
|
|
|
fileSystems."/" = rootDef;
|
|
|
|
|
2022-02-11 13:26:33 +00:00
|
|
|
virtualisation = {
|
2022-02-11 01:15:24 +00:00
|
|
|
diskImage = "./.vms/${config.system.name}-persist.qcow2";
|
|
|
|
};
|
2022-02-12 01:53:57 +00:00
|
|
|
}
|
|
|
|
(mkIf config.my.boot.isDevVM {
|
2022-02-11 01:15:24 +00:00
|
|
|
fileSystems = mkVMOverride {
|
|
|
|
"/" = mkVMOverride' rootDef;
|
|
|
|
# Hijack the "root" device for persistence in the VM
|
|
|
|
"${cfg.persistDir}" = {
|
|
|
|
device = config.virtualisation.bootDevice;
|
|
|
|
neededForBoot = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
})
|
2022-02-12 01:53:57 +00:00
|
|
|
]);
|
2022-02-09 20:41:51 +00:00
|
|
|
}
|