feat(storage): add impermanence

We'll setup impermanence for a1d1 based on some RAIDed together hard
drives we have. In doing so, we'll gain the ability to keep some
important data persistent while losing everything else.

This is also useful when looking for what to backup.

Change-Id: I51a9dfcaea46a4a21e601615ddd7288c91effa9e
Reviewed-on: https://git.clicks.codes/c/Infra/NixFiles/+/724
Tested-by: Samuel Shuert <coded@clicks.codes>
Reviewed-by: Samuel Shuert <coded@clicks.codes>
diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt
new file mode 100644
index 0000000..2071b23
--- /dev/null
+++ b/LICENSES/MIT.txt
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) <year> <copyright holders>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/flake.lock b/flake.lock
index 9ef2593..0289d4f 100644
--- a/flake.lock
+++ b/flake.lock
@@ -90,6 +90,21 @@
         "type": "github"
       }
     },
+    "impermanence": {
+      "locked": {
+        "lastModified": 1708968331,
+        "narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=",
+        "owner": "nix-community",
+        "repo": "impermanence",
+        "rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-community",
+        "repo": "impermanence",
+        "type": "github"
+      }
+    },
     "nixpkgs": {
       "locked": {
         "lastModified": 1716966868,
@@ -109,6 +124,7 @@
     "root": {
       "inputs": {
         "deploy-rs": "deploy-rs",
+        "impermanence": "impermanence",
         "nixpkgs": "nixpkgs",
         "snowfall-lib": "snowfall-lib",
         "unstable": "unstable"
diff --git a/flake.nix b/flake.nix
index 2b80604..a565974 100644
--- a/flake.nix
+++ b/flake.nix
@@ -19,6 +19,8 @@
       url = "github:serokell/deploy-rs";
       inputs.nixpkgs.follows = "nixpkgs";
     };
+
+    impermanence.url = "github:nix-community/impermanence";
   };
 
   outputs =
@@ -37,6 +39,8 @@
     lib.mkFlake {
       overlays = with inputs; [ ];
 
+      systems.modules.nixos = [ inputs.impermanence.nixosModules.impermanence ];
+
       deploy = lib.mkDeploy {
         inherit (inputs) self;
         overrides = {
diff --git a/modules/nixos/clicks/storage/impermanence/default.nix b/modules/nixos/clicks/storage/impermanence/default.nix
index ac797a6..eb8a72e 100644
--- a/modules/nixos/clicks/storage/impermanence/default.nix
+++ b/modules/nixos/clicks/storage/impermanence/default.nix
@@ -11,33 +11,56 @@
 {
   options.clicks.storage.impermanence = {
     enable = lib.mkEnableOption "Enable impermanent rootfs with btrfs subvolumes";
-    device = lib.mkOption {
-      type = lib.types.str;
-      description = "Device Path";
+    devices = {
+      root = lib.mkOption {
+        type = lib.types.str;
+        description = "Rootfs device path";
+      };
+      persist = lib.mkOption {
+        type = lib.types.str;
+        description = "Persistent data device path";
+      };
     };
     volumes = {
       mount = lib.mkOption {
         type = lib.types.str;
-        description = "Path on device to the mounting subvolume, everything on here will be deleted";
+        description = "Path on rootfs device to the mounting subvolume, everything on here will be deleted";
         default = "@";
       };
       old_roots = lib.mkOption {
         type = lib.types.str;
-        description = "Path on device to store old roots on";
+        description = "Path on rootfs device to store old roots on";
         default = "old_roots";
       };
+      persistent_data = lib.mkOption {
+        type = lib.types.str;
+        description = "Path on persist device to store persistent data on";
+        default = "data";
+      };
     };
     delete_days = lib.mkOption {
       type = lib.types.int;
-      description = "How many days to wait before deleting an old root from cfg.old_roots";
+      description = "How many days to wait before deleting an old root from `cfg.volumes.old_roots`";
       default = 7;
     };
+    persist = {
+      directories = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
+        description = "List of directories to store between boots";
+        default = [ ];
+      };
+      files = lib.mkOption {
+        type = lib.types.listOf lib.types.str;
+        description = "List of files to store between boots";
+        default = [ ];
+      };
+    };
   };
 
   config = lib.mkIf cfg.enable {
     boot.initrd.postDeviceCommands = lib.mkAfter ''
       mkdir /impermanent_fs
-      mount ${cfg.device} /impermanent_fs
+      mount ${cfg.devices.root} /impermanent_fs
 
       if [[ -e /impermanent_fs/${cfg.volumes.mount} ]]; then
           mkdir -p /impermanent_fs/${cfg.volumes.old_roots}
@@ -62,9 +85,26 @@
     '';
 
     fileSystems."/" = {
-      device = cfg.device;
+      device = cfg.devices.root;
       fsType = "btrfs";
       options = [ "subvol=${cfg.volumes.mount}" ];
     };
+
+    fileSystems."/persist" = {
+      device = cfg.devices.persist;
+      neededForBoot = true;
+      fsType = "btrfs";
+    };
+
+    environment.persistence."/persist/${cfg.volumes.persistent_data}" = {
+      directories = [ ] ++ cfg.persist.directories;
+      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"
+      ] ++ cfg.persist.files;
+    };
   };
 }
diff --git a/systems/x86_64-linux/a1d1/default.nix b/systems/x86_64-linux/a1d1/default.nix
index 4f7e821..cd71bbf 100644
--- a/systems/x86_64-linux/a1d1/default.nix
+++ b/systems/x86_64-linux/a1d1/default.nix
@@ -32,7 +32,10 @@
       raid.enable = true;
       impermanence = {
         enable = true;
-        device = "/dev/disk/by-uuid/ab5c2f52-a737-4b29-a505-e3d0b9d0714c";
+        devices = {
+          root = "/dev/disk/by-uuid/ab5c2f52-a737-4b29-a505-e3d0b9d0714c";
+          persist = "/dev/md/a1d1:persist";
+        };
       };
     };
   };