nix-community / impermanence

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

bindMount logic flaw: There is already an active mount at or below 'folder'! #198

Open PowderedToastMan opened 1 month ago

PowderedToastMan commented 1 month ago

Under my current configuration, the Impermanence module refuses to bindMount folders under my home directory because it mistakenly believes there is already and active mount.

I maintain a /persist folder containing all persistent data. Under this folder, I mount a few zfs filesystems.

fileSystems = {
  "/persist/home/dave/Downloads" = { device = "tank/dave/Downloads"; fsType = "zfs"; };
  "/persist/home/dave/tmp" = { device = "tank/dave/tmp"; fsType = "zfs"; };
  "/persist/home/dave/Documents" = { device = "spool/dave/Documents"; fsType = "zfs"; };
  #...
};

persistence."/persist/home/${config.user}" = lib.mkIf config.impermanence {
  allowOther = true;
  directories = [
    ".cache"
    "Documents"
    "Downloads"
    "tmp"
  ];
  files = [
    ".local/share/zsh/history"
  ];
};

The folder fails to mount when activating home-manager, only creating an empty folder. Upon closer inspection, it would appear that the logic that determines whether the destination is already mounted is mistakenly tripping on this setup.

$ /nix/store/ik7kg6fm1isyvi53xmbkkaxi466ai0yw-hm-setup-env /nix/store/g71f2hkfylxdwsqj45grx5455wfdqf1i-home-manager-generation
Starting Home Manager activation
Activating checkFilesChanged
Activating checkLinkTargets
Existing file '/home/dave/.local/share/zsh/history' is in the way of '/nix/store/gs0nfb9m210qh4rvmp1gdk9ybf51j332-home-manager-files/.local/share/zsh/history', will be skipped since they are the same
Activating unmountPersistentStoragePaths
Activating createAndMountPersistentStoragePaths
Activating createTargetFileDirectories
Activating writeBoundary
Activating createGpgHomedir
Activating installPackages
Activating linkGeneration
Cleaning up orphan links from /home/dave
No change so reusing latest profile generation 1
Creating home file links in /home/dave
Activating onFilesChange
Activating runUnmountPersistentStoragePaths
Activating reloadSystemd
The user systemd session is degraded:
  UNIT                                            LOAD   ACTIVE SUB    DESCRIPTION
● bindMount--persist-home-dave-Documents-.service loaded failed failed Bind mount '/persist/home/dave/Documents' at '/home/dave/Documents'
● bindMount--persist-home-dave-Downloads-.service loaded failed failed Bind mount '/persist/home/dave/Downloads' at '/home/dave/Downloads'
● bindMount--persist-home-dave-tmp-.service       loaded failed failed Bind mount '/persist/home/dave/tmp' at '/home/dave/tmp'

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.
3 loaded units listed.
Attempting to reload services anyway...

It appears the problem is the grep logic that takes the output of mount:

$ mount | grep -F '/home/dave/Documents'' '
spool/dave/Documents on /persist/home/dave/Documents type zfs (rw,relatime,xattr,posixacl,casesensitive)

The grep statement isn't looking for whitespace at the beginning of the file path. The following seems to work:

$ mount | grep -F ' ''/home/dave/Documents'' '

This grep logic appears in a few places. Are there any issues with adding a check for whitespace preceding the path?

bphenriques commented 3 weeks ago

I am encountering a similar issue and created a minimal setup to reproduce in this folder which includes:

Issue:

Relevant snippet:

{

    programs.gpg.enable = true;
    services.gpg-agent = {
      enable = true;
      pinentryPackage = pkgs.pinentry-gnome3;
    };
    ...
    home.persistence."/persist/data/bphenriques" = {
      allowOther = true;
      directories = [
        ".dotfiles"
        "Desktop"
        "Downloads"

        # Both absent: work
        # Both present: break
        # only nix one: works
        # only systemd: breaks -> the culprit
        #".local/share/nix" # trusted settings and repl history
        ".config/systemd"  # systemd timers
        ".ssh"
        ".gnupg"
      ];
    };
}

After isolating the issue, I also tried your patch https://github.com/nix-community/impermanence/pull/199 but did not work for me.

It is hard to debug this and impermanence does not complain :sweat:

edit summary:


Never persist .config/systemd :sweat_smile: I copied from someone's impermenance file and it seemed like a good idea but it contains the service definitions that I needed :runner: :dash: Good way to learn linux!

nazarewk commented 2 weeks ago

FYI: Looking through the code looks like A LOT is duplicated and mountpoints aren't even properly handled (eg: parsing mount output vs using findmnt), so I'm actually working on refactoring the whole home-manager and de-duplicating code at https://github.com/nix-community/impermanence