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;