Importing the Impermanence module #
As we use Nix to define our system state, the only directories actually required for boot are /boot and /nix. We can leverage this to ensure only desired files are actually retained on boot, eliminating cruft and ensuring pristine state upon each reboot. This can be done declaratively by importing the Impermanence module flake.
Destroying root #
Using our BTRFS volume defined in the previous section, we can add an initrd service to delete the entire /root sub-partition on boot. Nix will then regenerate all required files with symlinks to the nix store located in the separate /nix sub-partition.
{
inputs,
...
}:
{
flake.modules.nixos.impermanence =
{
config,
lib,
pkgs,
...
}:
{
options = {
impermanence.enable = lib.mkEnableOption "impermanence";
};
config = lib.mkIf config.impermanence.enable {
fileSystems."/persist".neededForBoot = true;
boot.initrd.systemd.services.rollback = {
description = "Rollback BTRFS root subvolume to a pristine state";
wantedBy = [ "initrd.target" ];
after = [ "initrd-root-device.target" ];
before = [ "sysroot.mount" ];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
set -e
mkdir -p /mnt
mount ${config.fileSystems."/".device} /mnt
if [[ -e /mnt/root ]]; then
btrfs subvolume delete -R /mnt/root
fi
btrfs subvolume create /mnt/root
umount /mnt
'';
};
};
};
}Persisting files #
Using the environment.persistence.<persistence sub-partition> configuration option we can set desired system directories such as bluetooth and network settings to be mounted to the persisted sub-partition and symlinked to their actual location in the root sub-partition:
impermanence.enable = true;
environment.persistence."/persist" = {
hideMounts = true;
directories = [
"/var/log"
"/var/lib/bluetooth"
"/var/lib/nixos"
"/var/lib/systemd/coredump"
"/var/lib/libvirt"
"/var/lib/netbird"
"/etc/NetworkManager/system-connections"
"/etc/nixos"
"/root/.ssh"
];
};Similarly, we can persist user files such as Desktop, Documents and Flatpak applications:
(lib.mkIf config.impermanence.enable {
environment.persistence."/persist".users.${username} = {
directories = [
"Desktop"
"Documents"
"Downloads"
"Music"
"Pictures"
"Videos"
"Games"
"Books"
"nix-config"
{
directory = ".ssh";
mode = "0700";
}
{
directory = ".local/share/keyrings";
mode = "0700";
}
{
directory = ".local/share/kwalletd";
mode = "0700";
}
".local/share/flatpak"
".local/share/Steam"
".local/share/PrismLauncher"
".local/state/cosmic"
".local/state/cosmic-comp"
".config"
".var"
".vscode-oss/extensions"
];
files = [
".bash_history"
".zsh_history"
];
};
})