Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions docs/explanation/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,29 @@ The build system is designed around three principles:

- **Minimal host dependencies** — The build runs entirely inside a container. Apart from the
container engine itself, the host needs no build tools.
- **Composability** — Images are assembled from reusable [features](/explanation/flavors#feature-based-design)
- **Composability** — Images are assembled from reusable [features](/explanation/features#feature-types)
rather than hand-crafted for each target. The same feature definition is reused across all
platforms that include it.
- **Reproducibility** — The builder container is versioned and pinned, so a given combination
of source code and feature set should produce the same image regardless of when or where it
is built.

## Flavor Names as Build Inputs
## Versioned Flavors as Build Inputs

The build command takes a *flavor name* as its argument. A flavor name directly encodes what
will be built:
The `./build` script accepts a **cname** (`{cname}`), a **flavor** (`{cname}-{arch}`), or a **versioned flavor** (`{cname}-{arch}-{version}`) as its argument.

```
<platform>-<feature1>-<feature2>_<feature3>-<arch>
```
When no version is included in the argument, it is derived automatically by calling `./get_version`, which reads the `VERSION` file in the repository root:

For example, `aws-gardener_prod-amd64` tells the builder to produce an AWS image (`aws`) with
the [`gardener`](/reference/features/gardener) and [`_prod`](/reference/features/_prod) features for the `amd64` architecture. The build script parses this
name and assembles the image by combining the specified platform and features.
- On `main`, `VERSION` contains `today`, so the literal string `today` is used as the version.
- On a release branch, `VERSION` contains the full semver for that branch (e.g. `2150.5.0`), and `get_version` returns it as-is.

For a full explanation of how flavors and features compose, including the [CNAME system](/explanation/flavors#the-cname-system) and how
features are joined, see [Flavors](/explanation/flavors).
When a version is explicitly provided on the command line (e.g. `./build aws-amd64-2142.0.0`), that version is used directly. The builder fetches the matching versioned container image while using the source code from the currently checked-out commit.

The resolved version is passed to `make` as `DEFAULT_VERSION` and combined with the flavor to form the **versioned flavor** (`{cname}-{arch}-{version}`) used internally.

For example, `./build aws-gardener_prod-amd64` on `main` produces artifacts prefixed `aws-gardener_prod-amd64-today-<short_commit>`.

The four-level naming hierarchy — cname, flavor, versioned flavor, and artifact base name — is defined in [ADR 0035](/reference/adr/0035-cname-flavor-artifact-naming). For a full explanation of how features and feature types compose, see [Flavors](/explanation/flavors) and [Features](/explanation/features). For the canonical names specification, see [Flavors Reference](/reference/flavors#canonical-names).

## Cross-Architecture Builds

Expand Down
105 changes: 105 additions & 0 deletions docs/explanation/features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: Features
description: Feature types, dependency graph resolution, and composition rules in Garden Linux
order: 121
related_topics:
- /explanation/flavors.md
- /reference/flavors.md
- /reference/features/
- /reference/adr/0034-feature-terminology.md
- /reference/adr/0020-enforce-single-platform-by-default-in-builder.md
migration_status: "done"
migration_issue: "https://github.com/gardenlinux/gardenlinux/issues/4600"
migration_stakeholder: "@tmangold, @yeoldegrove, @ByteOtter"
migration_approved: false
github_org: gardenlinux
github_repo: builder
github_source_path: docs/explanation/features.md
github_target_path: docs/explanation/features.md
---

# Features

## What Is a Feature?

A **feature** is the atomic building block of a Garden Linux image. Each feature is a named directory inside the `features/` tree of the Garden Linux repository containing at minimum an `info.yaml` file that declares its type and dependencies.

Features are not independent. They form a **directed acyclic graph (DAG)** where each feature may declare:

- `features.include` — Other features that are automatically pulled in when this feature is selected
- `features.exclude` — Other features that are removed from the build if they were only transitively included

The DAG is resolved and validated at build time. Explicitly including an excluded feature is a hard build error.

A feature is not just a package list, but a complete configuration unit that may include:

- **Packages** — APT packages to install
- **Configuration files** — System configuration with appropriate defaults
- **Scripts** — Setup and lifecycle scripts
- **Dependencies** — A list of other features to include or exclude

For example, the [`gardener`](/reference/features/gardener) element feature does not just install `containerd` — it also configures systemd services and includes other features such as [`log`](/reference/features/log) to set up logging.

## Feature Types

Every feature has exactly one type, declared in its `info.yaml` file. The type is primarily a descriptive and user-facing classification; it does not change how the feature participates in the DAG or how its content is applied during the build.

The three feature types are defined in [ADR 0034](/reference/adr/0034-feature-terminology):

| Type | Description | Examples |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| **platform** | Represents the deployment target — the combination of hardware, firmware, and cloud or hypervisor environment the image is intended to run on. | [`aws`](/reference/features/aws), [`azure`](/reference/features/azure), [`gcp`](/reference/features/gcp), [`kvm`](/reference/features/kvm), [`baremetal`](/reference/features/baremetal), [`container`](/reference/features/container) |
| **element** | Represents a functional component or capability added on top of the platform. Elements are composable: multiple elements may be present in a single build. | [`gardener`](/reference/features/gardener), [`server`](/reference/features/server), [`cloud`](/reference/features/cloud), [`cis`](/reference/features/cis), [`firewall`](/reference/features/firewall), [`metal`](/reference/features/metal) |
| **flag** | Represents a lightweight modifier. Flags are identified by a leading underscore (`_`) in their name. Flags are intended for minor behavioural changes that do not warrant a full element and should not include other features. | [`_prod`](/reference/features/_prod), [`_fips`](/reference/features/_fips), [`_trustedboot`](/reference/features/_trustedboot), [`_usi`](/reference/features/_usi) |

:::tip
A complete list of features can be seen in the [Features Reference](/reference/features/).
:::

## Include/Exclude Semantics and DAG Resolution

When you specify features for a build, the builder resolves the complete feature set by following the DAG:

1. Validate that all available features form a valid DAG (no cycles) — this check runs on the full, unfiltered feature graph before any resolution begins
2. Start with the explicitly requested features
3. Recursively include all features listed in each feature's `features.include` list
4. Remove any features listed in `features.exclude` lists (but only if they were transitively included); attempting to exclude a feature that was explicitly requested is a hard build error

For example, if you request [`aws`](/reference/features/aws) and [`gardener`](/reference/features/gardener):

- The [`aws`](/reference/features/aws) platform feature includes dependencies for cloud-init, kernel modules, etc.
- The [`gardener`](/reference/features/gardener) element feature includes the [`log`](/reference/features/log) feature for logging configuration
- Both features exclude certain features that are incompatible with their use case
- The builder resolves the complete set and validates there are no conflicts

:::tip
For the precise mechanics of how feature content (package lists, file overlays, build-time scripts) is applied during the build, see the [builder reference documentation for features](/reference/features/).
:::

## Single-Platform Rule as Design Decision

Each Garden Linux build enforces exactly one platform feature by default. Specifying zero or multiple platforms causes the build to fail, preventing silent misconfigurations where multiple platforms could produce unpublished or broken images.

This enforcement was introduced to prevent regressions like the `openstackbaremetal` incident where a misconfigured feature set caused images to be silently skipped during publication. See [ADR 0020](/reference/adr/0020-enforce-single-platform-by-default-in-builder) for the full rationale.

If you need to create a build with zero or multiple platforms (a **frankenstein image**), you must explicitly opt in via the `--allow-frankenstein` builder flag. Frankenstein images are not considered a supported configuration.

:::info
When a frankenstein build is created, the `GARDENLINUX_PLATFORM` value in `/etc/os-release` is set to the literal string `frankenstein` instead of a single platform identifier.
:::

## Feature Resolution in `/etc/os-release`

The builder exposes the resolved feature set via `GARDENLINUX_*` keys written into `/etc/os-release` by the `base` feature. For the complete key table, see [Feature resolution in `/etc/os-release`](/reference/features/#feature-resolution-in-etcos-release).

## Further Reading

For information about how features combine to define flavors, see [Flavors](/explanation/flavors).

For the complete file format specification of features (`info.yaml`, `pkg.*`, `file.*`, `exec.*`, etc.), see the [builder features reference](/reference/features/).

For a catalog of all individual features, see the [Features Reference](/reference/features/).

## Related Topics

<RelatedTopics />
19 changes: 14 additions & 5 deletions docs/how-to/building-images.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,29 @@ pass the container engine. :::

## Build an Image

Run the build script with the target flavor name:
Run the build script with the flavor (`{cname}-{arch}`):

```bash
./build ${platform}-${feature1}-${feature2}-${arch}
```

Where:

- `${platform}` — the target platform (e.g. `kvm`, `metal`, `aws`); must be the
- `${platform}` — the target platform (e.g. [`kvm`](/reference/features/kvm), [`metal`](/reference/features/metal), [`aws`](/reference/features/aws)); must be the
first component.
- `${featureX}` — one or more features from the `features/` directory, separated
by `-` (or `_` for features whose names begin with `_`).
- `${arch}` — optional target architecture (`amd64` or `arm64`); must be the
last component.
last component. Defaults to the host architecture when omitted.

:::info Partial arguments are accepted
You can pass any subset of the full [naming hierarchy](/reference/flavors#canonical-names):
a bare cname (e.g. `aws-gardener_prod`), a flavor (cname + arch, e.g.
`aws-gardener_prod-amd64`), or a versioned flavor (flavor + version, e.g.
`aws-gardener_prod-amd64-1877.3`). Any missing component is resolved
automatically: architecture defaults to the host architecture, and version is
read from the `VERSION` file via `./get_version`.
:::

Examples:

Expand All @@ -71,7 +80,7 @@ Examples:
For a full list of build script options, see the
[Builder Command-Line Reference](/reference/builder).

For help choosing a flavor name, see
For help choosing a flavor, see
[Choosing Flavors](/how-to/choosing-flavors).

## Run Parallel Builds
Expand Down Expand Up @@ -107,7 +116,7 @@ apt install qemu-user-static

## Build Secureboot / Trustedboot / TPM2 Images

Before building any image with the `_tpm2`, `_trustedboot`, or `_secureboot`
Before building any image with the [`_tpm2`](/reference/features/_tpm2), [`_trustedboot`](/reference/features/_trustedboot), or [`_secureboot`](/reference/features/_secureboot)
feature, generate the signing certificates:

```bash
Expand Down
6 changes: 3 additions & 3 deletions docs/how-to/custom-feature.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ Garden Linux requires exactly one platform feature per build. Running `./build b

Garden Linux features follow the same structure as vanilla builder features, but use three types:

- **`platform`** — target platform such as `kvm`, `aws`, `azure`, `metal`, `gcp`. Rarely created by users.
- **`element`** — significant feature that may include/exclude other features, e.g., `server`, `cloud`, `cis`, `fedramp`.
- **`flag`** — minor toggles, conventionally prefixed with `_`, e.g., `_prod`, `_slim`, `_selinux`.
- **`platform`** — target platform such as [`kvm`](/reference/features/kvm), [`aws`](/reference/features/aws), [`azure`](/reference/features/azure), [`metal`](/reference/features/metal), [`gcp`](/reference/features/gcp). Rarely created by users.
- **`element`** — significant feature that may include/exclude other features, e.g., [`server`](/reference/features/server), [`cloud`](/reference/features/cloud), [`cis`](/reference/features/cis), [`fedramp`](/reference/features/fedramp).
- **`flag`** — minor toggles, conventionally prefixed with `_`, e.g., [`_prod`](/reference/features/_prod), [`_slim`](/reference/features/_slim), [`_selinux`](/reference/features/_selinux).

### Customizing the image

Expand Down
Loading
Loading