Your submission was sent successfully! Close

Custom images

Building a bespoke image for a Supported platform enables an Ubuntu Core device to be customised at the point of deployment. Customisation options include configuration for both hardware and software, specific kernels, and which snap packages to pre-install.

See Image building for an overview of building reference Ubuntu Core images for a supported platform, and see below for the step required to build a custom image.

Note: Building for non-reference architectures is also possible but requires upstream enablement. For further details, contact Canonical.

Model assertion

The model assertion is a text-based document that contains the fundamental definition of a snap-based device. It describes what the system image includes and is signed by the brand account owning the device definition.

The model assertion contains:

  • Identification information, such as brand account id and model name.
  • Which essential snaps make up the device system, including the gadget snap, kernel snap and the boot base snap with the (read-only) root filesystem.
  • Other required or optional snaps that implement the device functionality.
  • Additional options for the defined device, such as grade for a UC 20 device.

The model assertion is central to both the creation of the device image and the deployed device’s lifecycle; in particular, it:

  • drives image creation via ubuntu-image. The resultant system seed includes the set of snaps and assertions specified in the model assertion.
  • allows first boot verification of the system seed before its snaps are turned into an installed system.
  • conveys model information, through registration from either the factory or in the field, which is used for cross-checking and registration-affecting options, such as which account can issue a serial assertion for the device.

The reference model assertions for each image are stored in the snapcore/models GitHub repository.


To build a custom image, first use the snapcraft command to login to the Snap Store:

$ snapcraft login

If not installed already, install the snapcraft command with:

$ sudo snap install snapcraft --classic

Visit Snapcraft overview for further details, and visit Create a developer account if you don’t yet have an account.

Before creating a custom model assertion, you will need to retrieve your developer ID and generate a properly-formatted timestamp. The snapcraft command can be used to retrieve your developer id:

$ snapcraft whoami
email: <email>
developer-id: bJzr2XzZ56...

Use the following date command to output the correctly-formatted timestamp for the model assertion:

$ date -Iseconds --utc

Custom model assertion

