Base snaps with defined applications

Hey everyone,

I started to play with creating my own base snap recently. I more or less converted an existing snap into a base snap by adding type: base to the snapcraft.yaml, ensured all the relevant directories are created, added a basic rootfs layout to the snap (dev, etc, home, ...) and installed missing packages normally coming from the core snap.

Once done I installed the snap on a system with snapd from core 16-2.32.8. My expectation was that all applications within the base snap (daemon + regular apps) are running inside a rootfs constructed with the snap as its own base. However what ended up happening was that the installed core snap was taken as the base for apps being executed inside the base snap. Other snaps targeting my base snap were correctly using it.

Leaving it this way can have bad consequences. Think about an app being defined in a fedora base snap and then being executed against the Ubuntu powered core snap. Bad things will happen :slight_smile:

After discussing with @mvo, @zyga-snapd and @chipaca on IRC there seem to be two options:

  1. Allow applications within a base snap to use their snap as the base.
  2. Disallow a base snap to define any applications.

What do you guys think?

regards, Simon

I’m inclined to say we want 1) but it needs some more discussion.

When a base snap refreshes and has a service and a refresh hook, would the refresh hook from the new base run in the context of the old base because the service keeps the mount namespace bound to the previous revision?

Do we allow all kinds of apps (including services)?

What are the use cases of services, apps and hooks on bases.

Out of interest, did your snap include a base: my-snap-name line in its snap.yaml?

As I understand it, a snap that doesn’t declare a base will use the core snap as its root file system. You could argue that it should be different for applications provided by base snaps, but maybe it is better to keep it explicit.

Out of interest, did your snap include a base: my-snap-name line in its snap.yaml?

Nope, it didn’t. Just type: base and I also verified that snapcraft didn’t add a base: <name> field to meta/snap.yaml.

You could argue that it should be different for applications provided by base snaps, but maybe it is better to keep it explicit.

So you mean a base snap should set base: <snap name>?

@morphis it’s a bit unclear from your description why you wanted to do that though? why does your base has apps?

I’m more in favor of 2) until we have a strong use case, I fear under 1) lots of things will have answers but rather subtle

I thought the definition of a base snap is that it is a base for other app snaps? Therefore, it should not have any apps; in your case, you would ship daemons that you would’ve run in the base snap in a separate snap. This is obviously a vote for #2.

There are all kinds of issues with doing anything else; one that comes to mind is base1 ships network-manager and base2 ships network-manager. app1 requires base1 and app2 requires base2. app1 and app2 don’t necessarily even use network-manager but can’t be installed at the same time because base1 and base2 conflict with each other (you can’t have two network-manager slot implementations on the system). There are certainly many other issues…

Unfortunately, this is flawed, because it will be necessary for basic things to come from the base that must be executed. This is even correct today with the current core/app snap configuration.

Base snaps provide the fundamental framework for other app snaps to run. This obviously includes the filesystem layout and other similar expectations, but also includes basic things like configuration hooks, services, and programs that are fundamental to the base functioning correctly.

To cover this with more details and a specific use case:

I am currently exploring options to bundle Android applications as snaps which obviously need a runtime, which will be Anbox.

Android applications by itself are packaged as an APK (a signed zip archive). The idea was now that we have an Anbox base snap which these Android application snaps target and which hosts the Anbox runtime environment.

When an Android application snap gets installed or refreshed it takes a binary from the base (think $ /usr/bin/anbox install <path to apk>) to get the APK it ships installed into the runtime.

As the Anbox runtime requires a daemon to sit in the background and keep the Android container up and running having a base snap without any daemons is not possible.

If base snaps are not meant to provide any services or applications then another approach to this would be to introduce a anbox-runtime base snap which just ships the anbox install binary and enables a snap packaging an Android application to get the APK installed (leaving required interfaces for this aside) into the Anbox runtime. The Anbox runtime itself would continue to come from a regular application snap as it does today.

first there is a difference between general bases and bootable bases, and being exposed as usual service vs having binaries to run is also different, do note already “core” and “core18” don’t expose any app or service nor a configuration hook

This is not incompatible with using a second content snap that provides the required services.

Thinking out loud here, that said, irrespective of where the service is shipped, things are going to get really interesting with IPC with alternate bases (eg, a DBus service that is used by many snaps from different bases (eg network-manager) may not be compatible with certain bases. Eg, network-manager shipped as a snap (base or app, doesn’t matter for this) that is built on Fedora base snap is installed and ‘slots: network-manager’. Any snaps that specify the fedora base snap work, but perhaps a snap that uses an Ubuntu base snap does not because of a changed API. This is of course not limited to DBus; it would be true of any IPC). What we’ve said before base snaps were a thing was that if network-manager incompatibly changed APIs, then we could introduce a new interface since the interface contract is otherwise broken. I suppose base snaps don’t change that.

I’m not sure base snaps providing their own app entry points was really considered. If a base snap is purely intended as a root file system for use by other snaps, then we’d never construct a mount namespace for it, and not need the base: <name> declaration.

Once you’ve added apps (or hooks) to the snap, it’s going to use the base: ... declaration to construct that mount namespace. That’s why I was curious to know whether adding that line to your snapcraft.yaml would solve the problem for you.

Really?

$ ls -l /snap/core/current/meta/hooks
total 5
-rwxr-xr-x 1 root root 4435 Jun  6 12:17 configure

Presumably that hook will run with core as a base due to it being the default, but that seems to be prior art for a base providing some code to be executed under confinement in the root file system it provides.

@jamesh core (really system) configuration is now run internally by snapd, that is a left over for older version of snapd, but is legacy