Anatomy of a recipe¶
This page provides a break down of the keys in complete Snapcraft recipes, as
declared in snapcraft.yaml
files.
Two recipes will be examined. The first is a simple recipe from a Python-based snap called yt-dlp. The second is more complex and builds the wethr app, which is written in Node.
Each key in the yt-dlp recipe will be covered, and the more advanced keys in wethr will be examined.
Simple recipe¶
yt-dlp is a command line tool for extracting online videos, and is a self-contained Python project.
yt-dlp recipe
name: yt-dlp
summary: A fork of youtube-dl with additional features and patches
description: |
Download and play videos on your local system. Runs from the command
line and with all the features and patches of youtube-dlc in addition
to the latest youtube-dl.
version: test
grade: stable
confinement: strict
base: core22
apps:
yt-dlp:
command: bin/yt-dlp
plugs: [home, network, network-bind, removable-media]
parts:
yt-dlp:
plugin: python
source: https://github.com/yt-dlp/yt-dlp.git
Top-level directives¶
Several top-level keys define and describe the snap.
Metadata¶
For convenience, the first set of keys comprise the snap’s metadata, or manifest. These declare information about the snap itself, such as the snap’s name, version, summary, and description. These identifying keys allow users to find the snap through the Snap Store.
The name
key defines the name of the snap. It must start with an ASCII
character and can only use ASCII lowercase letters, numbers, and hyphens. It
must be between 1 and 40 characters in length. It must be unique in the Snap
Store.
The version
key defines the version of the snap to the user. The maximum
length is 32 characters.
The summary
key describes the software in brief. It can’t exceed 79
characters.
The description
key describes the software in full. It also accepts
multi-line syntax. It has a 4,096 character limit, and can be split across
multiple lines with YAML’s multi-line syntax.
When the snap is published, this metadata will be made available to users. It can also be used to pre-populate certain keys in the snap’s Snap Store page during upload.
Base¶
As part of their security design, snaps can’t see the host’s root file system by default. This prevents conflict with other snaps and increases security. However, apps inside the snap still need some location to act as their root filesystem. They would also benefit if common libraries were drawn from this root file system rather than being bundled into each.
The base
key specifies the core snap, which
provides a minimal set of libraries common to most snaps. It’s mounted and used
as the root filesystem for the apps inside the snap. In essence, this means the
snaps behave as though they were running on a system that matches the base.
The core24, core22, and core20 bases are available. Bases correspond to Ubuntu LTS releases. For example, the library set in core24 is equivalent to a subset found in the Ubuntu 24.04 LTS general release. For most practical purposes, the use of either core24 and core22 is recommended, depending on the supported plugins the snap uses.
Confinement¶
Security confinement distinguishes snaps from software distributed using the traditional repository methods. Confinement allows for a high level of isolation and security, and prevents snaps from being affected by underlying system changes, snaps affecting each other, or snaps affecting the host.
The confinement
key describes what type of access the snap’s apps will have
once installed on the host. Confinement levels can be treated as filters that
define what type of system resources outside the snap that the app can access.
Confinement is defined by a level and fine-tuned using interfaces.
There are three confinment levels:
strict
. This confinement level uses Linux kernel security features to lock down the apps inside the snap. By default, a strictly-confined app can’t access the network, the users’ home directory, any audio subsystems or webcams, and it can’t display any graphical output through X or Wayland. Interfaces override its access.This is the preferred confinement for most apps.
devmode
. This is a debug mode level used by developers as they iterate on the creation of their snap. This allows developers to troubleshoot apps, because they may behave differently when confined.This confinement is a temporary measure while a snap is being crafted.
classic
. This is the maximally permissive level equivalent to the full system access that traditional apps have. Classic confinement is often used as a stop-gap measure to enable developers to publish apps that need more access than the current set of permissions allow.This confinment should be used only when required for functionality, as its lack of restrictions is a security risk. Before a snap can be published with classic confinement, it must be approved by the Snap Store team according to a candidate review process. Snaps may be rejected if they don’t meet the necessary requirements.
Here are the resources the snap is exposed to, across confinement levels:
A strictly-confined snap is considered untrusted, and it runs in a restricted sandbox. By design, untrusted apps:
Can freely access their own data.
Can’t access other apps’ data.
Can’t access non-app-specific user data.
Can’t access privileged portions of the OS.
Can’t access privileged system APIs.
May access sensitive APIs under some conditions.
Interfaces¶
Strictly-confined apps don’t always function properly with the default security policy. For example, a browser without network access or a media player without audio access don’t serve their intended purpose. To that end, snap developers can use interfaces, a mechanism of granular resource-level security permissions. These allow developers to expand on the default security policies and connect apps to system resources.
An interface consists of a connection between a slot and a plug. The slot is the provider of the interface while the plug is the consumer, and a slot can support multiple plug connections.
Interfaces can be automatically or manually connected. Some interfaces will be auto-connected. Others may not, especially if they have access to sensitive resources, like network control. Users have the option to manually control interfaces by connecting and disconnecting them using snapd.
Parts¶
The part directives define all the pieces of software that will be used to build the apps inside the snap. It describes how the snap is going to be built.
The yt-dlp snap only has one part, for the app itself.
The plugin
key instructs the part to use the Python plugin, which will
build the app’s Python code. The plugin automatically handles all building and
dependency installation.
The source
key specifies the path to the software source or a download URL
to it. It can be a local or remote path, and can refer to a directory tree, a
compressed archive or a revision control repository. In this particular case,
the app is built the project’s upstream GitHub repository.
Apps¶
The app directives define the command path for each app, how it will be run, optional parameters, and the interface connections that will be established at runtime.
The yt-dlp recipe declares a single app, which is the main app itself. Other snaps may have multiple sub-apps or executables.
The command
key defines the path to the executable – relative to the snap
– and arguments to use when the app runs.
The plugs
key defines the list of interfaces to which the app will have
access to. This enables the intended app functionality. In this specific case,
the yt-dlp snap will be allowed access to the home, network and removable-media
interfaces, which are not available by default under strict confinement. This
will allow the user of the tool to access files in the user’s home directory,
from a network connection, or from any mounted removable media locations.
Advanced recipe¶
For a more complex example, there’s the recipe for wethr, a CLI command for retrieving local weather conditions.
The metadata, base, and confinement declarations are rather similar to the simple example, but with some notable differences.
wethr recipe
name: wethr
summary: Command line weather tool.
description: |
Get current weather
adopt-info: wethr
base: core22
grade: stable
confinement: strict
architectures:
- build-on: amd64
- build-on: armhf
- build-on: arm64
apps:
wethr:
command: bin/wethr
plugs:
- network
parts:
wethr:
plugin: npm
npm-include-node: true
npm-node-version: "10.14.1"
source: https://github.com/twobucks/wethr.git
override-pull: |
craftctl pull
last_committed_tag="$(git describe --tags --abbrev=0)"
last_committed_tag_ver="$(echo ${last_committed_tag} | sed 's/v//')"
last_released_tag="$(snap info wethr | awk '$1 == "latest/beta:" { print $2 }')"
# If the latest tag from the upstream project has not been released to
# beta, build that tag instead of master.
if [ "${last_committed_tag_ver}" != "${last_released_tag}" ]; then
git fetch
git checkout "${last_committed_tag}"
fi
Snapcraftctl set-version "$(git describe --tags | sed 's/v//')"
build-packages:
- git
- sed
Note
The recipe shown here has been modified from the actual snap’s recipe to highlight features of Snapcraft.
Adopting metadata¶
The adopt-info
key instructs Snapcraft to import metadata from another
source. Such use can be useful for continuous integration and delivery systems,
where the declarations in the recipe can be obtained from scripts rather than
manually.
There are multiple ways that information can be obtained. For a how-to guide on bringing in external metadata, see Using external metadata.
Multiple metadata fields can be populated using this key. In this recipe, the snap’s version is obtained from the Git repository release tag, which proceeds in two stages:
The
adopt-info
key instructs Snapcraft to populate the metadata fields that aren’t already declared in the recipe.In the parts section at the end of the recipe:
A step in the build lifecycle is manually overridden.
A custom script is used to derive the version string.
The version string is set using the Snapcraftctl scriptlet.
Alternatively, in this particular example, the version field could also be
manually set with version: '1.5'
.
Quality grade¶
The grade
key defines the quality level of the snap. Two levels are
available, devel and stable. Snaps with the devel grade can’t be uploaded to
either of the stable or candidate channels in the Snap Store.
Architectures¶
The architectures
key defines the target platforms for which the snap should be built on and built
for. It requires the build system that is running the Snapcraft tool to be able
to compile and build the snap for the listed platforms.
Parts¶
Compared to the recipe of yt-dlp, wethr has a part that’s notably more intricate.
It too has one part, but it’s built with the npm plugin, which is designed to simplify the building of Node and JavaScript-based apps, and contains custom options for Node.
The npm-include-node
key determines whether to download and include a Node
runtime in the snap, which in turn is specified by the npm-node-version
key.
The source
key like before defines the URL or a path of the app code that
needs to be downloaded for the build. It points to the original wethr project’s
source code.
The override-pull
key is an inline Bash script that runs during the pull
step of the part lifecycle. It’s used to perform operations
that can’t be satisfied by the default pull operation in the lifecyele. In the
wethr example, the listed commands are used to derive the correct version of
the app, and set it using the Snapcraftctl scriptlet. More details about
overrides can be found in Overriding the default build.
The build-packages
key defines the list of tools and libraries required to
successfully build or compile the part. The build packages are obtained from
the repository archives that match the base, and need to be written in the
syntax that can be correctly interpreted by the apt package manager. For
instance, a foo build package from core22 would be installed (apt install
foo
) in the snap build environment during build. In the case of wethr, the
snap needs Git to retrieve the sources from a remote Git repository and sed
to search and replace the string and yield a Git tag.