aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flake.lock20
-rw-r--r--flake.nix6
-rw-r--r--infra/modules/base/persist.nix115
-rw-r--r--infra/modules/base/zfs.nix2
4 files changed, 142 insertions, 1 deletions
diff --git a/flake.lock b/flake.lock
index 7a94029..e78f754 100644
--- a/flake.lock
+++ b/flake.lock
@@ -38,6 +38,25 @@
"type": "github"
}
},
+ "impermanence": {
+ "inputs": {
+ "home-manager": [],
+ "nixpkgs": []
+ },
+ "locked": {
+ "lastModified": 1769548169,
+ "narHash": "sha256-03+JxvzmfwRu+5JafM0DLbxgHttOQZkUtDWBmeUkN8Y=",
+ "owner": "nix-community",
+ "repo": "impermanence",
+ "rev": "7b1d382faf603b6d264f58627330f9faa5cba149",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "repo": "impermanence",
+ "type": "github"
+ }
+ },
"import-tree": {
"locked": {
"lastModified": 1778781969,
@@ -88,6 +107,7 @@
"inputs": {
"disko": "disko",
"flake-parts": "flake-parts",
+ "impermanence": "impermanence",
"import-tree": "import-tree",
"nixpkgs": "nixpkgs",
"treefmt-nix": "treefmt-nix"
diff --git a/flake.nix b/flake.nix
index b55a537..4a8daec 100644
--- a/flake.nix
+++ b/flake.nix
@@ -10,6 +10,12 @@
inputs.nixpkgs.follows = "nixpkgs";
};
+ impermanence = {
+ url = "github:nix-community/impermanence";
+ inputs.nixpkgs.follows = "";
+ inputs.home-manager.follows = "";
+ };
+
flake-parts.url = "github:hercules-ci/flake-parts";
import-tree.url = "github:denful/import-tree";
diff --git a/infra/modules/base/persist.nix b/infra/modules/base/persist.nix
new file mode 100644
index 0000000..634230e
--- /dev/null
+++ b/infra/modules/base/persist.nix
@@ -0,0 +1,115 @@
+{ inputs, ... }:
+{
+ flake.modules.nixos.base =
+ {
+ config,
+ lib,
+ pkgs,
+ ...
+ }:
+ {
+ imports = [ inputs.impermanence.nixosModules.impermanence ];
+
+ options.infra.persist = {
+ dir = lib.mkOption {
+ type = lib.types.path;
+ default = "/persist";
+ description = "The root directory to use for persistence.";
+ };
+
+ directories = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = [ ];
+ description = "The list of root owned directories to persist across reboots.";
+ };
+
+ files = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = [ ];
+ description = "The list of root owned files to persist across reboots.";
+ };
+
+ users = lib.mkOption {
+ type = lib.types.attrsOf (
+ lib.types.submodule {
+ options = {
+ directories = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = [ ];
+ description = "The list of directories to persist within the users home directory.";
+ };
+
+ files = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = [ ];
+ description = "The list of files to persist within the users home directory.";
+ };
+ };
+ }
+ );
+ default = { };
+ description = "The directories and files to persist for a user.";
+ };
+ };
+
+ config =
+ let
+ cfg = config.infra.persist;
+ blank = "${config.infra.zfs.pool}/local/root@blank";
+ in
+ {
+ boot = {
+ initrd = {
+ supportedFilesystems.zfs = true;
+ systemd = {
+ storePaths = [ pkgs.zfs ];
+ services.infra-rollback-root = {
+ description = "Rollback root ZFS dataset to blank snapshot";
+ wantedBy = [ "initrd.target" ];
+ after = [ "zfs-import-${config.infra.zfs.pool}.service" ];
+ before = [ "sysroot.mount" ];
+ enableStrictShellChecks = true;
+
+ serviceConfig = {
+ Type = "oneshot";
+ };
+
+ script = ''
+ if "${pkgs.zfs}/bin/zfs" list -H -o name "${blank}" >/dev/null 2>&1; then
+ "${pkgs.zfs}/bin/zfs" rollback -r "${blank}"
+ fi
+ '';
+ };
+ };
+ };
+ };
+
+ fileSystems."${cfg.dir}".neededForBoot = true;
+ environment.persistence."${cfg.dir}" = {
+ directories = [
+ # keep-sorted start
+ "/var/lib/nixos"
+ "/var/lib/systemd"
+ "/var/log/journal"
+ # keep-sorted end
+ ]
+ ++ cfg.directories;
+ files = [
+ "/etc/machine-id"
+
+ # Needed for sops-nix to be able to decrypt secrets.
+ "/etc/ssh/ssh_host_ed25519_key"
+ "/etc/ssh/ssh_host_ed25519_key.pub"
+ ]
+ ++ cfg.files;
+ };
+
+ assertions = [
+ {
+ assertion = config.boot.initrd.systemd.enable;
+ message = "initrd systemd must be enabled for persistence (impermanence)";
+ }
+ ];
+ };
+ };
+}
diff --git a/infra/modules/base/zfs.nix b/infra/modules/base/zfs.nix
index e2cb007..4a818e7 100644
--- a/infra/modules/base/zfs.nix
+++ b/infra/modules/base/zfs.nix
@@ -99,7 +99,7 @@
"persist" = {
type = "zfs_fs";
- mountpoint = "/persist";
+ mountpoint = config.infra.persist.dir;
options = {
canmount = "on";
mountpoint = "legacy";