Create an Ubuntu Core image

Note

Check Dedicated Snap Store configuration for information relating to the specific configuration for your Dedicated Snap Store.

Warning

Example values are provided for store configuration in this document. If

you are a Dedicated Snap Store customer, you will be provided with a set of documentation with the details of your store.

To validate that the store was provisioned correctly and that you are able to access it, we recommend creating and booting an Ubuntu Core image for amd64.

Setup the Serial Vault

In order for a device to be able to connect to your Dedicated Snap Store, it must provide a secret to the Serial Vault. This secret is called the model API key, and this key corresponds to a particular model name. The model name should be an informative string like “acme-gateway-prod”. For this tutorial, we are using the model name alpha. You should configure the Serial Vault adding that model name, and make note of the API key. We will add that to the gadget snap in the next section.

Creating the gadget snap

One major requirement for building an Ubuntu Core image is having a gadget snap. Gadget snaps do many things but, for our purposes here, the important functionality is generating a serial number and using that serial number and a pre-shared API key to get credentials from the Serial Vault to authenticate with the Device View store. You can also use the gadget snap to set default configuration values for the system and application snaps.

To build a custom gadget snap, we start by selecting a suitable candidate from the Canonical supported gadgets. For detailed instructions, see here.

For this specific case of validating the initial store setup, let’s use the 64-bit PC Gadget Snap.

user@localhost:~$
sudo snap install --classic --channel=8.x/stable snapcraft
user@localhost:~$
sudo apt update

user@localhost:~$
sudo apt install -y git

user@localhost:~$
git clone -b 24 https://github.com/canonical/pc-gadget acme

user@localhost:~$
cd acme

Update the name field in the snapcraft.yaml to acme-pc. Update the value of the MODEL_APIKEY environment variable in the snapcraft.yaml to the value generated during the Serial Vault setup above. Feel free to also adjust the version, summary and description to be more meaningful in your context.

Build the snap:

user@localhost:~/acme$
snapcraft

The sample “product_serial” is generated by date -Is in this gadget (see the snap/hooks/prepare-device hook). In production the serial number should be derived from a value inserted during the factory process or from a unique hardware identifier, for uniqueness and traceability. See here for how to modify the gadget to use dmidecode (x86_64 only) to read a serial number from the DMI table.

Ensure that the Brand account is a Publisher in your Base store and login to the Brand account.

Register the gadget snap name in your Base store and push the initial revision:

user@localhost:~/acme$
snapcraft whoami
email:        [email protected]
developer-id: brand-account
user@localhost:~/acme$
snapcraft register acme-pc --store=acme-store
...
you, and be the software you intend to publish there? [y/N]: y
Registering acme-pc.
Congrats! You are now the publisher of 'acme-pc'.
user@localhost:~/acme$
snapcraft push acme-pc_24_amd64.snap
The Store automatic review failed.
A human will soon review your snap, but if you can't wait please write in
the snapcraft forum asking for the manual review explicitly.

If you need to disable confinement, please consider using devmode, but
note that devmode revision will only be allowed to be released in edge and beta
channels.
Please check the errors and some hints below:
  - (NEEDS REVIEW) type 'gadget' not allowed

At this point, you should add a collaborator to the gadget snap and logout of the Brand account. A good choice for such an account would be one with the Viewer role in the Alpha 3 and acme id stores.

Log into the web dashboard as admin@acme.com, the Reviewer for the Alpha 3 store, and access the reviews page to approve the gadget revision.

Login to the account you made a Collaborator on the gadget snap. Once the revision is approved, you can use snapcraft to release it in the stable channel as a Collaborator:

user@localhost:~/acme$
snapcraft whoami
email:        [email protected]
developer-id: brand-account
user@localhost:~/acme$
snapcraft release acme-pc 1 stable
Track    Arch    Channel    Version    Revision
latest   all     stable     24     1
                 candidate  ^          ^
                 beta       ^          ^
                 edge       ^          ^
The 'stable' channel is now open.

The gadget snap is now available for installation from the acme id store and for inclusion in images.

Creating the model assertion

The final step before you can build a custom Ubuntu Core image is creating a model assertion, which provides image related metadata ubuntu-image uses to build the image. In order to create the model assertion, a key registered to the Brand account must sign the JSON for the model assertion. For details on how to create and register a model key, please refer to Sign a model assertion.

