Build an image with custom snaps

An Ubuntu Core image is built using the ubuntu-image command with a signed model assertion:

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

See Build your own Ubuntu Core image for more details on the entire process.

ubuntu-image tool retrieves 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)

You can now use the image to boot either real or virtual hardware. From within a running session on a custom image, you can run the pre-installed snap:


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[...]

The early link to “Supported platforms” takes one instead to “System requirements”, is there some sort of redirection happening here?

“base: provides the run-time environment. core20 is the newest base, built from Ubuntu 20.04 LTS. core18 is the current standard base and is built from Ubuntu 18.04 LTS.”

Is it not time to reword this to suggest that core20 is the current standard base?

Good idea. I think you’re right. I’ve updated this now.

First link is still incorrect.

Thanks - the original page was split into two, with Supported platforms moving to its own new page.

It would be nice to see the model assertion that generates this output

I’ve now added this to the end of the previous step. I’ll update these examples to uc22 too.

I will whine about this again – docs should clearly distinguish between the text-based (and unsigned) “model”, and the subsequently digitally-signed “model assertion.” Too many docs continually bounce back and forth between these two terms, just like on this page.

This How-to doesn’t really capture what I want it to; it doesn’t tell me where the reference model JSONs are located, it doesn’t tell me how to augment that JSON with a new snap, and it doesn’t tell me how to sign the JSON to get an associated assertion.

I think this How-to needs at least those three things to be effective.

I’m going to propose a rewrite for the entire How-to set of pages this is housed under (Image creation), which basically swaps the order of all the pages and breaks it down into subsections. This rewrite doesn’t impeded at least improving this How-to as a first step, however.


|- Hardware enablement
|   |-> gadget snap creation
|         |-> Add a splash screen
|   |-> kernel snap creation
|- Image creation
      |-> Creating a model (without cannibalizing the 
                            Tutorial this page links to)
      |-> Adding custom snaps
      |-> Optimize boot speed