Per the conversation in the topic about using pre-built binaries inside snaps, please note that for a some time now we support declaring environment variables to be exported inside the snap environment directly in snapcraft.yaml.
I think what still needs to be released for this to be generally available is support for variable expansion, I was surprised to notice that most of my use of environment had this construct:
apps:
vim:
command: vim
environment:
VIM_RUNTIME_DIR: $SNAP/usr
Or something like that. Is that currently working on the released versions?
It didn’t work when I tried it on version 2.28. Unfortunately, this means that it’s still not possible to set $PATH for example, without relisting all directories or using the wrapper scripts of old.
To add to this, we can’t use env vars (nor a lot of other potentially useful stuff, like quotes) in commands. I think it makes sense for things like daemons to not need a wrapper just to have a funky commandline; not sure about regular commands though.
EDIT: my statement is true only for environment, not for command. Sorry for this mixup.
This should work with 2.23.6 (which is in -updates). We have a test in test-snapd-tools that looks like this:
name: test-snapd-tools
environment:
EXTRA_CACHE_DIR: $SNAP_USER_DATA/.cache
and when I run it:
$ test-snapd-tools.env |grep CACHE
EXTRA_CACHE_DIR=/home/egon/snap/test-snapd-tools/x1/.cache/.cache
Unless I misunderstand the topic this is what you need, right?
So a follow up question, is there a way to have the environment entries affect command but not be exported? This will help a lot with classic confined snaps.
Do you mean interpolating the command but not exporting as a variable? Mixing these two options seems super confusing, and the benefit is unclear. Seems simpler and more straightforward to simply use a variable name which isn’t used by the command.
The thing that uses this environment variable is ld.so, which is the interpreter of the dynamically linked executable. Not exporting means the shell holds it just for its own use on interpolations, which means it won’t pass it over during the child fork, which means ld.so won’t find it.
Just to add one egg to to this basket, there’s a bug now that $PATH is incorrect. I suspect it has happened since we introduced better environment handling. Details are available here:
One quirk I found is that variables defined in snap.yaml environment: sections are interpolated for $SNAP* variables for apps, but not in the configure hook, they are set to the un-interpolated string.
The configure hook variables are left un-interpolated, but the app ones are. Additionally, a stray newline is added to the variables value!?
I note that only $SNAP* variables are interpolated, which i assume is a security feature? I would be nice if other variables defined within the same environment: block could also be interpreted?
I am working around this hardcoding /var/snap//current instead of $SNAP_DATA in my environment: block, but I need to strip my env vars in the configure hook code
Ok, at first I thought this is a bug and has an easy explanation - we do not do osutil.SubstituteEnv(..) for hooks in snap-exec. But I think it is actually by design and not an oversight (one could also say it’s a limitation): hooks are executed by snapd with euid=root (but are confined of course), so doing env var expansion for hooks would be a security issue.
@bloodearnest so, we don’t interpolate the variables from “environment:” section for hooks, but you can of course use $SNAP_DATA, $SNAP_COMMON etc. directly in hooks (no need for intermediate values in the yaml).
@zyga-snapd I don’t know the original designs and I didn’t implement the hook machinery. All I can say is right now the env expansion happens in snap-exec and for some reason we don’t expand for hooks - fixing this is a one line change if that’s what we want.