Table of Contents

What are Layers?

Layers are modular, composable components that define specific aspects of your Raspberry Pi build. Each layer encapsulates a specific and focussed piece of functionality and can declare dependencies on other layers, creating a flexible build system. Layers have been loosely grouped into categories with a super-set being as follows.

  • Device Layers: Hardware-specific configuration for a particular device type. For example, may only install firmware applicable to Pi5.

  • Image Layers: Image-specific configuration to produce an image with a defined footprint / on-disk layout. For example, an image capable of supporting AB booting for OS and system slot redundancy.

  • General Layers: Reusable configuration snippets, utilities, groups of related functionality, packages and/or scripts. For example, local system user account creation, basic networking, etc.

  • Suites: A layer providing a particular baseline of device functionality. Typically, these type of 'profile' layers are agnostic to the underlying device. Using a suite allows a single layer to recursively pull in other layers to provide a common base of functionality such as a desktop or SDK, or a minimal set of userland components providing apt and networking, container utilities, etc.

How are Layers Used?

rpi-image-gen uses custom metadata in a layer to declare variables and construct a deterministic layer build order then passes this to bdebstrap (https://github.com/bdrung/bdebstrap) which aggregates and merges everything together into a configuration. That configuration is handed off to mmdebstrap (https://gitlab.mister-muffin.de/josch/mmdebstrap) which is the engine that drives creation of the filesystem. By using bdebstrap, layers provide a structured way to configure and extend mmdebstrap’s capabilities:

Layer Structure

Each layer is a YAML file containing:

  • X-Env Metadata: Mandatory. Layer attributes, variable declarations, dependencies

  • mmdebstrap configuration: Optional. Package lists, repository mirrors, scripts

Build Process

  1. Parameter Assembly: Config file, cmdline and CLI establish desired layers, environment variables and search paths

  2. Layer Resolution: Layer dependencies determine build order

  3. Variable Expansion: Environment variables are validated and expanded using defined rules

  4. Configuration Merging: Layer are merged

  5. mmdebstrap Execution: The merged configuration drives mmdebstrap to create the filesystem

  6. Processing: Additional layer-specific scripts are executed at defined points, eg setup, essential, customize, cleanup, etc

  7. Post-Processing: filesystem overlays, SBOM generation, image creation, hooks

Key Benefits of Layers

  • Modularity: Mix and match layers to create custom images

  • Reusability: Share common configurations across different builds

  • Validation: Built-in variable validation prevents configuration errors

  • Dependencies: Automatic resolution of layer prerequisites

  • Customisation: Override defaults through environment variables set via the config file

X-Env Metadata

Layers use a custom X-Env metadata schema that strictly follows the DEB822 format (https://repolib.readthedocs.io/en/latest/deb822-format.html) embedded within YAML comment blocks. The metadata is delimited by # METABEGIN and # METAEND markers and parsed using the standard python3-debian DEB822 parser. By using metadata fields a layer can define attributes, dependencies, and configuration variables. The metadata is parsed separately from the standard YAML content.

Metadata Structure

X-Env metadata is contained within comment blocks:

# METABEGIN
# X-Env-Layer-Name: This layer's name
# X-Env-Layer-Description: Brief description of what this layer does
# X-Env-Layer-Category: device
# X-Env-Layer-Requires: base-layer,required-layer
# X-Env-VarPrefix: device
# X-Env-Var-hostname: pi-${HOSTNAME_SUFFIX}
# X-Env-Var-hostname-Description: System hostname for the device
# X-Env-Var-hostname-Valid: regex:^[a-zA-Z0-9.-]+$
# X-Env-Var-hostname-Set: immediate
# METAEND

# mmdebstrap YAML configuration follows...

mmdebstrap:
  packages:
    - systemd
    - network-manager

Static vs Dynamic Layers

Layers are static unless explicitly marked dynamic. To render a layer at build time add:

# X-Env-Layer-Type: dynamic
# X-Env-Layer-Generator: myscript

The loader then:

  1. Checks for the existence of a temporary directory specified by tag TMPROOT_layer=<tmpdir> on the layer search path (rpi-image-gen does this automatically).

  2. Runs the generator with two arguments, <template-path> <output-path>, where the output is written to TMPROOT_layer/path/to/<layer-name>.yaml. The path/to portion matches the layer’s path under its original search root, so dynamic layers mirror the same directory structure as static layers when reported via tagged paths.

  3. Reads all mmdebstrap/env content from the generated file while continuing to use the original # X-Env-* metadata for naming, dependencies, documentation, etc.

Generators must write a complete layer to the output path. A trivial generator could copy the template directly to the output (e.g. cp works fine). More more complex generators may inject snapshot timestamps, merge user data, or pull content from other sources. If the generator writes nothing, the layer still 'exists' (metadata is intact) but it contains no YAML body information (packages, hooks, etc) and --describe output will reflect that. Dynamic layers provide a way to manipulate the layer YAML at build time. Modifications made by the generator only affect the YAML body. The original # X-Env-* metadata is always taken from the template.

Important

X-Env-Layer-Generator must resolve to an executable (on PATH or via a relative/absolute path).

Note

rpi-image-gen ships its own generators in bin/generators. If a source directory was specified at build time, <SRCROOT>/bin/generators is automatically included in PATH if present.

Layer Attributes

X-Env-Layer-Name: Layer name

X-Env-Layer-Description: Human-readable description of the layer’s purpose

X-Env-Layer-Category: Categorisation (device, image, etc.)

X-Env-Layer-Version: Version identifier for the layer

X-Env-Layer-Requires: Comma-separated list of required layers

X-Env-Layer-Provides: Services or capabilities this layer provides

X-Env-Layer-RequiresProvider: Services or capabilities this layer requires

X-Env-Layer-Conflicts: Layers that cannot be used together with this one

X-Env-Layer-Type: Static (default) or dynamic

X-Env-Layer-Generator: If dynamic, the generator invoked by the loader

Dependencies and Providers

X-Env-Layer-Requires

  • Direct layer references: "I need these specific layers"

  • Concrete dependencies: Must reference actual layer names

  • Environment variable expansion: Supports ${VAR} syntax for dynamic dependencies

  • Build order enforcement: Dependencies are loaded first and are pull in automatically

  • Example: A device layer depends on a device base-layer because the base-layer provides mandatory settings inherited by the device layer.

# METABEGIN
# X-Env-Layer-Name: conditional-layer
# X-Env-Layer-Requires: base-layer,${ARCH}-toolchain,${DISTRO}-packages
# METAEND

Environment variables in dependencies are evaluated during layer discovery using the current environment context. If a required environment variable is not set, layer discovery will fail.

This enables dynamic layer dependency resolution based on build-time variables such as:

  • Architecture: ${ARCH}-toolchain resolves to arm64-toolchain when ARCH=arm64

  • Distribution: ${DISTRO}-packages resolves to debian-packages when DISTRO=debian

  • Build variant: ${VARIANT}-config for different build configurations

Important

Only variables present in the environment can be used in dependencies.

X-Env-Layer-Provides / X-Env-Layer-RequiresProvider

  • Abstract capability requirements: "I need something that provides X"

  • Service/capability contracts: Multiple layers could satisfy the requirement

  • Flexible implementation: Any layer providing the capability can fulfill it

  • Relationships: If a provider is required, only one can exist in the overall configuration

  • Example: A layer requires a device provider, which could be satisfied by different device layers

Important

Unlike dependencies, environment variables are not supported when evaluating providers.

Environment Variables

X-Env-VarPrefix: Prefix for all variables declared by this layer (e.g., device)

X-Env-VarRequires: Comma-separated list of variables this layer expects from other layers

X-Env-Var-<name>: Variable declaration with default value (supports placeholders like ${DIRECTORY})

X-Env-Var-<name>-Description: Human-readable description of the variable

X-Env-Var-<name>-Valid: Validation rule (type, range, regex, enum, etc.)

X-Env-Var-<name>-Set: Set policy (immediate, lazy, force, skip)

Variable Naming Convention

Variables follow the pattern: IGconf_<prefix>_<name>

  • Layer declares: X-Env-Var-hostname with prefix device

  • Environment variable: IGconf_device_hostname

  • Template expansion: Can reference as ${IGconf_device_hostname} in YAML values

Placeholder Support

Variable values support dynamic placeholders:

${DIRECTORY}: Directory containing the layer file

${FILENAME}: Name of the layer file (without extension)

${FILEPATH}: Full path to the layer file

Configuration Variables

The environment variables declared by a layer customise build behavior:

  • Validation: Each variable includes validation rules (types, ranges, patterns)

  • Placeholders: Support for dynamic values like ${DIRECTORY} and ${FILENAME}

  • Set Policies: Control when and how variables are applied during layer resolution

  • Documentation: Integrated help and validation error messages

For variable validation help and policy explanations, use rpi-image-gen metadata --help-validation or refer to the variable-validation help page accessible via the individual layer documentation pages.

For detailed information about a particular layer, including configuration options and defaults, please inspect the layer via the command line (rpi-image-gen layer --describe <layer name>) or refer to the layer’s documentation page. It is recommended to use a config file to set layer variables. Layers that declare variables specify a defined prefix. Use this prefix in the config file to set variables applicable to that layer. For example - device and image layers define variables with prefix 'device' and 'image' respectively:

device:
  storage_type: nvme

image:
  compression: zstd

Device and Image Layers

The config system allows device and image layers to be specified two different ways. Both yield the same result. The main difference is that the latter allows the name of the variable holding the device/image layer to be defined by the user, therefore making it customisable. Using the former makes more sense if defining other device settings since they can all be encapsulated under the same section in the config file.

device:
  layer: rpi5
layer:
  myvar: rpi5

The above would result in two variables being defined:

IGconf_device_layer=rpi5
IGconf_layer_myvar=rpi5

Both would pull layer rpi5 into the system configuration.

rpi-image-gen expands and references all IGconf_layer_* variables at layer collection time, whereas it looks specifically for IGconf_device_layer and IGconf_image_layer to locate device and image layers respectively for those particular sections.

It’s worth noting that rpi-image-gen does not mandate a device or image layer being specified. The construction of a filesystem can take place with or without either of these. For example, a user may wish to use rpi-image-gen to create a filesystem tar ball for use in a docker container.

Specifying Layers

Layers can be specified in the config file by name (i.e. their X-Env-Layer-Name). The name of the variable containing the layer name is completely arbitrary.

layer:
  foo: trixie-minbase
  bar: rpi5
  app: my-app

This would result in the following variables being defined:

IGconf_layer_foo=trixie-minbase
IGconf_layer_bar=rpi5
IGconf_layer_app=my-app

rpi-image-gen would attempt to locate layers trixie-minbase,rpi5 and my-app, including their depdendencies. Deduplication of layers occurs at the resolution phase, meaning that specifying duplicate layer names is harmless and basically a nop.

How to Use This Documentation

  • Browse the auto-generated layer list (currently only available in the HTML documentation) to find layers relevant to your build

  • Click on any layer name to view detailed documentation information including:

  • Configuration variables and their validation rules

  • Package dependencies and installation details

  • Layer relationships and dependencies

  • Technical implementation details and companion information

Getting Started

  1. Choose a device layer that matches your Raspberry Pi hardware

  2. Choose an image layer applicable to your deployment

  3. Add a suite and/or list of general layers for additional functionality

  4. Configure the variables as documented in each layer

  5. Run rpi-image-gen build with your config

Available Layers

Audit

sbom-base- SBOM provider and settings.

Build

artefact-base- Base artefact naming, versioning and organisation for filesystem builds.
deploy-base- Deployment and organisation for build output artefacts
sys-build-base- Build environment configuration including workspace, apt settings, and system foundation defaults.
target-config- bdebstrap output target configuration.

Container

docker-debian-bookworm- Docker engine and framework for Debian Bookworm
docker-debian-trixie- Docker engine and framework for Debian Trixie

Device

device-base- Device defaults.
rpi-cm4- Raspberry Pi CM4 specific device layer
rpi-cm5- Raspberry Pi CM5 specific device layer
rpi-generic64- Generic Raspberry Pi device common with v8 kernel, boot firmware supporting all devices, and wlan/BT firmware.
rpi3- Raspberry Pi 3 specific device layer
rpi4- Raspberry Pi 4 specific device layer
rpi5- Raspberry Pi 5 specific device layer
rpizero2w- Raspberry Pi Zero 2 W specific device layer

Distribution

debian-bookworm-arm64- Debian Bookworm apt base for arm64
debian-bookworm-arm64-multi- Debian Bookworm apt base for arm64 and armhf.
debian-bookworm-arm64-slim- Debian Bookworm custom layer for arm64 providing a usable and practical base.
debian-bookworm-buildd- Architecture agnostic Debian Bookworm buildd base. This provides a base layer specifically designed for automated pa...
debian-trixie-arm64- Debian Trixie apt base for arm64.
debian-trixie-arm64-multi- Debian Trixie apt base for arm64 and armhf.
debian-trixie-arm64-slim- Debian Trixie custom layer for arm64 providing a usable and practical base.
debian-trixie-buildd- Architecture agnostic Debian Trixie buildd base. This provides a base layer specifically designed for automated pack...
raspbian-bookworm-armhf- Raspbian Bookworm apt base for armhf.
raspbian-trixie-armhf- Raspbian Trixie apt base for armhf.

Firmware

rpi-boot-firmware- Raspberry Pi boot firmware for all devices

Foundation

essential- Serves as the mandatory foundation for all rpi-image-gen builds, and is automatically included in every configuratio...
locale-base- Default locale settings

General

ca-certificates- Common CA Certificate PEM files
fake-hwclock- Persistent time management for non-RTC systems.
openssh-server- OpenSSH server daemon and local user SSH key setup.
rpi-debian-bookworm- Raspberry Pi Debian Bookworm APT repository
rpi-debian-trixie- Raspberry Pi Debian Trixie APT repository
rpi-essential-base- Raspberry Pi essential basic system packages
rpi-misc-skel- Raspberry Pi miscellaneous filesystem directory skeleton.
rpi-misc-utils- Raspberry Pi system utilities
rpi-splash-screen- Raspberry Pi fullscreen splash screen support with custom image configuration.
rpi-user-credentials- Raspberry Pi base layer for local user admin. Creates a local account for user IGconf_device_user1, a home directory...
systemd-min- Core systemd components for init, SysV compatibility and timesyncd, without networkd and resolved services.
systemd-net-min- Systemd networking via networkd and resolved services

Image

image-base- Default image settings and build attributes.
image-rota- Immutable GPT A/B layout for rotational OTA updates, boot/system redundancy, and a shared persistent data partition.
image-rpios- Raspberry Pi OS style image layout with MBR, vfat boot partition, and a root partition that can be ext4 or btrfs.
rpi-ab-slot-mapper- Dynamic slot device management for A/B boot: udev rules and helpers that create stable by-slot symlinks from GPT PAR...

Kernel

rpi-linux-2712- Raspberry Pi 2712 kernel
rpi-linux-v7- Raspberry Pi v7 kernel
rpi-linux-v7l- Raspberry Pi v7l kernel
rpi-linux-v8- Raspberry Pi v8 kernel

Service

rpi-connect- Raspberry Pi Connect client with screen-sharing support and remote shell access
rpi-connect-lite- Raspberry Pi Connect client with remote shell access

Suite

bookworm-minbase- Debian Bookworm with apt, utils, wired networking, ssh.
trixie-minbase- Debian Trixie with apt, utils, wired networking, ssh.

Toolchain

arm64-toolchain-cross- ARM64 cross-compilation toolchain
arm64-toolchain-native- ARM64 native compilation toolchain
autotools-base- Autotools build environment
build-user- Environmental setup for dedicated build user
debian-dev-tools- Debian package development and maintenance tools
gnu-common- Common GNU toolchain setup with ccache and environment
kbuild-base- Linux kernel build environment with Debian packaging support.