Best practices for classic snaps?

When running on Focal, the git-ubuntu snap fails to run ssh:

/snap/core/current/usr/bin/ssh: error while loading shared libraries: cannot open shared object file: No such file or directory

Looks like the core snap ships usr/bin/ssh but not Now that is gone from the host on Focal, it no longer works. Clearly it’s an error that a classic snap depended on something from the host system. But what about depending on the core snap?

Also related is LP: 1871827 where running ssh from the core snap causes it to use the host’s /etc/ssh, which fails when versions are mismatched.

I can think of a number of ways to approach fixing this, but I can’t find collated in documentation anywhere a set of best practices: things that are not permitted, things that should be avoided, recommended ways of doing things, and so forth. Any chance we could put this down all in one place? Here’s an attempt at a start:

  • Must not depend on anything on the host system.
  • Can we depend on anything in the core snap at runtime? If so, what? Or should a classic snap treat the core snap as available at build time only?
  • Can we run binaries from the core snap at runtime? If not, what’s the appropriate way of achieving this? stage-packages and an embed into the classic snap itself?

Rather than hack something together yet again, I’d like to solve this in the “right” way this time given everything that has been learned so far.


$ sudo find /snap/core* -name '**'

it is there but most likely not in your LD_LIBRARY_PATH …

why do you try to run ssh from the core snap … the fact you are using classic means you can (and should) happily use the one from the host system (with the respective tests/checks indeed (the path might differ between distros etc)) … after all being able to execute binaries from the host is the main reason to use classic (beyond being able to write to random places on disk).

this is indeed a given …

libc … a shell, i think this is it … (there is python and a minimal set of python modules but that differs between core/core18/core20 and PYTHONPATH might not be right … if you plan to ship python stuff, better also ship your own interpreter and modules)

you can definitely run shell builtins and stuff like df or /bin/echo, the cleaner way (and the one that gives you more control) is indeed using stage-packages though.

the problem here is that snapcraft gives you so much flexibility and so many ways to achieve a goal that it is really hard to define “best practices” IMHO

i.e. to include a shell script from your source tree there are probably at least ten ways (have a Makefile with install call and use the make plugin, use the dump plugin with a fileset, use the nil plugin and an override-build shell snippet etc) …

the same thing goes for runtime handling (use a wrapper to set your library path, use environment entries in snapcraft.yaml, use a command-chain, use an extension that sets up all this for you, etc etc …)

There isn’t any guarantee that the host system has an ssh client, right? Clearly it’s unlikely, but git-ubuntu’s ability to push git+ssh to Launchpad seems to me like something that should be embedded within it rather than depend on the host system.

I’m not sure there’s a clear answer here. Users might expect their /etc/ssh/ssh_config host system changes to have an effect on git-ubuntu, which would require it to use the host’s ssh. But users would also expect git-ubuntu to work even if it requires ssh capabilities not available on their host systems, which would require it to use its own ssh.

that’s the reason why i mentioned adding checks and tests :slight_smile:

a strict snap could actually ship its own ssh client and use the ssh-keys and ssh-public-keys interfaces to use the hosts keys.

well, i guess you have two options here … either tell the user their ssh setup is not usable (because … missing) and to set up their host properly for you …

or ship with hacks to make it possible to use your own shipped ssh and copy/link things like keys and configs from the host into a well known place in the snap area that your shipped ssh then uses.