From 89b1bcce3ae09c4d808a69019d586ef79b50492a Mon Sep 17 00:00:00 2001 From: vkcku Date: Mon, 1 Jun 2026 12:15:35 +0530 Subject: infra: add impermanence to base module monorepo-revid: dea24bc37b399da7739ce19063e7439ec756a457 --- flake.lock | 20 +++++++ flake.nix | 6 +++ infra/modules/base/persist.nix | 115 +++++++++++++++++++++++++++++++++++++++++ infra/modules/base/zfs.nix | 2 +- 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 infra/modules/base/persist.nix 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"; -- cgit v1.3.1