1
Files
flake-nixinator/system/modules/impermanence/default.nix

196 lines
6.4 KiB
Nix

{
config,
lib,
mylib,
username,
...
}: let
inherit (config.modules) impermanence;
in {
options.modules.impermanence = import ./options.nix {inherit lib mylib;};
config = let
# NOTE: Setting user/group/mode only has an effect if the
# directory is created by impermanence!
m777 = "u=rwx,g=rwx,o=rwx";
m755 = "u=rwx,g=rx,o=rx";
m711 = "u=rwx,g=x,o=x";
m700 = "u=rwx,g=,o=";
m644 = "u=rw,g=r,o=r";
m600 = "u=rw,g=,o=";
m444 = "u=r,g=r,o=r";
mkDir = user: directory: mode: {
inherit directory mode;
user = config.users.users.${user}.name;
group = config.users.users.${user}.group;
};
mkFile = user: file: mode: {
inherit file;
parentDirectory = {
inherit mode;
user = config.users.users.${user}.name;
group = config.users.users.${user}.group;
};
};
in
lib.mkIf impermanence.enable {
environment.persistence."/persist" = let
mkRDir = mkDir "root";
mkRFile = mkFile "root";
mkUDir = mkDir "${username}";
mkUFile = mkFile "${username}";
in {
hideMounts = true; # Sets x-gvfs-hide option
files = [
(mkRFile "/etc/adjtime" m644)
(mkRFile "/etc/machine-id" m444)
];
directories = [
(mkRDir "/etc/NetworkManager" m755)
(mkRDir "/etc/secureboot" m755)
(mkRDir "/etc/ssh" m755)
# https://github.com/nix-community/impermanence/issues/253
(mkRDir "/usr/systemd-placeholder" m755)
(mkRDir "/var/db/sudo" m711)
(mkRDir "/var/lib/bluetooth" m755) # m700
(mkRDir "/var/lib/containers" m755)
(mkRDir "/var/lib/flatpak" m755)
(mkRDir "/var/lib/NetworkManager" m755)
(mkRDir "/var/lib/libvirt" m755)
(mkRDir "/var/lib/nixos" m755)
(mkRDir "/var/lib/systemd" m755)
(mkRDir "/var/tmp" m777)
];
users.${username} = {
files = [
# (mkUFile ".ssh/known_hosts" m755) # m644
#
# (mkUFile ".secrets/spotify_client_id" m755) # m644
# (mkUFile ".secrets/spotify_client_secret" m755) # m644
# (mkUFile ".secrets/youtube_music_cookies" m755) # m644
# (mkUFile ".secrets/age/age.key" m755) # m600
];
directories = [
(mkUDir "Downloads" m755)
(mkUDir "Documents" m755)
(mkUDir "GitRepos" m755)
(mkUDir "NixFlake" m755)
(mkUDir "Notes" m755)
(mkUDir "Pictures" m755)
(mkUDir "Projects" m755)
(mkUDir "Public" m755)
(mkUDir "Unity" m755)
(mkUDir "Videos" m755)
(mkUDir ".gnupg" m755) # m600
(mkUDir ".secrets" m755) # m644
(mkUDir ".ssh" m755) # m644
(mkUDir ".mozilla/firefox" m755) # TODO: Remove this someday
(mkUDir ".mozilla/native-messaging-hosts" m755)
(mkUDir ".nix-package-search" m755)
(mkUDir ".ollama" m755)
(mkUDir ".var/app" m755)
(mkUDir ".vim/undo" m755)
(mkUDir ".cache/fish/generated_completions" m755)
(mkUDir ".cache/nix-index" m755)
(mkUDir ".cache/nvim" m755)
(mkUDir ".config/beets" m755)
(mkUDir ".config/chromium" m755) # TODO: Remove this someday
(mkUDir ".config/Ferdium" m755)
(mkUDir ".config/fish/completions" m755)
(mkUDir ".config/kdeconnect" m755)
(mkUDir ".config/keepassxc" m755)
(mkUDir ".config/Msty" m755)
(mkUDir ".config/Nextcloud" m755)
(mkUDir ".local/share/direnv" m755)
(mkUDir ".local/share/flatpak" m755)
(mkUDir ".local/share/keyrings" m755) # m700
(mkUDir ".local/share/nix" m755)
(mkUDir ".local/share/nvim/sessions" m755)
(mkUDir ".local/share/zoxide" m755)
(mkUDir ".local/state/astal/notifd" m755)
(mkUDir ".local/state/nvim" m755)
];
};
};
# Because we have a LUKS encrypted drive
# we use a systemd service to cleanup the volumes
boot.initrd.systemd = {
enable = true;
services.btrfs-volume-cleanup = let
backupDuration = "7"; # Days
mountDir = "/btrfs_tmp";
in {
description = "Clean btrfs subvolumes for impermanence";
wantedBy = ["initrd.target"];
after = ["dev-mapper-crypted.device"];
before = ["sysroot.mount"];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
path = ["/bin" config.system.build.extraUtils];
script = ''
mkdir -p ${mountDir}
mount -o subvol=/ /dev/mapper/crypted ${mountDir}
# Backup old root subvolume
if [[ -e ${mountDir}/root ]]; then
mkdir -p ${mountDir}/old_roots
timestamp=$(date --date="@$(stat -c %Y ${mountDir}/root)" "+%Y-%m-%-d_%H:%M:%S")
mv ${mountDir}/root "${mountDir}/old_roots/$timestamp"
fi
# Backup old home subvolume
if [[ -e ${mountDir}/home ]]; then
mkdir -p ${mountDir}/old_homes
timestamp=$(date --date="@$(stat -c %Y ${mountDir}/home)" "+%Y-%m-%-d_%H:%M:%S")
mv ${mountDir}/home "${mountDir}/old_homes/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for subvol in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "${mountDir}/$subvol"
done
btrfs subvolume delete "$1"
}
# Delete old roots
for old_root in $(find ${mountDir}/old_roots/ -maxdepth 1 -mtime +${backupDuration}); do
delete_subvolume_recursively "$old_root"
done
# Delete old homes
for old_home in $(find ${mountDir}/old_homes/ -maxdepth 1 -mtime +${backupDuration}); do
delete_subvolume_recursively "$old_home"
done
# Create new root + home subvolumes
btrfs subvolume create ${mountDir}/root
btrfs subvolume create ${mountDir}/home
umount ${mountDir}
rmdir ${mountDir}
'';
};
};
};
}