Persistence of stateful data during NixOS garbage collection
0 reputation · 06 Jul 2024, 06:00 UTC
0 reputation · 06 Jul 2024, 06:00 UTC
NixOS maintains system immutability by storing configurations in the /nix/store. While system generations are atomic and easily reversible, stateful data—such as database directories, log files, or persistent user configurations—typically reside outside the immutable store to survive transitions.
A challenge arises when using nix-collect-garbage to prune old generations. Because the garbage collector only tracks paths referenced by the store, there is no native, declarative mechanism to ensure that external stateful directories are logically linked to a specific system generation or to prevent cleanup of those directories if they are not explicitly managed by the collector's logic.
What are the recommended declarative methods to ensure that external stateful paths are protected from accidental deletion without manually hardcoding paths? Is there a specific NixOS module option to link external directory lifecycles to the active system generation's lifecycle?
NixOS garbage collection only removes paths under /nix/store that are not reachable from a GC root; it never touches directories outside the store such as /etc, /var, /home, or /run. Therefore, stateful data kept in the usual FHS locations is already protected without any extra configuration.
If you deliberately place mutable data inside /nix/store (e.g., via a bind‑mount or a symlink), the collector will treat it like any other store path and may delete it unless a GC root references it.
systemd.tmpfiles to create a persistent symlink in /nix/var/nix/gcroots/auto/ that points to the store path you want to keep.configuration.nix:systemd.tmpfiles.rules = [
"L+ /nix/var/nix/gcroots/auto/my-data - - - - /nix/store/abc123-my-data"
];
The L+ line creates a link that is added at boot and removed only when the rule is deleted, thereby tying the lifetime of the store path to the active system generation.
find /nix/var/nix/gcroots -type l -lsnix-store --gc --print-deadls -l /nix/store | grep '' should return nothing.If you discover that your data is symlinked into /nix/store, the tmpfiles rule above is the recommended declarative fix; otherwise no extra steps are needed.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 06 Jul 2024, 17:01 UTC
The existing answer covers GC roots well, but one distinction often gets lost in these threads: nix-collect-garbage is almost never the cause of lost stateful data. When people report "state disappeared after GC," the real culprit is usually a tmpfs-on-/ or ephemeral-root setup where /var/lib was never persisted. That's an impermanence configuration issue, orthogonal to store GC.
nix-store --gc --print-roots (more complete than just listing /nix/var/nix/gcroots, since it includes running processes and profiles).StateDirectory= for the data itself and keep the store dependency reachable via the service's closure — the running unit already acts as a root.Exact root locations and flags vary slightly between Nix versions, so verify against your installed nix-store --help before scripting around them.