nix-community / impermanence

Modules to help you handle persistent state on systems with ephemeral root storage [maintainer=@talyz]
MIT License
1.01k stars 76 forks source link

Strategies to deal with `renameat(3)` on persisted files #175

Open Ma27 opened 3 months ago

Ma27 commented 3 months ago

Suppose you have a configuration like this:

{
  environment.persistence = {
    "/impermanence/safe" = {
      directories = [
        "/etc/wpa_supplicant.conf"
      ];
  };
}

Now, wpa_supplicant appears to do a rename when writing changes to the config which is state I'd like to keep. A similar issue also exists for ~/.local/share/recently-used.xbel or .gdbinit.

This doesn't work if only the file is persisted (i.e. bind-mounted) since a rename fails with EBUSY in that case.

There are two kinds of workarounds:

What I'm wondering is, is there any feasible, generic way that doesn't require us to find solutions per-application? If so, we may want to consider adding those as another alternative into impermanence.

[1] https://docs.gtk.org/gtk4/property.Settings.gtk-recent-files-enabled.html

DarkKronicle commented 3 months ago

This isn't optimal, but I think it would work in this situation. If using btrfs subvolumes, on boot (or at least before a lot of services start), you could copy the file into your /persist location, and then copy that over to the actual location.

For example, if this is your persist:

/persist/recently-used.xbel (mtime 4/02)

Then on boot:

/last_boot/home/.../recently-used.xbel (mtime 4/03) -> /persist/recently-used.xbel
/persist/recently-used.xbel (mtime 4/03) -> /home/.../recently-used.xbel

This has the downside of not being persisted until after boot happens again, but on btrfs this copy could be essentially free with --reflink.