Using ubuntu-image

Images are built from a model assertion using ubuntu-image, a tool to generate a bootable image. It can be installed on a snap-supporting Linux system as follows:

sudo snap install ubuntu-image --classic

The ubuntu-image command requires only a path to a model assertion to build an image.

If you want to include your own core snaps, such as a custom gadget snap, see Building an image with custom snaps for details on how the model assertion and ubuntu-image command need to be modified.


Inside a model

Creating an Ubuntu Core image starts with a model assertion, a digitally signed text file with structured headers defining every aspect of the image.

The input model for defining and signing such a document is provided as JSON text:

{
    "type": "model",
    "series": "16",
    "model": "ubuntu-core-22-pi-arm64",
    "architecture": "arm64",
    "authority-id": "canonical",
    "brand-id": "canonical",
    "timestamp": "2022-04-04T10:40:41+00:00",
    "base": "core22",
    "grade": "signed",
    "snaps": [
        {
            "name": "pi",
            "type": "gadget",
            "default-channel": "22/stable",
            "id": "YbGa9O3dAXl88YLI6Y1bGG74pwBxZyKg"
        },
        {
            "name": "pi-kernel",
            "type": "kernel",
            "default-channel": "22/stable",
            "id": "jeIuP6tfFrvAdic8DMWqHmoaoukAPNbJ"
        },
        {
            "name": "core22",
            "type": "base",
            "default-channel": "latest/stable",
            "id": "amcUKQILKXHHTlmSa7NMdnXSx02dNeeT"
        },
        {
            "name": "snapd",
            "type": "snapd",
            "default-channel": "latest/stable",
            "id": "PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4"
        }
    ]
}

The above example shows an unsigned reference model for Raspberry Pi/arm64. To see how this can be modified and signed, see Custom images.

The model includes details such as the store to use (brand-id and authority-id), the model name (ubuntu-core-22-pi-arm64) and the hardware architecture (arm64). Any snaps installed on the device will respect this selected architecture.

As outlined in Snaps in Ubuntu Core, there are four principle types of snap that combine to create the Ubuntu Core environment. These are kernel, gadget, base and snapd, and all four need to be referenced within a model assertion.

Building with ubuntu-image

The following will build an amd64 image using the ubuntu-core-22-amd64.model reference model:

$ ubuntu-image snap ubuntu-core-22-amd64.model
Fetching snapd
Fetching pc-kernel
Fetching core22
Fetching pc

The output includes the img file itself, alongside a seed.manifest file. The manifest file simply lists the specific revision numbers of the snapd, pc, pc-kernel and core snaps built within the image, plus any other snaps added to the model.

Testing an image

Rather than immediately booting an image on native hardware, it’s good practice to boot an image first with QEMU (https://www.qemu.org/). See Testing Ubuntu Core with QEMU for further details.

After a successful boot, Ubuntu Core initialisation will ask for both networking parameters and an Ubuntu One account (see https://snapcraft.io/account).

When the initialisation process has finished, and rebooted, you can SSH to the device using either the physical device network address, or localhost port 8022 for the above QEMU example command:

ssh <username>@localhost -p 8022

You are now connected to the Ubuntu Core virtual machine, from where you can configure and install whatever apps you need.

To list which snaps are installed, for example, type ‘snap list’:

$ snap list
Name       Version        Rev    Tracking       Publisher   Notes
core22     20221210       904    latest/stable  canonical✓  base
pc         2022.4         115    22/stable      canonical✓  gadget
pc-kernel  5.4.0-66.74.1  722    22/stable      canonical✓  kernel
snapd      2.49           11107  latest/stable  canonical✓  snapd

To view the model assertion used to build the image, type snap model --assertion:

$ snap model --assertion
type: model                                                                                                                                                
authority-id: canonical                                                                                                                                    
series: 16                                                                                                                                                 
brand-id: canonical                                                                                                                                        
model: ubuntu-core-22-amd64                                                                                                                                
architecture: amd64                                                                                                                                        
base: core22                                                                                                                                               
grade: signed                                                                                                                                              
[...]

To output the serial assertion rather than the model assertion, type snap model --serial:

$ snap model --serial
brand-id:  canonical
model:     ubuntu-core-22-amd64
grade:     signed
serial:    1194d330-d27b-4230-a16f-ab0d23665010

See the Snap documentation for more details on working with snaps. To build a custom image that includes your own selection of snaps, take a look at Custom images.

Again, we should distinguish between the (unsigned) “model”, and the (signed) “model assertion”. Early discussion should refer exclusively to the “model” or “reference model”, and only after signing should there be discussion of the resultant “model assertion.”

1 Like

You’ve already covered running under QEMU a number of times, just refer back to that section.

Good point. I’ve been meaning to remove the duplication for ages, but you’ve finally pushed me into doing it. Thanks!