The following is the tweaked JSON input for a custom model assertion based on ubuntu-core-20-amd64:

    "type": "model",
    "series": "16",
    "authority-id": "developer-id",
    "brand-id": "developer-id",
    "model": "ubuntu-core-20-amd64",
    "architecture": "amd64",
    "timestamp": "2020-11-17T13:09:51+00:00",
    "base": "core20",
    "grade": "signed",
    "snaps": [
            "name": "pc",
            "type": "gadget",
            "default-channel": "20/stable",
            "id": "UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH"
            "name": "pc-kernel",
            "type": "kernel",
            "default-channel": "20/stable",
            "id": "pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza"
            "name": "core20",
            "type": "base",
            "default-channel": "latest/stable",
            "id": "DLqre5XGLbDqg9jPtiAhRRjDuPVa5X1q"
            "name": "snapd",
            "type": "snapd",
            "default-channel": "latest/stable",
            "id": "PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4"
            "name": "htop",
            "type": "app",
            "default-channel": "latest/stable",
            "id": "hJmReLmgXSUj4SF7WhyTVRV6IzUa4QUZ"

We’ve saved the above example to a file called my-model.json, and it contains the following modified properties:

  • base: provides the run-time environment. core20, built from Ubuntu 20.04 LTS, is the recommended base to use. core18 is an older alternative, built from Ubuntu 18.04 LTS. See Base snaps for more details.
  • authority-id, brand-id: defines the authority signing the assertion.
    Reference assertions are signed by Canonical. Non-reference assertions are signed by their brand store. For a custom model assertion, this needs to be the developer ID.
  • timestamp: UTC formatted time and date
    used to denote the assertion’s creation time.
  • snaps: “pc”, “pc-kernel”, “core20” and “snapd” are all required for a functioning core20 device. In addition to those, the example shows the arbitrary addition of a snap called htop from the Snap Store. This is purely for illustrative purposes.

For a complete list of model assertion keywords, see Model assertion.

Signing a model assertion

The difference between building an image from a reference model assertion and building from a modified model assertion is that the modified model assertion needs to be digitally signed. This is accomplished in four stages:

  1. create a key
  2. export/register the key
  3. sign the model assertion
  4. build the image

Note: Rather than creating a key for every device, the same key is typically used across all models or model family.

First, sign in to the Snap Store (snap login) and check whether there is already a published key available. You can list any published snaps with the snap keys command:

$ snap login
Login successful

$ snap keys
No keys registered, see `snapcraft create-key`

If you have no registered keys, create one as follows:

$ snap create-key my-models
Confirm passphrase: <passphrase>

$ snap keys
Name         SHA3-384
my-key-name  E-n0AOKPFjIyy4S_i9JxTT4tkuaZf7rP9D2mBNXjlgTGDjL8euFSlb87U0NPl

With a key created, use the snapcraft command to upload and register it with the store:

$ snapcraft register-key
Registering key ...

A custom model assertion is signed by piping the assertion through the snap sign command with the key name as its sole argument:

$ cat my-model.json | snap sign -k my-key-name > my-model.model

The resulting my-model.model file contains the signed model assertion and can now be used to build the image.

Building the image

With a signed model assertion, the Ubuntu Core image can now be built just like a reference image, using the ubuntu-image command:

$ ubuntu-image snap my-model.model
Fetching snapd
Fetching pc-kernel
Fetching core20
Fetching pc
Fetching htop

The output includes the img file itself, alongside seed.manifest and snaps.manifest files. These manifest files simply list the specific revision numbers for the snapd, pc, pc-kernel and core snaps built within the image.

Building an image with custom snaps


$ ubuntu-image snap ubuntu-core-20-amd64.model

will retrieve signed snaps with the given snap-id in the model assertion from the store.

To override these default snaps, first make sure the model assertion has a grade of dangerous to allow non-store snaps to be included:

grade: dangerous

The ubuntu-image command will now build an image using locally sourced and built snaps, such as a custom gadget snap:

$ ubuntu-image snap my-model.model --snap ./pc_20-0.4_amd64.snap
WARNING: proceeding to download snaps ignoring validations, this default will change in the future. For now use --validation=enforce for validations to be taken into account, pass instead --validation=ignore to preserve current behavior going forward
Fetching snapd
Fetching pc-kernel
Fetching core20
WARNING: "pc" installed from local snaps disconnected from a store cannot be refreshed subsequently!
Copying "./pc_20-0.4_amd64.snap" (pc)

As with building a reference image, you can now use the image to boot either real or virtual hardware. See Building the image for more details.

From within a running session on a custom image, you can run the pre-installed snap:

$ htop

Use snap list to see which snaps are installed:

$ snap list
Name       Version        Rev   Tracking       Publisher   Notes
core20     20             634   latest/stable  canonical✓  base
htop       3.0.2          1332  latest/stable  maxiberta   -
pc         20-0.4         108   20/stable      canonical✓  gadget
pc-kernel  5.4.0-54.60.1  642   20/stable      canonical✓  kernel
snapd      2.47.1         9721  latest/stable  canonical✓  snapd

The snap model --assertion command will show the read-only custom model assertion used to build the image:

$ snap model --assertion
type: model
authority-id: bJzr2XzZg6Qv6Z53HIeziXyxtn1XItIq
series: 16
brand-id: bJzr2XzZg6Qv6Z53HIeziXyxtn1XItIq
model: ubuntu-core-20-amd64
architecture: amd64
base: core20
grade: signed
    default-channel: 20/stable
    id: UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH
    name: pc
    type: gadget
    default-channel: 20/stable
    id: pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza
    name: pc-kernel
    type: kernel
    default-channel: latest/stable
    id: DLqre5XGLbDqg9jPtiAhRRjDuPVa5X1q
    name: core20
    type: base
    default-channel: latest/stable
    id: PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4
    name: snapd
    type: snapd
    default-channel: latest/stable
    id: hJmReLmgXSUj4SF7WhyTVRV6IzUa4QUZ
    name: htop
    type: app
timestamp: 2020-11-17T13:09:51+00:00
sign-key-sha3-384: 9aZR3b1U[...]

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