David Callé
on 9 January 2017
Last Thursday, January 5, the snapd team was delighted to announce a new release of snapd (2.20), the daemon that enables systems to work with snaps and provides the snap command.
It’s time we take a look at the most prominent feature of this release: classic confinement. A new relaxed security policy for snaps, aimed at developer tools and scripts that need access to the whole host system.
Confinement policies
As you may know, snaps are installed and mounted in a tightly controlled space: they don’t have access to the vast majority of system resources, they bundle libraries they need and have a read-only file-system. In the snap world, this is the “strict” confinement policy, which is enforced by default.
With snapd 2.20, a new confinement policy is introduced: “classic”, designed to cater for all your scripting and tooling needs. Snaps declaring their confinement as “classic”, have access to the rest of the system, as most legacy (debian packages for example) packaged apps do, while still benefiting from the ci-integrated store model, with automated updates, rollbacks to older versions, release channels, etc.
This new “classic” confinement is only available when snapd is installed on top of a traditional Linux distribution, as opposed to Ubuntu Core systems.
See the confinement reference for details, or directly jump into a 5 minutes practical example. All you need is an up-to-date Ubuntu install and a terminal.
Practical example
To illustrate this feature, let’s dive in and make a classic snap!
This example assumes you are on a fully updated (sudo apt update && sudo apt upgrade
) Ubuntu 16.04, 16.10 or 17.04 and you have the snapcraft package installed (sudo apt install snapcraft
).
you are going to snap a tool that used to be notoriously hard to snap, because it requires access to virtual pty devices and may need to launch other snaps: asciinema.
Asciinema allows you to record a terminal session, play it back (and optionally send it to asciinema.org for online playback).
Create the project
Let’s start by initiating our project with snapcraft init
. It will create a snap template for you to fill.
mkdir asciinema
cd asciinema
snapcraft init
The template is called snapcraft.yaml
, this is the only file you will need to snap asciinema from source. Let’s edit it:
$ <your favorite editor> snapcraft.yaml
And make it look like this:
name: asciinema
version: 'latest'
summary: One-line elevator pitch for asciinema
description: |
You can write a longer
multi-line paragraph in here.
grade: stable
confinement: classic
apps:
asciinema:
command: asciinema
parts:
asciinema:
source: https://github.com/asciinema/asciinema.git
plugin: python
python-version: 'python3'
Anatomy of a snapcraft.yaml
You can find the syntax reference in the snapcraft documentation (see below), but let’s take it field by field:
name: asciinema
This is the name of our final package, that will be presented to users.
version: 'latest'
Version is a free-form, human-friendly, string and since I’m going to use the master asciinema git branch, I’m versioning it as “latest”.
summary: One-line elevator pitch for asciinema
description: |
You can write a longer
multi-line paragraph in here.
Summary and description are self-explicit and appear in search results for snaps and store frontends. Note that “summary” has a 79 characters limit.
grade: stable
Grade lets us declare the stability of our software, which can be stable or devel. This allows you not to release to the stable store channel by mistake something that is not ready for all users. In practice, the store only allows “devel” grade software to be released in the edge and beta channels. In our case, let’s go directly with “stable”.
confinement: classic
Here is our classic confinement mode declaration. Since classic snaps have a relaxed security model, users will need to explicitly pass the --classic
flag to the snap install
command when installing this snap.
apps:
asciinema:
command: asciinema
The apps declaration is where you declare which apps your snap will expose to the user. In this case, it exposes an asciinema
command launching an asciinema
executable placed in the path of the snap (in this case, its bin/
directory). If the executable was located in a foo/
directory, the command
field would look like this:
command: foo/asciinema
Then, you have to declare where the source code for your app lives and how to build it, using the parts
keyword. A part is a piece of code that composes your snap. In this case, you only have one piece, which is the asciinema source code.
parts: asciinema:
Then, in a part, you need to declare its source
, which can be remote or local, and the way to build it. Snapcraft makes this very easy with a plugin system for different technologies and languages. Asciinema is a Python 3 app, let’s see how snapcraft can understand this:
parts: asciinema: source: https://github.com/asciinema/asciinema.git plugin: python python-version: 'python3'
The python plugin comes with options, in this case, you want to build a Python 3 app. When snapcraft will run and build the snap, you will be able to see all the build output (in this case, `pip` installs).
Snap it!
That’s it. You can go back to your terminal and run snapcraft
to build the snap, it should take one or two minutes depending on your network speed to 1) download the asciinema source and Python plugin dependencies, 2) build the app, 3) compress it in a snap.
At the end of the process, you will have an asciinema_latest_amd64.snap
file (name_version_arch.snap) ready to install.
You can install it with the snap install
command:
snap install asciinema_latest_amd64.snap --classic --dangerous
The --classic
flag acknowledges the fact that you are not installing a snap in strict confinement and the --dangerous
flag overrides signature checking, as snaps installed from the store are signed with your developer key.
On install, an asciinema
launcher has been added to /snap/bin/
, that will call the snap itself, installed in /snap/asciinema/<revision>/
:
$ which asciinema /snap/bin/asciinema
Then of course, let’s run asciinema itself and see if it works:
$ asciinema usage: asciinema [-h] [--version] {rec,play,upload,auth} ... [...]
Test upload to asciinema.org:
Congratulations, you have made your first snap with classic confinement!
This tutorial covers the basics of this new feature. The snapcraft documentation will walk you through everything else you need to know (which plugins to use, how to register snap names in the store, etc.)