From 53f25d04805cd356c2fa22f318d62a41fe8501d5 Mon Sep 17 00:00:00 2001 From: NullBite Date: Sat, 20 Apr 2024 04:03:27 -0400 Subject: [PATCH] nullbox: add proof-of-concept impermanence --- hosts/nullbox/configuration.nix | 2 + hosts/nullbox/impermanence.nix | 115 ++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 hosts/nullbox/impermanence.nix diff --git a/hosts/nullbox/configuration.nix b/hosts/nullbox/configuration.nix index 1175355..917002f 100644 --- a/hosts/nullbox/configuration.nix +++ b/hosts/nullbox/configuration.nix @@ -13,6 +13,8 @@ # Encryption ./luks.nix ./mcserver.nix + + ./impermanence.nix ]; config = { diff --git a/hosts/nullbox/impermanence.nix b/hosts/nullbox/impermanence.nix new file mode 100644 index 0000000..dfef31c --- /dev/null +++ b/hosts/nullbox/impermanence.nix @@ -0,0 +1,115 @@ +{ pkgs, config, lib, ... }: +let + mkBtrfsInit = { prefix ? "", + volume }: + '' + mkdir /btrfs_tmp + mount ${volume} /btrfs_tmp -o subvol=/ + + # unix is fine with multiple consecutive slashes if prefix is empty or + # contains a leading or trailing slash + mkdir -p "/btrfs_tmp/${prefix}/" + + if [[ -e "/btrfs_tmp/${prefix}/volatile" ]] ; then + mkdir -p "/btrfs_tmp/${prefix}/old_roots" + timestamp=$(date --date="@$(stat -c %Y "/btrfs_tmp/${prefix}/volatile")" "+%Y-%m-%-d_%H:%M:%S") + mv "/btrfs_tmp/${prefix}/volatile" "/btrfs_tmp/${prefix}/old_roots/$timestamp" + fi + + delete_subvolume_recursively() { + IFS=$'\n' + for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do + delete_subvolume_recursively "/btrfs_tmp/$i" + done + # btrfs subvolume delete "$1" + echo would run: btrfs subvolume delete "$1" + echo remove this echo once you see this message + + } + + for i in $(find /btrfs_tmp/${prefix}/old_roots/ -maxdepth 1 -mtime +30); do + delete_subvolume_recursively "$i" + done + + btrfs subvolume create /btrfs_tmp/${prefix}/volatile + + echo new root created + sleep 1 + + umount /btrfs_tmp + ''; + + root_vol = "/dev/archdesktop/root"; +in { + config = { + fileSystems."/persistent" = { + neededForBoot = true; + device = root_vol; + fsType = "btrfs"; + options = [ "subvol=/nixos/@persistent" ]; + }; + + boot.initrd.postDeviceCommands = lib.mkAfter (mkBtrfsInit { prefix = "nixos"; volume = root_vol; }); + fileSystems."/" = lib.mkForce { + device = root_vol; + fsType = "btrfs"; + options = [ "subvol=/nixos/volatile" ]; + }; + environment.persistence = { + "/persistent/nobackup" = { + hideMounts = true; + directories = [ + "/var/lib/systemd/coredump" + "/var/lib/flatpak" + ]; + + files = [ + "/var/lib/systemd/random-seed" + ]; + }; + + "/persistent/backup" = { + hideMounts = true; + directories = [ + # this affects generation/consistency of uids and gids, and should + # probably NEVER be excluded removed. + "/var/lib/nixos/" + # password files for user.user..hashedPasswordFile + { directory = "/etc/passfile"; mode = "0700"; } + + # persistent non-declarative config + "/etc/nixos" + "/etc/ssh" + { directory = "/etc/wireguard"; mode = "0700"; } + + # let's keep the root home dir as well + { directory = "/root"; mode = "0700"; } + + # system state + "/var/lib/bluetooth" + "/var/lib/blueman" + "/var/lib/cups" + "/var/lib/NetworkManager" + "/var/lib/power-profiles-daemon" + "/var/lib/systemd/rfkill" + { directory = "/var/lib/tailscale"; mode = "0700"; } + "/var/lib/unbound" + "/var/db/sudo/lectured" + "/var/log" + + # remember login stuff + "/var/cache/tuigreet" + ]; + + files = [ + "/etc/machine-id" + ]; + }; + }; + + users.mutableUsers = false; + users.users.nullbite.hashedPasswordFile = "/persistent/passfile/nullbite"; + users.users.nullbite.initialPassword = null; + users.users.root.hashedPasswordFile = "/persistent/passfile/root"; + }; +}