LXD distrobuilder howto

We want to use the tool distrobuilder to create LXC/LXD containers, see LXC Distrobuilder Tutorial. The host system is Ubuntu 22.04.

The starting point may be https://blog.simos.info/using-distrobuilder-to-create-container-images-for-lxc-and-lxd/ but this page lacks some details.

The following examples are using the LXD fork called “incus”, see https://linuxcontainers.org/incus/.

Note: See the LXC/LXD cheat-sheet https://gist.github.com/berndbausch/a6835150c7a26c88048763c0bd739be6

Now installing the distrobuilder and the tool debootstrap , see https://github.com/lxc/distrobuilder/tree/main

$ sudo snap install distrobuilder --classic
$ sudo apt install -y debootstrap

Now create a template for the container, for example download the debian template, see examples at https://github.com/lxc/lxc-ci/tree/main/images

$ mkdir -p templates/debian/
$ cd templates/debian/
$ curl https://raw.githubusercontent.com/lxc/lxc-ci/main/images/debian.yaml >  debian.yaml

Now create the container, specifying the architecture and release to avoid download failures “Error while downloading source”

# distrobuilder build-incus -o image.architecture=amd64 -o image.release=bookworm debian.yaml 

The tool distrobuild will now download the resources and will create two output files
* meta.tar.xz
* rootfs.tar.xz

INFO   [2024-01-15T17:05:26+01:00] Downloading source                           
I: Retrieving InRelease 
I: Checking Release signature
I: Valid Release signature (key id 4CB50190207B4758A3F73A796ED0E7B82643E131)
I: Retrieving Packages 
I: Validating Packages 
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Checking component main on https://deb.debian.org/debian...
I: Retrieving libacl1 2.3.1-3
INFO   [2024-01-15T17:09:15+01:00] Skipping generator                            generator=fstab
INFO   [2024-01-15T17:09:15+01:00] Running hooks                                 trigger=post-files
+ umount -l /etc/resolv.conf
+ ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
INFO   [2024-01-15T17:09:15+01:00] Creating LXC image                            compression=xz
 INFO   [2024-01-15T17:12:33+01:00] Removing cache directory                     

The directory should look like

# ls -l
total 98144
-rw-r--r-- 1 root root     72655 Jan 15 20:35 debian.yaml
-rw-r--r-- 1 root root       708 Jan 15 20:42 incus.tar.xz
-rw-r--r-- 1 root root 100421632 Jan 15 20:42 rootfs.squashfs

The following command will import the newly build container

# incus image import incus.tar.xz rootfs.squashfs --alias mycontainerimage
Image imported with fingerprint: 0e582e2407463f4f9beffb083fe81f274e04fbf0421998003c07053b1c47e84b

After the import, the container will be listed

# incus image ls
|      ALIAS       | FINGERPRINT  | PUBLIC |              DESCRIPTION              | ARCHITECTURE |   TYPE    |   SIZE   |         UPLOAD DATE          |
| mycontainerimage | 0e582e240746 | no     | Debian bookworm amd64 (20240115_1936) | x86_64       | CONTAINER | 95.77MiB | Jan 15, 2024 at 7:48pm (UTC) |

The container can be started using

# incus launch mycontainerimage c1
Creating c1
The instance you are starting doesn't have any network attached to it.
  To create a new network, use: incus network create
  To attach a network to an instance, use: incus network attach

Starting c1

Flutter not suitable for RaspberryPI 3B+

Flutter seems to be a nice GUI framework to create portable GUIs for all kinds of systems, such as Win, Desktop-Linux, Android, iPhone. Just the latest version doesn’t seem suitable for RaspberryPI 3B+ (1GB RAM) based Linux systems.

I wasn’t even able to produce a native GUI app for RP3B+ at all. The initial set up of Flutter environment on RaspberryPI 3B+ failed already, running out of memory (RAM). And AFAICS the underlying dart compiler does not support cross compilation yet, therefor it is not possible to execute the flutter/dart compiler on amd64 to produce native code for RP3B+/ARMv8.

Flutter seems to be nice for systems with 4GB of RAM or more, but Flutter doesn’t seem suitable for devices such as the RaspberryPI 3B+, providing 1GB of RAM “only”.

Rust borrowing/lifetime & Modules

The connections between modules are the assumptions which the modules make about each other.

David Parnas
Information Distribution Aspects of Design Methodology, 1971

The Rust borrowing and lifetime concept help to express the assumptions being made between modules.

Defining an API, it is not about the signature of methods only, but also about the assumption about the usage and lifetime of the input and output data.

FIT image containing u-boot script

FIT images may be signed and verified by bootloader u-boot, as required for opencritis.org. FIT images may contain multiple images, such as the kernel, fdt device trees initramfs and scritps.

As the FIT image is tagging each embedded element, these entities are embedded in raw format, for example zImage, initrd.cpio and the scripts as simple text files. For example see this fit image declaration of file “image.its”


/ {
  description = "OpenCritis arm/virt FIT Image";
  #address-cells = <1>;

  images {
          kernel {
             description = "Kernel";
             data = /incbin/("zImage");
             type = "kernel";
             arch = "arm";
             os = "linux";
             compression = "none";
             load = <0x40400000>;
             entry = <0x40400000>;
             hash {
                algo = "sha256";

          fdt {
            description = "Flattened Device tree";
            data = /incbin/("nxp6ulevk.dtb");
            type = "flat_dt";
            arch = "ARM";
            compression = "none";
            hash {
      	       algo = "sha256";
      bootscript {
        description = "Bootscript";
        data = /incbin/("u-boot.scr");
        type = "script";
        compression = "none";

configurations {
      default = "standard";
      standard {
            description = "Standard Boot";
            kernel = "kernel";
            fdt = "fdt";
            hash {
                    algo = "sha256";

An u-boot script “u-boot.scr” has the form:

setenv bootargs "console=ttyAMA0,115200 ro rootwait root=/dev/sda2"
bootm  ${loadaddr}
echo "Bad image or kernel."

The fit image “image.ub” is generated using the following command

mkimage -f image.its image.ub 

Loading a fit image and sourcing the script is done as follows:

setenv loadaddr 0x48000000
fatload mmc 0:1  ${loadaddr} image.ub
source ${loadaddr}:bootscript

Note: indexed node names will be refused by u-boot FIT parser yielding “Bad FIT image format”, for example do not use the following form

script@1 { .... };