Sane defaults for disko + preservation integration.
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
disko.url = "github:nix-community/disko";
preservation-disko.url = "github:visualphoenix/preservation-disko";
};
}Start with disko's hybrid-tmpfs-on-root example, then add a persist partition:
# disko-config.nix
{ config, ... }:
{
disko.devices = {
disk.main = {
# ... ESP and nix partitions from hybrid-tmpfs-on-root.nix ...
content.partitions.persist = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/persist";
# This connects preservation to disko:
postMountHook = config.preservation.diskoSetupCommands;
};
};
};
# tmpfs root from hybrid-tmpfs-on-root.nix
nodev."/" = {
fsType = "tmpfs";
mountOptions = [ "defaults" "size=2G" "mode=755" ];
};
};
fileSystems."/persist".neededForBoot = true;
}# configuration.nix
{ inputs, ... }:
{
imports = [
inputs.disko.nixosModules.disko
inputs.preservation-disko.nixosModules.default
./disko-config.nix
];
}That's it. Run disko and nixos-install as normal.
Out of the box, the module:
| Feature | Details |
|---|---|
| Persisted directories | /var/lib/nixos, /var/lib/systemd, /var/log |
| Persisted files | /etc/machine-id (with proper initrd handling) |
| Disko integration | Auto-generated postMountHook commands |
| Initrd support | Enables boot.initrd.systemd automatically |
| Clan auto-detection | If using clan, automatically preserves secrets (not required) |
Add more directories or files using standard NixOS module merging:
{ config, ... }:
let
persistPath = config.preservation.persistentStoragePath; # "/persist" by default
in
{
preservation.preserveAt.${persistPath} = {
directories = [
"/var/lib/postgresql"
"/var/lib/private/myapp"
];
files = [
{ file = "/etc/ssh/ssh_host_ed25519_key"; }
{ file = "/etc/ssh/ssh_host_ed25519_key.pub"; }
];
};
}For directories needed before systemd starts (secrets, early-boot state):
{
preservation.extraBindMounts."/var/lib/myapp-secrets".neededForBoot = true;
}Note: /var/lib/sops-nix is handled automatically for clan users.
| Option | Default | Description |
|---|---|---|
preservation.persistentStoragePath |
"/persist" |
Where persistent storage is mounted |
preservation.installMountPoint |
"/mnt" |
Root mount point during installation |
preservation.machineIdMode |
"symlink" |
How to persist /etc/machine-id: "symlink" or "bindmount" |
preservation.extraBindMounts |
{} |
Additional bind mounts with neededForBoot support |
preservation.diskoSetupCommands |
(generated) | Shell commands for disko's postMountHook |
When you run disko, the postMountHook executes after mounting your persist partition. The generated commands:
- Create directories on persistent storage (
/mnt/persist/var/lib/nixos, etc.) - Create mount points on the root filesystem (
/mnt/var/lib/nixos, etc.) - Set up bind mounts so
nixos-installwrites to the persistent locations
At runtime, preservation handles the bind mounts via initrd systemd.
Clan is not required. This module works standalone with any NixOS + disko setup.
If you are using clan-core, the module automatically detects it and:
- Preserves
clan.core.factssecretUploadDirectory - Preserves
/var/lib/sops-nixwhenclan.core.varsgenerators are defined
No configuration needed - it just works.
"Directory doesn't exist" during nixos-install
Make sure postMountHook = config.preservation.diskoSetupCommands; is on your persist partition content.
Machine-ID regenerates every boot
The module handles this by default. If you're overriding /etc/machine-id preservation, ensure inInitrd = true.
Secrets not available at boot (non-clan sops-nix users)
Clan users get /var/lib/sops-nix automatically. For standalone sops-nix:
preservation.extraBindMounts."/var/lib/sops-nix".neededForBoot = true;- nix-community/preservation
- nix-community/disko
- NixOS PR #351151 - machine-id changes
- preservation#22 - machine-id discussion