Guarantees regarding /snap/<appname>/current

Hey, for the nxengine-evo snap, the question arose whether it would be acceptable to build the assets path (/snap/nxengine-evo/current/.../data) into the binary.

If I understand it correctly, snapd does some magic such that the application will find its assets under /snap even if the snap files are mounted in a different location (e.g. on Arch Linux).
I could not find anything in the docs about this, so I hope I did not overlook anything:

  1. Is it guaranteed that at runtime, the application will always find its assets at /snap/<appname>/current?
  2. (Out of curiosity) which kernel features is snapd using to enable this?

Whilst I’ll let someone with more authority give an exact answer, (but I believe the gist of it is yes, for a strict snap, /snap/example/current is guaranteed via the power of mount-namespaces), I looked through your Github discussion and I think you’d benefit from knowing snap layouts exist

If I’m reading it right, you’re having some trouble with e.g. /usr/share/nxengine, with a layout, you’d be able to either symlink it to a location of your choice in $SNAP, and in the offchance that your application is too advanced and is savvy about symlinks being not entirely normal, go to a bind-mount instead which convince 99% of applications.

So you can’t place things in /usr/share/nxengine, but you can completely make /usr/share/nxengine point wherever you want in your snap, which contains the goodies instead. The application shouldn’t be able to percieve the difference.

1 Like

If you are building a strict confined snap, then yes you can rely on your data being available at /snap/$SNAP_NAME/current. Within the sandbox, you can rely on your snap’s contents being available at that location.

If you are building a classic confined snap, then no you can’t depend on this. In particular:

  1. On some distros, snap data is instead mounted under /var/lib/snapd/snap.
  2. There is a (currently experimental) feature to parallel install multiple versions of a snap. If this is in use, only one instance of the snap will be at the expected path.

As strict confined snaps run within a private mount namespace, it was possible to provide a consistent view of the file system even when the above variables are involved.

1 Like

Thank you @jamesh, @James-Carroll!

One follow-up regarding classic snaps: I thought on distros where snaps are not mounted at /snap but at /var/lib/snapd/snap, classic snaps are only supported if e.g. one creates a /snap symlink manually.

Do I understand it correctly, that, while previously even classic snaps could rely on /snap, with the parallel installs feature this will become unsupported, i.e. potentially breaking existing classic snaps that relied on this assumption?

Parallel installs create seperate folders for each install, so /snap/example and /snap/example_second-install. You’d still find the snaps under /snap/ provided the symlink is set-up, but you’d see folders for each unique instance

Since the user is free to choose the instance name of the parallel snap, you wouldn’t be able to tell at compile time where it might go, but could make use of the $SNAP, $SNAP_INSTANCE_NAME and $SNAP_INSTANCE_KEY to find that out at runtime where the files are and compensate with that.

So this might break naive cases where the snap is hardcoded and isn’t aware parallel installations exist AND is installed as a parallel instance, but does nothing to them a primary instance (i.e. with no instance key)

1 Like

I’m thinking that maybe classic snaps should then have to opt-in to support parallel installs, i.e. essentially stating they’re relocatable :thinking:

E.g. I maintain the idris2 snap and it will break with parallel installs. The reason is that currently Idris 2 generates executable chez scheme code starting with a shebang that points to the interpreter contained in the snap. Hence, I had to implement some trickery to make it point to /snap/idris2/current/.../chez rather than /snap/42/current/.../chez because otherwise it would break with each update (in particular, $SNAP points to the resolved path rather than to the path containing the current symlink). Of course, I will try to change it to support parallel installs.

But what I want to say with this example is that I think that from the user perspective it would be good if there was a way to opt-in to parallel installs for classic snaps to avoid unexpected breakage.

Unless, of course, I’m wrong and it was never supposed to rely on /snap anyway, in which case the next question would be whether it may rely on current as the name for the symlink pointing to the current revision :slight_smile:

I just tried to fix the idris2 snap to support parallel instances. It’s not really nice but it’s also still probably better than the hack it previously used … I’m not really happy about exposing idris2.chez as a command since I really wanted to keep that an implementation detail but it seems like it’s the lesser evil in this case …

I would really appreciate any suggestions on how it could be improved further :slight_smile: In any case, thanks a lot for your help!