Inside Ubuntu Core 20
Ubuntu Core 20 (UC20) is built on the foundations of Ubuntu 20.04 LTS (Focal Fossa). It’s the next generation of Ubuntu for embedded devices.
New features for this release include:
- Raspberry Pi support (both ARMv7 and ARMv8)
Full-disk encryption via TPM integration
- x86-only, with ARM to follow.
- TPM integration works with existing CA
Recovery and reinstall modes
- Includes recovery mode menu and chooser
- Initial MAAS & cloud-init support
The kernel, boot assets, runtime environment, applications and device enablement capabilities are all delivered as snaps that are controlled by snapd (the snap daemon), which is itself packaged as a snap.
See below for how these elements combine in UC20.
The following components make up Ubuntu Core 20:
snapd is the system daemon that supervises all other snaps on Ubuntu Core. It exposes a REST API that makes Ubuntu Core appliances IP addressable by default. This API facilitates device management.
application snaps define the functionality of an embedded device and are confined with all their dependencies to their own sandbox. Interfaces to other applications or to the system can be created.
system snaps enable device capabilities like audio, power, disk storage and networking. Docker containers orchestration and virtualisation capabilities are provided through Microk8s and LXD.
boot assets come from the gadget snap and include board-specific binaries and data, such as bootloader, device tree, configuration files, and cloud-init configuration for edge virtualisation use cases. The gadget snap is typically issued and signed by board OEM/ODMs.
core snap holds the execution environment inside which applications run. It also serves as the root file system for Ubuntu Core images. Core snaps include basic Ubuntu 20.04 LTS packages.
kernel snap holds the kernel image and associated modules. It will also contain an initial ramdisk image for system initialisation. Firmware and device tree files can optionally be packaged here. The kernel snap can be updated but it cannot be swapped.
The above snaps are combined using the
ubuntu-image tool to create the Ubuntu Core installation image.
The REST API
Ubuntu Core exposes a built-in REST API for secure device command and control. Authenticated and authorised clients can perform software management and configuration tasks on their Ubuntu Core devices remotely. Devices running Ubuntu Core can be configured remotely via the REST API.
See Snaps in Ubuntu Core for a general overview, and see below for details on the UC20 specific configuration.
The storage layout of the generated image used to install Ubuntu Core, and the resultant storage on the device, is described by the gadget snap and its associated gadget.yaml file.
Ubuntu Core 20 typically uses the following storage partitions:
- ubuntu-seed (role: system-seed; read-only, vfat-formatted): contains the configuration for the first-stage/recovery boot loader and at least one recovery system which is a set of snaps (base, kernel, gadget and application snaps) together with a model assertion and snap assertions that define the device and for which the device can be recovered or reinstalled.
- ubuntu-boot (role: system-boot; read-only, ext4 or vfat): contains the second-state/run bootloader and unpacked kernel(s) to boot and with initramfs which decrypts the ubuntu-data and ubuntu-save partition.
- ubuntu-save (role: system-save; writable, ext4): stores device identity backup data and data to facilitate recovery or re-install. This partition is mandatory on encrypted systems where it should have a minimum size of approximately 20+MB to handle volume and file system creation.
- ubuntu-data (role: system-data; writable, ext4): stores user and system data. This partition is often minimally sized in the image but extended during device initialisation to use all the space available.
The system boot process:
- verifies the bootloaders and kernel signatures
- measures the above and the kernel command line with the TPM
- on top of the above trusted set the snapd initrd code measures the snap device model
- snapd then separately verifies other snaps with their assertions as needed
snap-bootstrap is the main executable that is run during the early initramfs booting stage of UC20. It has the following responsibilities:
- Mounting selected partitions from the disk that UC20 is on. Partitions include data, system-boot, seed, and if present, save (optional on unencrypted devices).
- As part of mounting those partitions, snap-bootstrap may perform the necessary steps to unlock any encrypted partitions such as ubuntu-data and ubuntu-save (see Full disk encryption).
- After unlocking and mounting all such partitions, snap-bootstrap then chooses which base snap is to be used for the root filesystem of userspace (the root filesystem of the initramfs is just a static set of files built into the initramfs and is not the final root filesystem), and mounts this base snap file.
- snap-bootstrap then chooses which kernel snap is to be used to mount and find additional kernel modules that are not compiled into the kernel or shipped as modules inside the initramfs or otherwise loaded as DTBs, etc.
- snap-bootstrap will then mount the ubuntu-data partition such that either the writable components of the root filesystem come from this actual partition, or if the mode the system is booting into is an ephemeral system such as install or recover, will mount a temporary filesystem for this.
- snap-bootstrap on kernel and base snap upgrades will also handle updating bootloader environment variables to implement A/B or try-boot functionality.
- snap-bootstrap then finally may do some additional setup of the root filesystem such as copying some default files for ephemeral system modes such as recover.
There are several layers of isolation that make snaps strictly confined.
The first layer of isolation is logical: a snap is a self-contained file system mounted on a Linux system. Snaps are immutable with least privileges by default, which make it easy to build tamper-proof devices.
Isolation mechanisms rooted in the Linux kernel add an additional layer of isolation through Cgroups and Namespaces:
|Cgroups Limit the amount of resources the process confined to a snap can consume (CPU, memory, network bandwidth, and so on).||Namespaces Make sure processes in a snap see their own personal view of the system (files, processes, network interfaces, hostname, and so on).|
|AppArmor Allows system administrators to restrict snap capabilities with default security profiles that can be extended.||Seccomp Isolates processes running in a snap by limiting the system calls they are allowed to make.|
See Security and sandboxing for further details on how confinement is implemented.