Accessing home directory with home interface

Is there a canonical way for programs that use the “home” interface to refer to the actual home directory? Standard methods like Qt’s QDir::homePath() merely return $HOME which is always set to $SNAP_USER_DATA. Consequently, applications that plug into home in order to access the user’s files will typically initialize their file dialogs at $SNAP_USER_DATA, from which the user must awkwardly go up several levels in order to access their documents. Keepassxc does this for example. Users should not need to know the relation between $SNAP_USER_DATA and their home directory in order to access their files.

The desktop-launch launcher provided by ubuntu/snapcraft-desktop-helpers project should link all XDG standard user directories (Documents, Music, Pictures…etc.) to the user’s real ones so the snapped application can easily access these files.

You definitely still have $USER set in the environment so using /home/$USER might work … there are other ways like using getpwnam() to get the pw_dir from /etc/passwd (that is likely not confined).

Since this question doesnt come up for the first time, i wonder if we should not have something like “$ORIG_HOME” or some such in the environment exported by snapd. That would make it easier to handle and also cover exotic locations for homedirs (/var/home/$USER comes to mind) that would only live in the passwd file but not be known inside the snap environment. Filing a whishlist bug against snapd might make sense here …

I still face this issue now. I am not sure is there any recommended to solve this?

I am using Rust’s dirs::home_dir() function and it returns /home/<user>/snap/<package> path instead of /home/<user>. This is happening only when I install install via snap.

I did some digging and seems like dirs::home_dir() function depends on $HOME.

As @Lin-Buo-Ren mentioned, snapcraft-dektop-helpers handles the Documents, Videos, etc directories.
but not HOME directory.

What’s the recommended way do solve this issue?
Should I add additional conditions or use this method?

SNAP VERSION
snap 2.39.3
snapd 2.39.3
series 16
ubuntu 18.04
kernel 4.15.0-55-generic

You are free to create a wrapper script for your command and reset HOME. You can determine the user’s home directory via shell getent passwd $(id -u) | cut -d ':' -f 6 or use the getpwent() equivalent in your language of choice.

I have experimented the same “problem” in my application. I have solved it by “re-written” the environment variable HOME of my snap application to point to the “real home”. My app is working as expected but I do not know if this may have some negative repercussion later on. According to the documentation, each snap application “re-writes” the HOME variable that each snap appears to have a dedicated home directory that is a subdirectory of the real home directory. Which is the main goal of this? Is there any problem to prevent it by forcing the HOME variable in the snapcraft.yaml file?

Thank you in advance

My .yaml:

apps:
myApp:
environment:
HOME: /home/$USER

Environment variables doc:

I faced the same issue here, and I’m not sure what is the best way to handle it.

In my case, there is a ‘Open File…’ and ‘Save File…’ menu in my app, when click it, I expect there is no different between Snapped version and Deb version. Like @Lin-Buo-Ren said, all ‘Documents’, ‘Pictures’… are fixed by desktop-launcher, however, the ‘HOME’ directory, which is the default folder for the ‘Open File…’ dialog, is pointed to $HOME directory, which is actually $SNAP_USER_DATA directory. This caused confuse by some people, as they thought they saved/opened the file from ‘HOME’ directory, but they cannot find them in their real HOME directory.

My current solution is reset $HOME to $SNAP_REAL_HOME,

        "HOME": "$SNAP_REAL_HOME",

however, it has side effects. As snap blocks all the access to the hidden files/dirs in the HOME directory even it connected to the home interface, the app will fail to access directories like:

  • ~/.config
  • ~/.cache
  • ~/.local
  • ~/.bashrc
  • ~/.pki
  • etc.

My current solution is to reset even more environment variables to workaround the problem.

        "XDG_CONFIG_HOME": "$SNAP_USER_DATA/.config",
        "XDG_CACHE_HOME": "$SNAP_USER_DATA/.cache",
        "XDG_DATA_HOME": "$SNAP_USER_DATA/.local/share"

However, I don’t think it’s a good solution:

  1. I’m not sure whether it will cover everything, unless it shows in the error log;
  2. XDG_* directories might be easy to fix, the .bashrc like access are fully depends on $HOME environment variables, that I don’t know how to redirect them to $SNAP_USER_DATA;
  3. It is not elegant anyway, many desktop apps have to reset those environment variables, and they can only realize they need to do so unless they hit the problem the same way I did.

I hope we can move the more settings to snapd/desktop-launcher side to create a consistent user experience, and deal with the specific settings on the app side.

  1. reset $HOME to $SNAP_REAL_HOME if home interface are connected to create a consistent UX;
  2. set more XDG_xxx to $SNAP_USER_DATA/xxx in desktop-launcher;
  3. Find a way to redirect the hidden files/dirs access to $SNAP_USER_DATA;

The preferred solution is to use XDG Desktop Portals to open a file chooser outside the snap sandbox. The portal would have the hosts proper $HOME and isn’t restricted by the sandboxing.

Whether you actually can use that though depends on the toolkit and the app, in some cases it might be as easy as setting a single variable; in other cases it might be next to impossible due to the toolkit limitations or proprietary nature of the apps.

If for example this was related to your qqmusic snap, it’d actually work fine on Electron 14+ if GTK_USE_PORTALS=1 was set, but seeing as it’s on Electron 7 and presumably proprietary, I’m unsure if there’s much you can do.

The above way with using $SNAP_REAL_HOME also falls flat on its face if a user actually disconnects the home interface … defaulting to $SNAP_USER_DATA to be the apps home dir has actually a technical reason :slight_smile: