Any way to acquire the originally set `HOME` environment variable?

I’m snapping an application that specifically needs the original HOME environment variable set by the user, which is rewritten as ~/snap/$SNAP_NAME/$SNAP_REVISION by snapd.

Not the one registered in the user’s password database entry(getent passwd $USER | cut -d: -f6) to be specific, is it possible?

I am expecting the snap runtime ships a SNAP_ORIGINAL_HOME environment variable for such usage, but nothing useful is found in the runtime environment.

There isn’t anything like that. The snap run command overwrites the HOME environment variable without stashing the original value anywhere.

The value it sets it to is based on the home directory found in the password database too, so you can’t deduce it from the new value of $HOME either.

1 Like

Just to be specific the application I tried to snap is ericpruitt/homeishome: Override passwd->pw_dir for the current user’s password database entry with $HOME.

I’m not sure I see the benefit of snap packaging a command like that. It’s primary purpose is run another user supplied command with LD_PRELOAD set, so as a snap it would just be running random commands within its confinement sandbox.

What problem are you trying to solve exactly?

I primarily snap it to fix some snapped applications that hardcoded its access of resources under the users’ real home directory(which is acquired from the passwd database and not always accessible in the snap runtime, like .gitconfig).

This issue is encountered when I tried to make it doubly functional as a stage snap to be consumed by other snaps and a regular snap that can be used by the end-user, the sandbox confinement can be workarounded by switching it to classic confinement.

So how would the original HOME environment variable help you here? Wouldn’t it also point the app at a location it can’t read/write?

One of the usage of the homeishome utility is to deceive the indirectly called program to use another path as the user’s home directory, for example, to prevent the program from polluting the files under the real home directory.

In the stage snap usage, though, is to make the snapped program read from $SNAP_USER_DATA or $SNAP_USER_COMMON, instead of the user’s real home directory.

The original intention is to make the to-be-released BFG Repo Cleaner snap to not read the ~/.gitconfig file in the user’s directory, which is not suitable for a personal-files declaration as the access is an unintended side-affect by the underlying Git libraries.

Okay, but why do you need to know the value of $HOME outside of confinement for that?

If you put a copy of homeishome inside your snap and run the other application under it, won’t that have the intended effect of pointing it at the snap’s private home directory even if it uses getpwuid?

It helps if homeishome is packaged as a regular snap application for its original purpose instead of being used in another snap.

Note that I’m not really intend to do so, though, I just come across this issue while exploring the possiblities.

I can always rewrite the HOME environment variable with the original one in a launcher :slight_smile:

But strict confined snaps cannot call commands provided by other snaps, so how would that help? And even if that wasn’t the case, there’s no guarantee that the homeishome snap would be installed on systems where your repo cleaner snap is installed. This sounds a lot more fragile than just distributing a single snap representing a complete application.

I decide to bundle the homeishome snap to the BFG Repo Cleaner snap via the stage-snaps mechanism instead of calling it directly, refer bfg-snap/snapcraft.yaml at master · Lin-Buo-Ren/bfg-snap for the implementation.

id. est.:

  • A standalone homeishome snap that is used independently for its original purpose
  • A bfg-repo-cleaner snap that bundles the homeishome snap’s content and use it as a runtime-patching launcher

Why not just build the helper library directly as a part? It would likely be faster than kicking off two Snapcraft builds, and avoids ordering dependencies if you need to rebuild for some reason.

It doesn’t even look like it’s really simplifying your snapcraft.yaml file. It likely makes the snap/manifest.yaml data less accurate, which will reduce the value of the security vulnerability scanner that checks if you’ve built against vulnerable package versions.

Then I have to duplicate the part recipe for all of my snaps that require them. With stage-snap I could simply import the provider snap and use it directly.

Wouldn’t snap/manifest.yaml record the stage-snap’s version? Also I assume the security vulnerability scanner only scans the packages that is shipped from the Ubuntu archive? As homeishome isn’t packaged in Ubuntu it seems to not be currently benefit by it.

FYI, the implementation of the stage-snap:

My point is that the “recipe” to build the library directly as a part is of similar length to the “recipe” you’ve written to pull in the binaries via stage-snaps. The alternative would be something like this:

    plugin: make
    make-install-var: INSTALLDIR

It’s the same length as your homeishome-launch part, and doesn’t depend on a second 100+ line snapcraft.yaml. It’s also guaranteed to be built against the correct library versions, which could be a problem with the stage-snaps approach when you begin migrating your snaps to target newer bases.

As for the manifest issue, it doesn’t look like it currently records the revision: just the track and channel. It doesn’t look like it is an issue in this particular case, but if the snap you included in stage-snaps did happen to stage some Ubuntu packages, the details of those staged packages wouldn’t make it into the final snap.

If the recipe works without addtional patching, sure. I really like the idea of minimizing the duplication of implementation via the stage-snaps mechanism and would not let go of it easily.

I assumed that it isn’t an issue as the code is fairly simple and should be compatible with newer glibc snap bases. Probably.

Good point.

FWIW I’ve used REAL_HOME="$(getent passwd $(id -u) | cut -d ':' -f 6)" successfully in the past to migrate user data from user’s home config to snap config using personal-files interface.

Is any of that patch necessary though? It can’t be reducing the binary size significantly, and is just one more thing you’re now on the hook for maintaining. The homeishome-launch script also looks like it would be one or two lines if its functionality was inlined:

  LD_PRELOAD: ${SNAP}/lib/

I get that you don’t want to be continually repeating yourself, but it’s worth considering whether the abstractions you’re introducing are actually making your life easier. If the boilerplate you need to add is of the same order as the boilerplate code you removed, then it’s not obvious the trade off is worth it.

Looking at your other use of stage-snaps, I can see why you’d want to avoid copying that long selective-checkout script into multiple projects. But it isn’t clear what benefit stage-snaps gives you over simply having a part that references the git repo where you maintain the script as a source. That also makes it easier for someone reading your snapcraft.yaml to understand what is going on.

That is probably true. But that also means you’ve introduced an ordering dependency for how you update your snaps. This might be workable if you are the only one who makes use of the snap, but what if other people do the same? How will you know when it is finally safe to upgrade this snap?

1 Like

As a temporary workaround, yes:

Noted. Thanks for the input!

Never thought of that, I might try this approach and see if it’s fit, thanks!

Good point. :thinking:

1 Like

I have same problem but without solution. Classic confinement for autotrash