{ pkgs, inputs, lib, config, ... }: let cfg = config.custom.impermanence; in { options.custom.impermanence = { enable = lib.mkOption { type = lib.types.bool; default = true; description = "Enable impermanent root fs"; }; }; config = lib.mkIf cfg.enable { environment.persistence = { "/persist" = { directories = [ "/var/lib/nixos" "/home" ]; files = [ "/etc/machine-id" "/etc/ssh/ssh_host_ed25519_key" "/etc/ssh/ssh_host_ed25519_key.pub" "/etc/ssh/ssh_host_rsa_key" "/etc/ssh/ssh_host_rsa_key.pub" ]; }; }; fileSystems."/".options = [ "compress=zstd" "noatime" ]; fileSystems."/nix".options = [ "compress=zstd" "noatime" ]; fileSystems."/persist".options = [ "compress=zstd" "noatime" ]; fileSystems."/persist".neededForBoot = true; fileSystems."/var/log".options = [ "compress=zstd" "noatime" ]; fileSystems."/var/log".neededForBoot = true; users.mutableUsers = false; # rollback results in sudo lectures after each reboot security.sudo.extraConfig = '' Defaults lecture = never ''; # needed for allowOther in the home-manager impermanence config programs.fuse.userAllowOther = true; # reset / at each boot # Note `lib.mkBefore` is used instead of `lib.mkAfter` here. boot.initrd.postDeviceCommands = pkgs.lib.mkBefore '' mkdir /mnt mount ${config.fileSystems."/".device} /mnt if [[ -e /mnt/root ]]; then mkdir -p /mnt/old_roots timestamp=$(date --date="@$(stat -c %Y /mnt/root)" "+%Y-%m-%-d_%H:%M:%S") mv /mnt/root "/mnt/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 "/mnt/$i" done btrfs subvolume delete "$1" } for i in $(find /mnt/old_roots/ -maxdepth 1 -mtime +30); do delete_subvolume_recursively "$i" done btrfs subvolume create /mnt/root umount /mnt ''; }; }