diff --git a/modules/system/impermanence.nix b/modules/system/impermanence.nix index 28bcb89..ad10a1d 100644 --- a/modules/system/impermanence.nix +++ b/modules/system/impermanence.nix @@ -10,36 +10,50 @@ config = lib.mkIf config.nanuqsaurus.impermanence.enable { boot.initrd.supportedFilesystems = [ "btrfs" ]; - boot.initrd.postDeviceCommands = lib.mkAfter '' - mkdir -p /mnt - mount -t btrfs -o subvol=/ /dev/disk/by-label/nixos /mnt + # Reset the /root subvolume to a pristine snapshot on every boot. + # systemd stage-1 initrd does not support boot.initrd.postDeviceCommands, so + # this runs as an initrd systemd service, ordered after the labelled device + # appears and before the root filesystem is mounted (sysroot.mount). + # Note: `cut` (coreutils) is used instead of `awk`, which is not in the + # systemd initrd. + boot.initrd.systemd.services.rollback = { + description = "Rollback btrfs root subvolume to a pristine state"; + wantedBy = [ "initrd.target" ]; + after = [ "dev-disk-by\\x2dlabel-nixos.device" ]; + before = [ "sysroot.mount" ]; + unitConfig.DefaultDependencies = "no"; + serviceConfig.Type = "oneshot"; + script = '' + mkdir -p /mnt + mount -t btrfs -o subvol=/ /dev/disk/by-label/nixos /mnt - if [ ! -d /mnt/root-blank ]; then - btrfs subvolume snapshot -r /mnt/root /mnt/root-blank - fi - - if [ -d /mnt/root ]; then - if [ -d /mnt/root-previous ]; then - btrfs subvolume delete /mnt/root-previous + if [ ! -d /mnt/root-blank ]; then + btrfs subvolume snapshot -r /mnt/root /mnt/root-blank fi - btrfs subvolume snapshot /mnt/root /mnt/root-previous - while true; do - subvols="$(btrfs subvolume list -o /mnt/root | awk '{print $9}')" - if [ -z "$subvols" ]; then - break + if [ -d /mnt/root ]; then + if [ -d /mnt/root-previous ]; then + btrfs subvolume delete /mnt/root-previous fi - for subvol in $subvols; do - btrfs subvolume delete "/mnt/$subvol" + btrfs subvolume snapshot /mnt/root /mnt/root-previous + + while true; do + subvols="$(btrfs subvolume list -o /mnt/root | cut -f9 -d' ')" + if [ -z "$subvols" ]; then + break + fi + for subvol in $subvols; do + btrfs subvolume delete "/mnt/$subvol" + done done - done - btrfs subvolume delete /mnt/root - fi + btrfs subvolume delete /mnt/root + fi - btrfs subvolume snapshot /mnt/root-blank /mnt/root - umount /mnt - ''; + btrfs subvolume snapshot /mnt/root-blank /mnt/root + umount /mnt + ''; + }; fileSystems."/persist".neededForBoot = true;