diff --git a/flake.lock b/flake.lock index c4f00749..e2c237fa 100644 --- a/flake.lock +++ b/flake.lock @@ -886,6 +886,21 @@ "type": "github" } }, + "preservation": { + "locked": { + "lastModified": 1738541138, + "narHash": "sha256-isT+jR8P8UFh5PJDzGHYXqVEHEZa0D5WvT5kfMf14AM=", + "owner": "nix-community", + "repo": "preservation", + "rev": "2f16754f9f6b766c1429375ab7417dc81cc90a63", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "preservation", + "type": "github" + } + }, "root": { "inputs": { "agenix": "agenix", @@ -912,6 +927,7 @@ "nur-ryan4yin": "nur-ryan4yin", "polybar-themes": "polybar-themes", "pre-commit-hooks": "pre-commit-hooks", + "preservation": "preservation", "wallpapers": "wallpapers" } }, diff --git a/flake.nix b/flake.nix index 5541b7fd..5ad0ba3e 100644 --- a/flake.nix +++ b/flake.nix @@ -67,6 +67,7 @@ }; impermanence.url = "github:nix-community/impermanence"; + preservation.url = "github:nix-community/preservation"; # community wayland nixpkgs # nixpkgs-wayland.url = "github:nix-community/nixpkgs-wayland"; diff --git a/hosts/12kingdoms-shoukei/default.nix b/hosts/12kingdoms-shoukei/default.nix index 5f0b9779..3e047a98 100644 --- a/hosts/12kingdoms-shoukei/default.nix +++ b/hosts/12kingdoms-shoukei/default.nix @@ -18,7 +18,7 @@ in { {hardware.myapple-t2.enableAppleSetOsLoader = true;} ./hardware-configuration.nix - ../idols-ai/impermanence.nix + ../idols-ai/preservation.nix ]; boot.kernelModules = ["kvm-amd"]; diff --git a/hosts/idols-ai/default.nix b/hosts/idols-ai/default.nix index 5fc7ca6c..862d5d47 100644 --- a/hosts/idols-ai/default.nix +++ b/hosts/idols-ai/default.nix @@ -18,7 +18,7 @@ in { ./hardware-configuration.nix ./nvidia.nix - ./impermanence.nix + ./preservation.nix ./secureboot.nix ]; diff --git a/hosts/idols-ai/impermanence.nix b/hosts/idols-ai/impermanence.nix deleted file mode 100644 index c3cfae41..00000000 --- a/hosts/idols-ai/impermanence.nix +++ /dev/null @@ -1,207 +0,0 @@ -{ - impermanence, - pkgs, - ... -}: { - imports = [ - impermanence.nixosModules.impermanence - ]; - - environment.systemPackages = [ - # `sudo ncdu -x /` - pkgs.ncdu - ]; - - # There are two ways to clear the root filesystem on every boot: - ## 1. use tmpfs for / - ## 2. (btrfs/zfs only)take a blank snapshot of the root filesystem and revert to it on every boot via: - ## boot.initrd.postDeviceCommands = '' - ## mkdir -p /run/mymount - ## mount -o subvol=/ /dev/disk/by-uuid/UUID /run/mymount - ## btrfs subvolume delete /run/mymount - ## btrfs subvolume snapshot / /run/mymount - ## ''; - # - # See also https://grahamc.com/blog/erase-your-darlings/ - - # NOTE: impermanence only mounts the directory/file list below to /persistent - # If the directory/file already exists in the root filesystem, you should - # move those files/directories to /persistent first! - environment.persistence."/persistent" = { - # sets the mount option x-gvfs-hide on all the bind mounts - # to hide them from the file manager - hideMounts = true; - directories = [ - "/etc/NetworkManager/system-connections" - "/etc/ssh" - "/etc/nix/inputs" - "/etc/secureboot" # lanzaboote - secure boot - # my secrets - "/etc/agenix/" - - "/var/log" - "/var/lib" - - # created by modules/nixos/misc/fhs-fonts.nix - # for flatpak apps - # "/usr/share/fonts" - # "/usr/share/icons" - ]; - files = [ - "/etc/machine-id" - ]; - - # the following directories will be passed to /persistent/home/$USER - users.ryan = { - directories = [ - # ====================================== - # System Defaults - # ====================================== - - "Downloads" - "Music" - "Pictures" - "Documents" - "Videos" - - # ====================================== - # Codes / Work / Playground - # ====================================== - "codes" # for personal code - "work" # for work, contains a .gitconfig with my work email. - "nix-config" - "tmp" - - # ====================================== - # IDE / Editors - # ====================================== - - # neovim plugins(wakatime & copilot) - ".wakatime" - ".config/github-copilot" - - # vscode - ".vscode" - ".config/Code" - ".vscode-insiders" - ".config/Code - Insiders" - - # cursor ai editor - ".cursor" - ".config/Cursor" - - # zed editor - ".config/zed" - - # doom-emacs - ".config/emacs" - "org" # org files - - # Joplin - ".config/joplin" # tui client - ".config/Joplin" # joplin-desktop - - # ====================================== - # Cloud Native - # ====================================== - { - # pulumi - infrastructure as code - directory = ".pulumi"; - mode = "0700"; - } - { - directory = ".aws"; - mode = "0700"; - } - { - directory = ".aliyun"; - mode = "0700"; - } - { - directory = ".config/gcloud"; - mode = "0700"; - } - { - directory = ".docker"; - mode = "0700"; - } - { - directory = ".kube"; - mode = "0700"; - } - ".terraform.d/plugin-cache" # terraform's plugin cache - - # ====================================== - # language package managers - # ====================================== - ".npm" # typsescript/javascript - "go" - ".cargo" # rust - ".m2" # java maven - ".gradle" # java gradle - ".conda" # python, generated by `conda-shell` - - # ====================================== - # Security - # ====================================== - - { - directory = ".gnupg"; - mode = "0700"; - } - { - directory = ".ssh"; - mode = "0700"; - } - ".pki" - - # ====================================== - # Games / Media - # ====================================== - - ".steam" # steam games - ".config/blender" - ".config/LDtk" - - # ====================================== - # Instant Messaging - # ====================================== - ".config/QQ" - ".xwechat" - - # ====================================== - # Meeting / Remote Desktop - # ====================================== - ".config/remmina" - ".config/freerdp" - ".zoom" - - # ====================================== - # browsers - # ====================================== - ".mozilla" - ".config/google-chrome" - - # ====================================== - # xdg data home & state home - # Used by: - # neovim, flatpak, autin, fcitx5, etc... - # ====================================== - ".local/share" - ".local/state" - - # ====================================== - # Misc - # ====================================== - ".config/pulse" - ".var" # flatpak app's data - ]; - files = [ - ".wakatime.cfg" - ".config/nushell/history.txt" - ".config/zoomus.conf" - ".config/zoom.conf" - ]; - }; - }; -} diff --git a/hosts/idols-ai/preservation.nix b/hosts/idols-ai/preservation.nix new file mode 100644 index 00000000..f7e0a881 --- /dev/null +++ b/hosts/idols-ai/preservation.nix @@ -0,0 +1,348 @@ +{ + preservation, + pkgs, + myvars, + ... +}: let + inherit (myvars) username; +in { + imports = [ + preservation.nixosModules.default + ]; + + preservation.enable = true; + # pverservation required initrd using systemd. + boot.initrd.systemd.enable = true; + + environment.systemPackages = [ + # `sudo ncdu -x /` + pkgs.ncdu + ]; + + # There are two ways to clear the root filesystem on every boot: + ## 1. use tmpfs for / + ## 2. (btrfs/zfs only)take a blank snapshot of the root filesystem and revert to it on every boot via: + ## boot.initrd.postDeviceCommands = '' + ## mkdir -p /run/mymount + ## mount -o subvol=/ /dev/disk/by-uuid/UUID /run/mymount + ## btrfs subvolume delete /run/mymount + ## btrfs subvolume snapshot / /run/mymount + ## ''; + # + # See also https://grahamc.com/blog/erase-your-darlings/ + + # NOTE: impermanence only mounts the directory/file list below to /persistent + # If the directory/file already exists in the root filesystem you should + # move those files/directories to /persistent first! + preservation.preserveAt."/persistent" = { + directories = [ + "/etc/NetworkManager/system-connections" + "/etc/ssh" + "/etc/nix/inputs" + "/etc/secureboot" # lanzaboote - secure boot + # my secrets + "/etc/agenix/" + + "/var/log" + + # system-core + "/var/lib/nixos" + "/var/lib/systemd" + { + directory = "/var/lib/private"; + mode = "0700"; + } + + # containers + # "/var/lib/docker" + "/var/lib/cni" + "/var/lib/containers" + + # other data + "/var/lib/flatpak" + + # virtualisation + "/var/lib/libvirt" + "/var/lib/lxc" + "/var/lib/lxd" + "/var/lib/qemu" + # "/var/lib/waydroid" + + # network + "/var/lib/tailscale" + "/var/lib/bluetooth" + "/var/lib/NetworkManager" + ]; + files = [ + # auto-generated machine ID + { + file = "/etc/machine-id"; + inInitrd = true; + } + ]; + + # the following directories will be passed to /persistent/home/$USER + users.${username} = { + commonMountOptions = [ + "x-gvfs-hide" + ]; + directories = [ + # ====================================== + # XDG Directories + # ====================================== + + "Downloads" + "Music" + "Pictures" + "Documents" + "Videos" + + # ====================================== + # Codes / Work / Playground + # ====================================== + "codes" # for personal code + "work" # for work contains a .gitconfig with my work email. + "nix-config" + "tmp" + + # ====================================== + # Nix / Home Manager Profiles + # ====================================== + + ".local/state/home-manager" + ".local/state/nix/profiles" + ".local/share/nix" + + # ====================================== + # IDE / Editors + # ====================================== + + # neovim plugins(wakatime & copilot) + ".wakatime" + ".config/github-copilot" + + # vscode + ".vscode" + ".config/Code" + ".vscode-insiders" + ".config/Code - Insiders" + + # cursor ai editor + ".cursor" + ".config/Cursor" + + # zed editor + ".config/zed" + ".local/share/zed" + + # nvim + ".local/share/nvim" + ".local/state/nvim" + + # doom-emacs + # "org" # org files + # ".config/emacs" + # ".local/share/doom" + # ".local/share/emacs" + + # Joplin + ".config/joplin" # tui client + ".config/Joplin" # joplin-desktop + + # ".local/share/jupyter" + + # ====================================== + # Cloud Native + # ====================================== + { + # pulumi - infrastructure as code + directory = ".pulumi"; + mode = "0700"; + } + { + directory = ".aws"; + mode = "0700"; + } + { + directory = ".aliyun"; + mode = "0700"; + } + { + directory = ".config/gcloud"; + mode = "0700"; + } + { + directory = ".docker"; + mode = "0700"; + } + { + directory = ".kube"; + mode = "0700"; + } + ".terraform.d/plugin-cache" # terraform's plugin cache + + # ====================================== + # language package managers + # ====================================== + ".npm" # typsescript/javascript + "go" + ".cargo" # rust + ".m2" # java maven + ".gradle" # java gradle + ".conda" # python generated by `conda-shell` + + # ====================================== + # Security + # ====================================== + + { + directory = ".gnupg"; + mode = "0700"; + } + { + directory = ".ssh"; + mode = "0700"; + } + { + directory = ".pki"; + mode = "0700"; + } + + ".local/share/password-store" + # gnmome keyrings + ".local/share/keyrings" + + # ====================================== + # Games / Media + # ====================================== + + ".steam" + ".config/blender" + ".config/LDtk" + + ".local/share/Steam" + ".local/share/PrismLauncher" + + ".local/share/tiled" + ".local/share/GOG.com" + ".local/share/StardewValley" + ".local/share/feral-interactive" + + # ====================================== + # Instant Messaging + # ====================================== + ".config/QQ" + ".xwechat" + + ".local/share/TelegramDesktop" + + # ====================================== + # Meeting / Remote Desktop + # ====================================== + ".config/remmina" + ".config/freerdp" + ".zoom" + + ".local/share/remmina" + + # ====================================== + # browsers + # ====================================== + ".mozilla" + ".config/google-chrome" + + # ====================================== + # CLI data + # ====================================== + ".local/share/atuin" + ".local/share/zoxide" + ".local/share/direnv" + ".local/share/k9s" + + # ====================================== + # Containers + # ====================================== + ".local/share/containers" + ".local/share/flatpak" + # flatpak app's data + ".var" + + # ====================================== + # Misc + # ====================================== + + # Audio + ".config/pulse" + ".local/state/wireplumber" + + # Digital Painting + ".local/share/krita" + ]; + files = [ + { + file = ".wakatime.cfg"; + how = "symlink"; + } + { + file = ".config/nushell/history.txt"; + how = "symlink"; + # create parent directory automatically + configureParent = true; + } + { + file = ".config/zoomus.conf"; + how = "symlink"; + } + { + file = ".config/zoom.conf"; + how = "symlink"; + } + ]; + }; + }; + + # Create some directories with custom permissions. + # + # In this configuration the path `/home/butz/.local` is not an immediate parent + # of any persisted file so it would be created with the systemd-tmpfiles default + # ownership `root:root` and mode `0755`. This would mean that the user `butz` + # could not create other files or directories inside `/home/butz/.local`. + # + # Therefore systemd-tmpfiles is used to prepare such directories with + # appropriate permissions. + # + # Note that immediate parent directories of persisted files can also be + # configured with ownership and permissions from the `parent` settings if + # `configureParent = true` is set for the file. + systemd.tmpfiles.settings.preservation = let + permission = { + user = username; + group = "users"; + mode = "0755"; + }; + in { + "/home/${username}/.config".d = permission; + "/home/${username}/.local".d = permission; + "/home/${username}/.local/share".d = permission; + "/home/${username}/.local/state".d = permission; + "/home/${username}/.terraform.d".d = permission; + }; + + # systemd-machine-id-commit.service would fail but it is not relevant + # in this specific setup for a persistent machine-id so we disable it + # + # see the firstboot example below for an alternative approach + systemd.suppressedSystemUnits = ["systemd-machine-id-commit.service"]; + + # let the service commit the transient ID to the persistent volume + systemd.services.systemd-machine-id-commit = { + unitConfig.ConditionPathIsMountPoint = [ + "" + "/persistent/etc/machine-id" + ]; + serviceConfig.ExecStart = [ + "" + "systemd-machine-id-setup --commit --root /persistent" + ]; + }; +} diff --git a/hosts/k8s/kubevirt-shoryu/impermanence.nix b/hosts/k8s/kubevirt-shoryu/impermanence.nix index 4cb6aaa2..be9a04c3 100644 --- a/hosts/k8s/kubevirt-shoryu/impermanence.nix +++ b/hosts/k8s/kubevirt-shoryu/impermanence.nix @@ -3,6 +3,11 @@ pkgs, ... }: { + # TODO: migrate from impermanence to preservation. + # Currently initrd do not support read password from devices: + # boot.initrd.luks.devices..fallbackToPassword is implied by systemd stage 1. + # + # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/boot/luksroot.nix imports = [ impermanence.nixosModules.impermanence ]; diff --git a/modules/nixos/desktop/remote-desktop/tailscale.nix b/modules/nixos/desktop/remote-desktop/tailscale.nix index 318c457e..2d7ec841 100644 --- a/modules/nixos/desktop/remote-desktop/tailscale.nix +++ b/modules/nixos/desktop/remote-desktop/tailscale.nix @@ -22,7 +22,7 @@ # Status Data: # `journalctl -u tailscaled` shows tailscaled's logs # logs indicate that tailscale store its data in /var/lib/tailscale -# which is already persistent across reboots(via impermanence.nix) +# which is already persistent across reboots(via preservation) # # References: # https://github.com/NixOS/nixpkgs/blob/nixos-25.05/nixos/modules/services/networking/tailscale.nix diff --git a/nixos-installer/flake.nix b/nixos-installer/flake.nix index 5612536e..30c57480 100644 --- a/nixos-installer/flake.nix +++ b/nixos-installer/flake.nix @@ -34,7 +34,7 @@ ../modules/nixos/base/networking.nix ../hosts/idols-ai/hardware-configuration.nix - ../hosts/idols-ai/impermanence.nix + ../hosts/idols-ai/preservation.nix ]; }; @@ -64,7 +64,7 @@ ../modules/nixos/base/networking.nix ../hosts/12kingdoms-shoukei/hardware-configuration.nix - ../hosts/idols-ai/impermanence.nix + ../hosts/idols-ai/preservation.nix ]; }; }; diff --git a/outputs/x86_64-linux/src/12kingdoms-shoukei.nix b/outputs/x86_64-linux/src/12kingdoms-shoukei.nix index be26812b..1a277837 100644 --- a/outputs/x86_64-linux/src/12kingdoms-shoukei.nix +++ b/outputs/x86_64-linux/src/12kingdoms-shoukei.nix @@ -34,7 +34,7 @@ { modules.desktop.wayland.enable = true; modules.secrets.desktop.enable = true; - modules.secrets.impermanence.enable = true; + modules.secrets.preservation.enable = true; } ] ++ base-modules.nixos-modules; diff --git a/outputs/x86_64-linux/src/idols-ai.nix b/outputs/x86_64-linux/src/idols-ai.nix index 14c8ef5d..deacd217 100644 --- a/outputs/x86_64-linux/src/idols-ai.nix +++ b/outputs/x86_64-linux/src/idols-ai.nix @@ -39,7 +39,7 @@ modules.desktop.fonts.enable = true; modules.desktop.wayland.enable = true; modules.secrets.desktop.enable = true; - modules.secrets.impermanence.enable = true; + modules.secrets.preservation.enable = true; } ] ++ base-modules.nixos-modules; diff --git a/outputs/x86_64-linux/src/kubevirt-shoryu.nix b/outputs/x86_64-linux/src/kubevirt-shoryu.nix index 99356c83..a27e6eae 100644 --- a/outputs/x86_64-linux/src/kubevirt-shoryu.nix +++ b/outputs/x86_64-linux/src/kubevirt-shoryu.nix @@ -26,7 +26,7 @@ ++ [ { modules.secrets.server.kubernetes.enable = true; - modules.secrets.impermanence.enable = true; + modules.secrets.preservation.enable = true; } ]; # home-modules = map mylib.relativeToRoot [ diff --git a/outputs/x86_64-linux/src/kubevirt-shushou.nix b/outputs/x86_64-linux/src/kubevirt-shushou.nix index ef7186f9..e7f91f08 100644 --- a/outputs/x86_64-linux/src/kubevirt-shushou.nix +++ b/outputs/x86_64-linux/src/kubevirt-shushou.nix @@ -26,7 +26,7 @@ ++ [ { modules.secrets.server.kubernetes.enable = true; - modules.secrets.impermanence.enable = true; + modules.secrets.preservation.enable = true; } ]; }; diff --git a/outputs/x86_64-linux/src/kubevirt-youko.nix b/outputs/x86_64-linux/src/kubevirt-youko.nix index c7eebaf1..474384bc 100644 --- a/outputs/x86_64-linux/src/kubevirt-youko.nix +++ b/outputs/x86_64-linux/src/kubevirt-youko.nix @@ -26,7 +26,7 @@ ++ [ { modules.secrets.server.kubernetes.enable = true; - modules.secrets.impermanence.enable = true; + modules.secrets.preservation.enable = true; } ]; }; diff --git a/secrets/nixos.nix b/secrets/nixos.nix index b9fcd732..46694e29 100644 --- a/secrets/nixos.nix +++ b/secrets/nixos.nix @@ -45,7 +45,7 @@ in { server.webserver.enable = mkEnableOption "NixOS Secrets for Web Servers(contains tls cert keys)"; server.storage.enable = mkEnableOption "NixOS Secrets for HDD Data's LUKS Encryption"; - impermanence.enable = mkEnableOption "whether use impermanence and ephemeral root file system"; + preservation.enable = mkEnableOption "whether use impermanence and ephemeral root file system"; }; config = mkIf (cfg.desktop.enable || enabledServerSecrets) (mkMerge [ @@ -56,7 +56,7 @@ in { # if you changed this key, you need to regenerate all encrypt files from the decrypt contents! age.identityPaths = - if cfg.impermanence.enable + if cfg.preservation.enable then [ # To decrypt secrets on boot, this key should exists when the system is booting, # so we should use the real key file path(prefixed by `/persistent/`) here, instead of the path mounted by impermanence.