{ config, lib, pkgs, ... }: with lib; let cfg = config.impermanence.rollback; in { options = { impermanence.rollback = { enable = mkEnableOption "rollback of the root filesystem"; device = mkOption { description = "Device to be wiped"; type = types.str; }; subvolume = mkOption { description = '' The subvolume to be rolled back. Usually, this should be where your root filesystem resides. ''; type = types.str; }; }; }; config = mkIf cfg.enable { boot.initrd.postDeviceCommands = '' # Mount the btrfs filesystem. mkdir -p /btrfs-tmp mount -t btrfs "${cfg.device}" /btrfs-tmp # If the moribound subvolume exists, send it do 'death row' (old-roots), # where live for about three days before its eventual deletion. if [[ -e "/btrfs-tmp/${cfg.subvolume}" ]]; then mkdir -p /btrfs-tmp/old-roots timestamp=$(date --date="@$(stat -c %Y "/btrfs-tmp/${cfg.subvolume}")" "+%Y-%m-%-d_%H:%M:%S") mv "/btrfs-tmp/${cfg.subvolume}" "/btrfs-tmp/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" } # Delete previous roots older than three days. # TODO: I would prefer archiving the last N previous roots, rather than # time. for i in $(find /btrfs-tmp/old-roots/ -maxdepth 1 -mtime +3); do delete_subvolume_recursively "$i" done btrfs subvolume create "/btrfs-tmp/${cfg.subvolume}" umount /btrfs-tmp ''; }; }