Impermanence

{
  lib,
  config,
  ...
}: {
  # Rollback function for BTRFS rootfs
  # This assumes we have a LUKS volume named "crypted"
  # https://mt-caret.github.io/blog/posts/2020-06-29-optin-state.html
  boot.initrd = {
    enable = true;
    supportedFilesystems = ["btrfs"];
    systemd.services.restore-root = {
      description = "Rollback BTRFS rootfs";
      wantedBy = ["initrd.target"];
      after = ["[email protected]"];
      before = ["sysroot.mount"];
      unitConfig.DefaultDependencies = "no";
      serviceConfig.Type = "oneshot";
      script = ''
        mkdir -p /mnt

        # We first mount the btrfs root to /mnt
        # so we can manipulate btrfs subvolumes.
        mount -o subvol=/ /dev/mapper/crypted /mnt

        # While we're tempted to just delete /root and create
        # a new snapshot from /root-blank, /root is already
        # populated at this point with a number of subvolumes,
        # which makes `btrfs subvolume delete` fail.
        # So, we remove them first.
        btrfs subvolume list -o /mnt/root |
        cut -f9 -d' ' |
        while read subvolume; do
          echo "deleting /$subvolume subvolume..."
          btrfs subvolume delete "/mnt/$subvolume"
        done &&
        echo "deleting /root subvolume..." &&
        btrfs subvolume delete /mnt/root

        echo "restoring blank /root subvolume..."
        btrfs subvolume snapshot /mnt/root-blank /mnt/root

        # Once we're done rolling back to a blank snapshot,
        # we can unmount /mnt and continue on the boot process.
        umount /mnt
      '';
    };
  };

  # Rollback results in sudo lectures after each reboot
  security.sudo.extraConfig = ''
    Defaults lecture = never
  '';

  # Persistent files
  environment.persistence."/persist" = {
    hideMounts = true;
    directories =
      [
        "/etc/NetworkManager/system-connections"
        "/etc/nixos"
        "/etc/pacman.d/gnupg"
        "/etc/secureboot"
        "/var/cache/tailscale"
        "/var/lib/AccountsService/icons"
        "/var/lib/bluetooth"
        "/var/lib/containers"
        "/var/lib/flatpak"
        "/var/lib/libvirt"
        "/var/lib/machines"
        "/var/lib/sddm"
        "/var/lib/systemd"
        "/var/lib/tailscale"
        "/var/lib/nixos"
        "/var/lib/upower"
        "/var/lib/vnstat"
        "/var/cache"
        {
          directory = "/var/lib/iwd";
          mode = "u=rwx,g=,o=";
        }
      ]
      ++ lib.optionals config.security.acme.acceptTerms [
        {
          directory = "/var/lib/acme";
          user = "acme";
          group = "acme";
          mode = "0755";
        }
      ]
      ++ lib.optionals config.services.printing.enable [
        {
          directory = "/var/lib/cups";
          user = "root";
          group = "root";
          mode = "0700";
        }
      ]
      ++ lib.optionals config.services.fail2ban.enable [
        {
          directory = "/var/lib/fail2ban";
          user = "fail2ban";
          group = "fail2ban";
          mode = "0750";
        }
      ]
      ++ lib.optionals config.services.postgresql.enable [
        {
          directory = "/var/lib/postgresql";
          user = "postgres";
          group = "postgres";
          mode = "0700";
        }
      ]
      ++ lib.optionals config.services.loki.enable [
        {
          directory = "/var/lib/loki";
          user = "loki";
          group = "loki";
          mode = "0700";
        }
      ]
      ++ lib.optionals config.services.grafana.enable [
        {
          directory = config.services.grafana.dataDir;
          user = "grafana";
          group = "grafana";
          mode = "0700";
        }
      ]
      ++ lib.optionals config.services.vaultwarden.enable [
        {
          directory = "/var/lib/vaultwarden";
          user = "vaultwarden";
          group = "vaultwarden";
          mode = "0700";
        }
      ]
      ++ lib.optionals config.services.influxdb2.enable [
        {
          directory = "/var/lib/influxdb2";
          user = "influxdb2";
          group = "influxdb2";
          mode = "0700";
        }
      ]
      ++ lib.optionals config.services.telegraf.enable [
        {
          directory = "/var/lib/telegraf";
          user = "telegraf";
          group = "telegraf";
          mode = "0700";
        }
      ]
      ++ lib.optionals config.services.adguardhome.enable [
        {
          directory = "/var/lib/private/AdGuardHome";
          user = "root";
          group = "root";
          mode = "0700";
        }
      ];
    users."root" = {
      home = "/root";
      directories = [
        {
          directory = ".gnupg";
          mode = "0700";
        }
        {
          directory = ".ssh";
          mode = "0700";
        }
      ];
    };
    users."nico" = {
      directories = [
        # Important user data
        ".android"
        ".ansible"
        ".config"
        ".firedragon"
        ".gitkraken"
        ".java"
        ".local/share/AyuGramDesktop"
        ".local/share/JetBrains"
        ".local/share/Nextcloud"
        ".local/share/PrismLauncher"
        ".local/share/SpeedCrunch"
        ".local/share/Steam"
        ".local/share/TelegramDesktop"
        ".local/share/Vorta"
        ".local/share/baloo"
        ".local/share/containers"
        ".local/share/direnv"
        ".local/share/dolphin"
        ".local/share/fish"
        ".local/share/godot"
        ".local/share/heroku"
        ".local/share/jupyter"
        ".local/share/kactivitymanagerd"
        ".local/share/klipper"
        ".local/share/knewstuff3"
        ".local/share/konsole"
        ".local/share/kpeoplevcard"
        ".local/share/krita"
        ".local/share/kscreen"
        ".local/share/kwalletd"
        ".local/share/lutris"
        ".local/share/plasma"
        ".local/share/plasma-systemmonitor"
        ".local/share/zed"
        ".mozilla/native-messaging-hosts"
        ".pki"
        ".steam"
        ".thunderbird/default"
        ".tldrc"
        ".wakatime"
        ".yubico"
        "Documents"
        "Downloads"
        "Games"
        "Music"
        "Nextcloud"
        "Pictures"
        "School"
        "Sync"
        "Videos"
        "VirtualBox VMs"
        # Cache stuff, not actual user data
        ".cache/JetBrains"
        ".cache/bookmarksrunner"
        ".cache/chromium"
        ".cache/containers"
        ".cache/firedragon"
        ".cache/konsole"
        ".cache/lutris"
        ".cache/mesa_shader_cache"
        ".cache/mozilla"
        ".cache/spotify"
        ".cache/systemsettings"
        ".cache/thunderbird"
        ".local/share/Trash"
        ".local/state/syncthing"
        ".local/state/wireplumber"
        # Special permissions needed for those
        {
          directory = ".gnupg";
          mode = "0700";
        }
        {
          directory = ".local/share/keybase";
          mode = "0700";
        }
        {
          directory = ".local/share/keyrings";
          mode = "0700";
        }
        {
          directory = ".ssh";
          mode = "0700";
        }
      ];
      files = [
        ".bash_history"
        ".wakatime.bdb"
        ".wakatime.cfg"
      ];
    };
  };
}