Snap layouts

Layouts are a developer-centric feature that simplify the creation of snap applications.

Up until snapd 2.36 an experimental feature-flag must be enabled before you can install a layout-dependent snap. Since snapd 2.36 the feature is enabled by default:

$ sudo snap set core experimental.layouts=true

Attempting to install a layout-dependent snap when the feature is disabled will generate the following error:

error: cannot install snap file: experimental feature disabled - test it by setting                                                                 
       'experimental.layouts' to true

Building snaps with layouts

Layouts enable snap developers to modify the execution environment of their snap. They simplify the process of using pre-compiled binaries and libraries that expect to find files and directories outside of locations referenced by $SNAP or $SNAP_DATA.

With layouts, you can take elements from $SNAP, $SNAP_DATA, $SNAP_COMMON and expose them in locations such as /usr, /var and /etc.

Layouts are supported by snapcraft 3.0 when the snap developer declares a base snap (e.g. base: core18). In prior versions, layout options within snapcraft.yaml must be made within the scope of a top-level passthrough field.

As a simple example, let’s consider a snap that includes software that:

  • stores all data in /var/lib/foo
  • has a configuration file in /etc/foo.conf
  • uses read-only data in /usr/share/foo

A layout that allows such software to be used without snap-specific modifications can be defined as follows:

layout:
  /var/lib/foo:
    bind: $SNAP_DATA/var/lib/foo
  /usr/share/foo:
    bind: $SNAP/usr/share/foo
  /etc/foo.conf:
    bind-file: $SNAP_DATA/etc/foo.conf

None of the above filesystem modifications are visible to any other snaps, or from the wider user session. They’re only visible within the per-snap mount namespace.

Layout reference

The syntax for defining a layout is:

layout:
  <target-path>: <declaration>
  <target-path>: <declaration>
  ..

Layouts are defined as a key-value map, mapping from a <target-path> to a layout declaration. Each declaration may be one of the following:

  • bind: <source-path>: bind-mount a directory
  • bind-file: <source-path>: bind-mount a file
  • symlink: <source-path>: create a symbolic link
  • type: tmpfs: mount a private temporary in-memory filesystem

<source-path> must refer to either $SNAP, $SNAP_DATA or $SNAP_USER_DATA.

<target-path> can include nearly any path except for /proc, /sys, /dev, /run, /boot, /lost+found, /media, /var/lib/snapd and /var/snap. Some other limitations apply (see the limitations section below).

If <source-path> and <target-path> don’t already exist, they will be automatically created by snapd. This includes the creation of new empty files, but doesn’t include the creation of symbolic link targets because snapd doesn’t know what kind of objects they may eventually point to. In the example above, $SNAP_DATA/etc/foo.conf is created before any snap application code is executed.

Creating new files and directories in read-only spaces

Layouts can create new directories and files even in read-only locations such as /usr/share. For example, the following declaration will create /usr/share/foo, visible only to executing snap applications (it’s assumed that /usr/share/foo does not exist in the base snap declared by the application developer).

layout:
  /usr/share/foo:
    bind: $SNAP/usr/share/foo

To accomplish the above, snapd uses a temporary filesystem (tmpfs) mounted on /usr/share and populated with a set of empty files and directories. These are then used for bind mounts as well as symlinks to reconstruct the original /usr/share. This allows snapd to make /usr/share writable, and consequently, allows snapd to create /usr/share/foo and configure it as desired.

Current limitations

The following limitations apply as of snapd 2.36

New entries in / (root)

Layouts cannot currently create new top-level files or directories. For example, the following layout declaration will not work:

layout:
  /foo: # Unsupported, cannot create new top-level directories.
     bind: $SNAP/foo

Incompatible existing file, directory or symbolic link

Layouts cannot replace an existing but incompatible filesystem object. This means, for example, that files cannot replace directories or symbolic links, files cannot replace a directory, and existing symbolic links cannot be redirected to a new target. You can, however, replace a directory with another directory.

Last updated 3 months ago. Help improve this document in the forum.