From b38379e8bee02d09843c479fe4a8143f8046f775 Mon Sep 17 00:00:00 2001 From: Pierre Dal-Pra Date: Thu, 7 Mar 2024 21:39:21 +0100 Subject: [PATCH] Setup impermanence on top of ZFS --- flake.lock | 16 ++++++++ flake.nix | 3 ++ lib/mk-nixos.nix | 10 ++++- lib/overlays.nix | 1 + system/configuration.nix | 8 ++++ system/impermanence.nix | 55 ++++++++++++++++++++++++++ system/machines/vm/configuration.nix | 10 +++-- system/machines/vm/disks.nix | 59 +++++++++++++++++++++++----- system/users.nix | 2 + 9 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 system/impermanence.nix diff --git a/flake.lock b/flake.lock index 0844f33..ca6f7f7 100644 --- a/flake.lock +++ b/flake.lock @@ -191,6 +191,21 @@ "type": "github" } }, + "impermanence": { + "locked": { + "lastModified": 1706639736, + "narHash": "sha256-CaG4j9+UwBDfinxxvJMo6yOonSmSo0ZgnbD7aj2Put0=", + "owner": "nix-community", + "repo": "impermanence", + "rev": "cd13c2917eaa68e4c49fea0ff9cada45440d7045", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "impermanence", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1706826059, @@ -243,6 +258,7 @@ "flake-compat": "flake-compat", "flake-utils": "flake-utils", "home-manager": "home-manager_2", + "impermanence": "impermanence", "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable", "nurpkgs": "nurpkgs" diff --git a/flake.nix b/flake.nix index 4e45657..edb7ec4 100644 --- a/flake.nix +++ b/flake.nix @@ -22,6 +22,7 @@ url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; + impermanence.url = "github:nix-community/impermanence"; # Flake libraries flake-utils.url = "github:numtide/flake-utils"; @@ -39,6 +40,7 @@ , agenix , home-manager , disko + , impermanence , flake-utils , ... }: @@ -84,6 +86,7 @@ home-manager agenix disko + impermanence system revision; }; diff --git a/lib/mk-nixos.nix b/lib/mk-nixos.nix index 2196236..efee063 100644 --- a/lib/mk-nixos.nix +++ b/lib/mk-nixos.nix @@ -4,15 +4,20 @@ name: { lib , home-manager , agenix , disko + , impermanence , system , revision }: let pkgs = overlays system; - specialArgs = { inherit myLib; }; + persistence = { + system = "/persistent-system"; + homes = "/persistent-homes"; + }; + specialArgs = { inherit myLib impermanence persistence; }; baseConfig = _: { - age.identityPaths = [ "/etc/agenix/key" ]; + age.identityPaths = [ "${persistence.system}/key" ]; system.configurationRevision = revision; networking.hostName = name; }; @@ -31,6 +36,7 @@ lib.nixosSystem { ../system/configuration.nix specificConfig diskoConfig + impermanence.nixosModules.impermanence home-manager.nixosModules.home-manager ]; } diff --git a/lib/overlays.nix b/lib/overlays.nix index 20dffbf..d46c983 100644 --- a/lib/overlays.nix +++ b/lib/overlays.nix @@ -21,3 +21,4 @@ import nixpkgs { unstableOverlay ]; } + diff --git a/system/configuration.nix b/system/configuration.nix index 446cea5..90365c4 100644 --- a/system/configuration.nix +++ b/system/configuration.nix @@ -6,6 +6,14 @@ _: ./wm.nix ]; + boot.loader = { + efi.canTouchEfiVariables = true; + systemd-boot = { + enable = true; + memtest86.enable = true; + }; + }; + time.timeZone = "Europe/Paris"; i18n.defaultLocale = "en_US.UTF-8"; diff --git a/system/impermanence.nix b/system/impermanence.nix new file mode 100644 index 0000000..8b53935 --- /dev/null +++ b/system/impermanence.nix @@ -0,0 +1,55 @@ +{ lib, config, persistence, impermanence, ... }: + +let + persistentHomePath = user: "${persistence.homes}/${user}"; +in +{ + + environment.persistence.${persistence.system} = { + hideMounts = true; + + files = [ + "/etc/machine-id" + ]; + }; + + home-manager.users.pdalpra = { + imports = [ + impermanence.nixosModules.home-manager.impermanence + ]; + + home.persistence.pdalpra = { + persistentStoragePath = persistentHomePath "pdalpra"; + allowOther = true; + + directories = [ + "Code" + "Desktop" + "Documents" + "Downloads" + "Music" + "Pictures" + "Videos" + ".ssh" + ".local/share/atuin" + ]; + + }; + }; + + system.activationScripts.persistent-dirs.text = + let + users = lib.attrValues config.users.users; + mkHomePersist = user: + let + path = persistentHomePath user.name; + in + lib.optionalString user.createHome '' + mkdir -p ${path} + chown ${user.name}:${user.group} ${path} + chmod ${user.homeMode} ${path} + ''; + in + lib.concatLines (map mkHomePersist users); + +} diff --git a/system/machines/vm/configuration.nix b/system/machines/vm/configuration.nix index a8bf65e..e4e42fb 100644 --- a/system/machines/vm/configuration.nix +++ b/system/machines/vm/configuration.nix @@ -1,10 +1,12 @@ { + imports = [ + ../../impermanence.nix + ]; + + networking.hostId = "fcd4a364"; + boot = { initrd.availableKernelModules = [ "ata_piix" "ohci_pci" "sd_mod" "sr_mod" ]; - loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; - }; }; virtualisation.vmware.guest.enable = true; diff --git a/system/machines/vm/disks.nix b/system/machines/vm/disks.nix index 2eb913a..2e4acb4 100644 --- a/system/machines/vm/disks.nix +++ b/system/machines/vm/disks.nix @@ -1,8 +1,32 @@ -{ disks ? [ "/dev/sda" ], ... }: +{ config, lib, persistence, ... }: + let - mainDisk = builtins.elemAt disks 0; + mainDisk = "/dev/sda"; + swapSize = "4G"; + blankSnapshot = "main/root@blank"; + poolName = "main"; + zfs_fs = mountpoint: options: { + inherit mountpoint; + type = "zfs_fs"; + options.mountpoint = "legacy"; + } // options; in { + services.zfs.trim.enable = true; + + fileSystems = { + ${persistence.system}.neededForBoot = true; + ${persistence.homes}.neededForBoot = true; + }; + + boot = { + supportedFilesystems = [ "zfs" ]; + kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages; + initrd.postDeviceCommands = lib.mkAfter '' + zfs rollback -r ${blankSnapshot} && echo "Blank snapshot restored" + ''; + }; + disko.devices = { disk.main = { device = mainDisk; @@ -13,20 +37,23 @@ in ESP = { name = "ESP"; type = "EF00"; - size = "512M"; + size = "1G"; content = { type = "filesystem"; format = "vfat"; mountpoint = "/boot"; }; }; - root = { - name = "root"; - end = "-2G"; + luks = { + end = "-${swapSize}"; content = { - type = "filesystem"; - format = "ext4"; - mountpoint = "/"; + type = "luks"; + name = "encrypted"; + extraOpenArgs = [ "--allow-discards" ]; + content = { + type = "zfs"; + pool = poolName; + }; }; }; swap = { @@ -39,5 +66,19 @@ in }; }; }; + zpool.${poolName} = { + type = "zpool"; + mode = ""; # unmirrored + options.ashift = "13"; # 8k blocks + rootFsOptions.canmount = "off"; + datasets = { + root = zfs_fs "/" { + postCreateHook = "zfs snapshot ${blankSnapshot}"; + }; + nix = zfs_fs "/nix" { }; + persistentSystem = zfs_fs persistence.system { }; + persistentHomes = zfs_fs persistence.homes { }; + }; + }; }; } diff --git a/system/users.nix b/system/users.nix index 03f2a6a..88aa1e2 100644 --- a/system/users.nix +++ b/system/users.nix @@ -6,6 +6,8 @@ age.secrets.pdalpra.file = ../secrets/pdalpra.age; age.secrets.root.file = ../secrets/root.age; + programs.fuse.userAllowOther = true; + users = { mutableUsers = false; defaultUserShell = pkgs.bash;