The below creates a JSON file which can be signed to create a model assertion.

Access the snap page to get the acme-pc snap’s snap ID and fill the <CUSTOMER_SNAP_IDS> field.

user@localhost:~/acme$
cat << EOF > alpha-model.json
{
  "type": "model",
  "authority-id": "brand-account",
  "brand-id": "brand-account",
  "series": "16",
  "model": "alpha",
  "store": "acme-id",
  "architecture": "amd64",
  "base": "core24",
  "grade": "dangerous",
  "snaps": [
    {
      "default-channel": "latest/stable",
      "id": "<CUSTOMER_SNAP_IDS>",
      "name": "acme-pc",
      "type": "gadget"
    },
    {
      "default-channel": "24/stable",
      "id": "pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza",
      "name": "pc-kernel",
      "type": "kernel"
    },
    {
      "default-channel": "latest/stable",
      "id": "dwTAh7MZZ01zyriOZErqd1JynQLiOGvM",
      "name": "core24",
      "type": "base"
    },
    {
      "default-channel": "latest/stable",
      "id": "PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4",
      "name": "snapd",
      "type": "snapd"
    },
    {
      "name": "console-conf",
      "type": "app",
      "default-channel": "24/stable",
      "id": "ASctKBEHzVt3f1pbZLoekCvcigRjtuqw",
      "presence": "optional"
    }
  ],
  "timestamp": "$(date +%Y-%m-%dT%TZ)"
}
EOF
user@localhost:~/acme$
snapcraft list-keys
    Name          SHA3-384 fingerprint
*   serial        <fingerprint>
*   model         <fingerprint>
user@localhost:~/acme$
snap sign -k model alpha-model.json > alpha-model.assert

Ensure that all snaps listed in the model assertion are available in the acme id store. If they are not, you must include them.

Creating the image

These are example instructions specific to your particular Dedicated Snap Store. To see more general instructions, please refer to the Build your first image and Image creation public documentation.

user@host:~$
sudo snap install --classic --channel=latest/stable ubuntu-image

In order for ubuntu-image to able to access snaps from your Dedicated Snap Store, you need to provide credentials for a Viewer account using one of the following environment variables:

  • UBUNTU_STORE_AUTH - this must be set to the actual contents of the file

    (e.g. store.auth) containing your exported developer credentials.

  • UBUNTU_STORE_AUTH_DATA_FILENAME - this must be set to the path of the file

    containing your exported developer credentials.

The Ubuntu Core image is built by using the above developer account credential. Because the console-conf snap is marked as presence: optional in the JSON above, we must explicitly include it in the image.

user@host:~$
UBUNTU_STORE_AUTH=$(cat store.auth) ubuntu-image snap --snap console-conf alpha-model.assert

Launching and verifying the image

To launch and test your newly generated Ubuntu Core image, follow the Testing with QEMU steps. Once the image is booted and installed, you can log in then verify if the all required snaps are installed, the alpha model is correct and a serial assertion was obtained:

acme-sso-user@localhost:~$
Welcome to Ubuntu 24 (GNU/Linux <kernel version> x86_64)
...
Please see 'snap --help' for app installation and updates.
...
acme-sso-user@localhost:~$
snap list
Name          Version      Rev    Tracking       Publisher    Notes
console-conf  24.04.1      40     24/stable      canonical✓   -
core24        20240528     423    latest/stable  canonical✓   base
pc-kernel     6.8.0-40.40  1938   24/stable      canonical✓   kernel
snapd         2.63         21759  latest/stable  canonical✓   snapd
acme-sso-user@localhost:~$
snap changes
ID   Status  Spawn               Ready               Summary
1    Done    today at 07:15 UTC  today at 07:16 UTC  Initialize system state
2    Done    today at 07:16 UTC  today at 07:16 UTC  Initialize device
acme-sso-user@localhost:~$
snap model --assertion
type: model
authority-id: brand-account
series: 16
brand-id: brand-account
model: alpha
...
acme-sso-user@localhost:~$
snap model --serial --assertion
type: serial
authority-id: brand-account
revision: 1
brand-id: brand-account
model: alpha
...