nix-community / impermanence

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

Behavior when persisting files #197

Open karaolidis opened 3 months ago

karaolidis commented 3 months ago

The README says: "If the file exists in persistent storage, it will be bind mounted to the target path; otherwise it will be symlinked."

Is there a specific reason for this behavior that I am missing out on? In my use case, some files spot the broken symlink, delete it, and replace it with their own file that ends up not being persisted. Wouldn't it make more sense to do:

...

if [[ -L "$mountPoint" && $(readlink -f "$mountPoint") == "$targetFile" ]]; then
    trace "$mountPoint already links to $targetFile, ignoring"
elif mount | grep -F "$mountPoint"' ' >/dev/null && ! mount | grep -F "$mountPoint"/ >/dev/null; then
    trace "mount already exists at $mountPoint, ignoring"
elif [[ -e "$mountPoint" ]]; then
    echo "A file already exists at $mountPoint!" >&2
    exit 1
fi

if [[ ! -e "$targetFile" ]]; then
    touch "$targetFile"
fi

touch "$mountPoint"
mount -o bind "$targetFile" "$mountPoint"

Instead of:

...

if [[ -L "$mountPoint" && $(readlink -f "$mountPoint") == "$targetFile" ]]; then
    trace "$mountPoint already links to $targetFile, ignoring"
elif mount | grep -F "$mountPoint"' ' >/dev/null && ! mount | grep -F "$mountPoint"/ >/dev/null; then
    trace "mount already exists at $mountPoint, ignoring"
elif [[ -e "$mountPoint" ]]; then
    echo "A file already exists at $mountPoint!" >&2
    exit 1
elif [[ -e "$targetFile" ]]; then
    touch "$mountPoint"
    mount -o bind "$targetFile" "$mountPoint"
else
    ln -s "$targetFile" "$mountPoint"
fi

I can open a PR if so :)

Thanks.

karaolidis commented 3 months ago

Just had a read through #1, I think adding an option to specify the behavior when a file doesn't exist might be a good call?

nazarewk commented 3 months ago

I'm actually hitting an issue related to this behavior: a lot of software seems to replace symlink with raw files preventing those from being stored at all.

I could really use an option to specify the default content of the file if it doesn't exist in either place so it is ALWAYS bind-mounted.

Another option would be to create a oneshot .service triggered by a PathExists= to move the file into /persist and create bind mount as soon as it appears for the first time.