Immich module: External Libraries inside home directory: permission issue

I know this is less of a NixOS question but the upstream only supports users of the “official method” of installation, which is via Docker. I’m using the NixOS service. The configuration is trivial services.immich.enable=true;.

I have two directories, /data and /home/artem/Pictures/archive with the same permissions: 755 (the prefix directories of the latter all also have 755). The former is fine as an “External Library” and the latter raises an error EACCES: permission denied, stat. Any ideas why is the difference and how to fix the latter directory?

Probably because one of the parent directories doesn’t have sufficiently loose perms.
Usually /home/<user> is 700… If it’s 755 as you say, then I wonder if there’s some ACLs?

My /home/<user> is indeed 755

/home🔒 
❯ ll
drwxr-xr-x - artem  8 Jan 10:22 artem
drwx------ - root  15 May  2024 lost+found

thanks to systemd.tmpfiles.rules.

I don’t know how to investigate ACL: I’ve never deal with it. Do you have any ideas by any chance?

Immich probably can’t access /home/artem/Pictures/archive because /home/artem is 700, which is typical for home directories, and directory access requires going through all parent directories.

I would not recommend doing a chmod 755 on your home directory, but it would probably solve your problem, in a “forgot my keys, broke a window” kind of way.

[EDIT: didn’t read your post carefully enough. But the below might work for you anyway if there’s other home folder policy going on, and then you don’t have to 755 your ~.]

Personally, I use bind mounts to have files inside my home directory also accessible to a service user. In your case, you could do something like this:

fileSystems."/media/immich/archive" = {
  device = "/home/artem/Pictures/archive";
  options = [ "bind" "nofail" ];
};

then mkdir -p /media/immich/archive and chmod 755 those instead. (I would chmod 000 the last archive folder there since you’re going to bind mount the other folder over it; this prevents you from accidentally writing files there when the bind mount isn’t mounted.)

If you don’t know what they are, then it’s unlikely you have any set, it was a shot in the dark.
But basically you would check getfacl to verify if there are any. (I think getfacl -e <path> would suffice.)

1 Like

Terrific! It works like a charm. I heard of bind mounts before but wasn’t sure what they’re good for or what are the limitations. I’ll read up about them now.

A little nitpick: for future generations, you could fix the name of the property fileSystems.

1 Like

Oops, I was retyping from my configs because my configs are formatted differently and missed that. I have several ZFS datasets mounted in my home folder and remounted as bind mounts, so I have a helper function

bindMount = dev: { device = dev; options = [ "bind" "nofail" ]; };

and several declarations like

"/pool/me/doc" = bindMount "/home/me/doc";

Glad to hear it works for you.

1 Like

Beautiful, I’ll reuse this function!

I have a similar problem syncing a folder in my home directory with syncthing. I gave the syncthing group access to the folder I am syncing. But as we know in order for a user/group to be able to access/read anything it needs the x permssion in all parent folders including my user home.

However on every nixos-rebuid switch the access bits of /home/<user> get reset to 700 breaking access. I need to be able to permanenly change the execute bit of the group on my home folder, or I am unable to use setfacl because with ACL that bit becomes the mask bit for all groups and named users basically blocking access for any other users and groups on all subfolders of my home.

I will probably use bind mounts like you to fix this problem. But is there another way to keep nixos from setting my home directory permissions in ways I don’t like?

Probably, but:

It’s fine to break your window once if there’s no better way, asking NixOS to break your window every day is a bit much. Go for the bind mount route, or run syncthing as a user service so that it shares permissions with your user - if you’re syncing user files that makes way more sense anyway.

1 Like

I just found users.users.<name>.homeMode that defaults to 700.

Thanks for the suggestion to run syncthing as user service. I will think about what the cleanest way to do this is (user service, bind mount or changing homeMode to 710 and using ACLs). Cheers!

What I do with Syncthing is run it as a system-level systemd service, but with my user.

{
  services.syncthing = {
    dataDir = "/home/justinas";
    enable = true;
    openDefaultPorts = true;
    user = "justinas";
  };
}
1 Like