The content
interface allows sharing code and data from a slot on a producer snap to one or more plugs on consumer snaps. It’s often used to share common themes and icons from a producer snap, for example, to many snapped applications.
Sharing happens at the filesystem level, which means anything that can be expressed as a file can be shared. This includes executables, libraries and data files, but also sockets.
The Yaru MATE Icons snap is a good producer snap example, letting other applications access the wonderful MATE icon theme. But there are many other producer snaps too, including several for GTK Common Themes and KDE Frameworks for better application integration with the desktop.
See Interface management and Supported interfaces for further details on how interfaces are used.
Auto-connect: no, unless connecting to snaps from the same publisher.
Attributes:
<SNAP>
)interface: content
)See below for more details on the following:
By default, when multiple directories are shared from a producer snap, or when multiple slots are connected to a single plug, the shared content is merged under the target
path of the consuming path’s plug definition. This behaviour can be modified with the source
attribute.
Read, write and target should start with either $SNAP
, $SNAP_DATA
or $SNAP_COMMON
to refer to the designated directory. See Environment variables for details on where these point to on the filesystem.
The content identifier specified by the consuming snap (plug) must match the content attribute of the producer snap (slot).
At a very basic level, the content interface enables one directory, file or socket to appear in a place where another snap can access it.
Each example below involve two snaps: the first provides some content (using a content slot) while the second consumes that content (using a content plug).
In all of the cases we see a small set of attributes defined on the particular interface:
read
attribute for read-only, or the write
attribute for both read and write permissionstarget
attribute to define where the content should become available at runtime.content
attribute to describe the content. This attribute must match on both sides for the connection to happen.source
The source
attribute presents one or more sub-directories, shared from a slot to a plug, beneath the plug’s target
path. Adding the source
attribute ensures that sub-directories, shared from one or more producer snaps, are presented separately to the consumer snap beneath its target
path.
When multiple slots are connected to the same plug and they share directories with the same name, those directories are given unique names with the following pattern: <directory>
, <directory>-2
, <directory>-3
, <directory>-x
. The names of shared directories with unique names are retained, as defined by the slot.
With the following example, directories from the producer snap are shared in corresponding directories beneath the consumer snap’s target
path:
producer/snapcraft.yaml:
slots:
_slot_name_:
interface: content
content: my-binaries
source:
read:
- $SNAP/bin
consumer/snapcraft.yaml:
plugs:
_plug_name_:
interface: content
content: my-binaries
target: $SNAP/usr/local/bin
Using the above configuration, the consumer snap could implement a part to run an executable from the following path:
$SNAP/usr/local/bin/<executable-name>
When more than one slot is connected to the same plug, the plug directory for the new connection will be incremented:
$SNAP/usr/local/bin-2/<executable-name>
Directory names are preserved after a reboot.
Read-only content sharing is ideal for executables and files related to global graphical themes and images.
When the following two interfaces are connected, the consumer snap can invoke executables from $SNAP/usr/local/bin
:
producer/snapcraft.yaml:
slots:
_slot_name_:
interface: content
content: my-binaries
read:
- $SNAP/bin
consumer/snapcraft.yaml:
plugs:
_plug_name_:
interface: content
content: my-binaries
target: $SNAP/usr/local/bin
The directory can be added to PATH
in the wrapper script, if desired, and the directory can also be inspected by any applications that wish to check if the extra executables are available (they can then fail gracefully).
A consumer snap can link to libraries shared by a producer snap:
producer/snapcraft.yaml:
slots:
old-libraries:
interface: content
content: lib0-1604
read:
- $SNAP/lib
consumer/snapcraft.yaml:
plugs:
old-libraries:
interface: content
content: lib0-1604
target: $SNAP/extra-libs
After connecting the interface, the consumer snap can link to libraries from $SNAP/extra-libs
. The directory can be added to LD_LIBRARY_PATH
in the wrapper script if desired.
The value of the content
attribute can be anything, but it is good practice to follow the form nameAPI-BUILDENV
to remind slot consumers of the API level and build tools used. This naming convention is also required when sharing content between snap publishers.
In the above example:
0
indicates API level 01604
denotes Ubuntu 16.04 LTS toolchain and libraries were used within the build environmentAPI and BUILDENV can be anything that is meaningful to the provider and consumers. For example, the GNOME content snap uses gnome-3-26-1604
to denote the full GNOME 3.26 platform libraries and supporting files built on Ubuntu 16.04 LTS.
The content identifier attribute identifies a mostly-immutable compatibility contract (API/ABI or similar) between the snap providing the corresponding content and the snaps consuming it.
The providing snap must preserve backward compatibility for the content provided under a given identifier.
Equally, updates to consuming snaps cannot strongly depend on changes of the identified content from updates to the providing snaps.
There is no support in snapd to synchronise updates between consuming and providing snaps. Compatibility breaking changes need to happen under a different content identifier.
The optional default-provider
attribute can be used to set to the name of a snap offering a corresponding content slot:
consumer/snapcraft.yaml
plugs:
lib0-1604:
interface: content
content: lib0-1604
target: $SNAP/extra-libs
default-provider: lib01604
If the system does not contain a snap providing a matching slot, installing a consumer snap with a default-provider will trigger the automatic installation of the named provider snap (from snapd 2.32). If the named snap is already installed, the absence of a matching slot will instead trigger an update of the named provider snap (from snapd 2.53). The plug and slot will be auto-connected assuming the auto-connection mechanism is configured properly for this.
For example, a snap consuming the GNOME content snap for GNOME 3.26 can set default-provider
to gnome-3-26-1604
.
Sharing writable data can be used to share data files, and UNIX sockets, between a group of snaps. This allows for the creation of a simple form of IPC between them.
Sharing writable files (from snapd 2.19.1):
producer/snapcraft.yaml:
slots:
_slot_name_:
interface: content
content: writable-data
write:
- $SNAP_DATA
consumer/snapcraft.yaml:
plugs:
_plug_name_:
interface: content
content: writable-data
target: $SNAP_DATA
Sharing UNIX sockets (from snapd 2.19.1):
producer/snapcraft.yaml:
slots:
_slot_name_:
interface: content
content: socket-directory
write:
- $SNAP_DATA
consumer/snapcraft.yaml:
plugs:
_plug_name_:
interface: content
content: socket-directory
target: $SNAP_DATA
When the two interfaces are connected the consumer snap can see the socket in $SNAP_DATA
.
The content interface is implemented via an interplay between two systems: AppArmor and bind mounts.
By default, the AppArmor sandbox allows writes to $SNAP_DATA
and reads from $SNAP
(see Environment variables for details).
The content interface takes advantage of this feature to map data from other locations to either $SNAP
or $SNAP_DATA
.
A bind mount is then created to link $SNAP
in one snap (e.g. from /snap/my-snap/1234/content
) to an empty directory in the other snap (e.g., to /snap/my-other-snap/4321/incoming-content
). Locations need to be selected carefully because a bind mount could potentially permit mounts over important locations, such as $SNAP_DATA
, preventing access to a snap’s own writable space.
The same can be done for particular files, if desired, but it requires a pair of interfaces for each file and is more cumbersome.
The previously mentioned Yaru MATE Icons snap is a good example of how this interface can be used to share media with other snaps. Its snapcraft.yaml can be found here: https://github.com/ubuntu-mate/icon-theme-yaru-mate-snap/blob/main/snap/snapcraft.yaml
The source code for this interface is in the snapd repository: https://github.com/snapcore/snapd/blob/master/interfaces/builtin/content.go
Last updated 8 months ago.