From 74cc76a5c8f76f99d0d73f46309fbe83bfc21dae Mon Sep 17 00:00:00 2001 From: Eike Waldt Date: Wed, 1 Jul 2026 15:18:54 +0200 Subject: [PATCH 1/3] docs: rework flavor, cname and related terms after ADR0034 and ADR0035 Signed-off-by: Eike Waldt On-behalf-of: SAP --- docs/explanation/builder.md | 22 +++---- docs/explanation/features.md | 105 +++++++++++++++++++++++++++++++++ docs/how-to/building-images.md | 4 +- docs/reference/builder.md | 2 +- docs/reference/features.md | 17 ++++++ 5 files changed, 137 insertions(+), 13 deletions(-) create mode 100644 docs/explanation/features.md diff --git a/docs/explanation/builder.md b/docs/explanation/builder.md index df42449..0d968c5 100644 --- a/docs/explanation/builder.md +++ b/docs/explanation/builder.md @@ -40,28 +40,30 @@ 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 takes a **flavor** (`{cname}-{arch}`) as its argument. The version is not supplied on the command line — it is derived automatically by calling `./get_version`, which reads the `VERSION` file in the repository root: + +- 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. + +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: ``` ---_- +./build {cname}-{arch} +# internally: make … DEFAULT_VERSION= {cname}-{arch}- ``` -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. +For example, `./build aws-gardener_prod-amd64` on `main` produces artifacts prefixed `aws-gardener_prod-amd64-today-`. -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). +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 diff --git a/docs/explanation/features.md b/docs/explanation/features.md new file mode 100644 index 0000000..248d49e --- /dev/null +++ b/docs/explanation/features.md @@ -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` element feature does not just install `containerd` — it also configures systemd services and includes other features such as `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`, `azure`, `gcp`, `kvm`, `baremetal`, `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`, `server`, `cloud`, `cis`, `firewall`, `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`, `_fips`, `_trustedboot`, `_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. Start with the explicitly requested features +2. Recursively include all features listed in each feature's `features.include` list +3. Remove any features listed in `features.exclude` lists (but only if they were transitively included) +4. Validate that the result forms a valid DAG (no cycles, no conflicts) + +For example, if you request `aws` and `gardener`: + +- The `aws` platform feature includes dependencies for cloud-init, kernel modules, etc. +- The `gardener` element feature includes the `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 + + diff --git a/docs/how-to/building-images.md b/docs/how-to/building-images.md index 2bebd7f..5c32e98 100644 --- a/docs/how-to/building-images.md +++ b/docs/how-to/building-images.md @@ -46,7 +46,7 @@ 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} @@ -71,7 +71,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 diff --git a/docs/reference/builder.md b/docs/reference/builder.md index 98be12b..7fe05cc 100644 --- a/docs/reference/builder.md +++ b/docs/reference/builder.md @@ -48,7 +48,7 @@ builder container. This means standard `make` flags such as `-j` are valid here. | `--privileged` | *(none)* | Off | Runs the builder container with `--privileged` and passes `--second-stage` to the container entrypoint. Required for two-stage builds that need elevated privileges inside the container. | | `--kms` | *(none)* | Off | Forwards AWS credential environment variables (`AWS_DEFAULT_REGION`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`) into the build. Required when Secure Boot key operations during the build use AWS Key Management Service. | | `--allow-frankenstein` | *(none)* | Off | Disables the [single-platform enforcement](/reference/adr/0020-enforce-single-platform-by-default-in-builder) by passing `ALLOW_FRANKENSTEIN=1` to the build. Allows composing a flavor from multiple platform features. See [ADR 0020](/reference/adr/0020-enforce-single-platform-by-default-in-builder) for the rationale. | -| `--resolve-cname` | *(none)* | Off | Resolves the given flavor argument to its full canonical name (CNAME) including the 8-character commit hash, prints it to stdout, and exits. Requires exactly one flavor argument. Useful for generating reproducible artifact names in scripts. | +| `--resolve-cname` | *(none)* | Off | Resolves the given flavor argument to the artifact base name (`{cname}-{arch}-{version}-{short_commit}`), prints it to stdout, and exits. Requires exactly one flavor argument. Useful for generating reproducible artifact names in scripts. | | `--print-container-image` | *(none)* | Off | Prints the pinned builder container image reference to stdout and exits immediately. Useful for scripts that need to pull or inspect the builder image independently of running a build. | | `--apparmor-profile` | `` | Auto-detected | Applies the named AppArmor profile to the builder container, replacing the default `apparmor=unconfined`. If not set and Docker is used on a host with `kernel.apparmor_restrict_unprivileged_userns = 1`, the script detects the restriction and offers to create a `builder` profile at `/etc/apparmor.d/builder` automatically. | diff --git a/docs/reference/features.md b/docs/reference/features.md index 3d49d16..ef67e0d 100644 --- a/docs/reference/features.md +++ b/docs/reference/features.md @@ -17,6 +17,23 @@ github_target_path: docs/reference/features/index.md # Features +For feature type definitions and composition semantics, see [Features](/explanation/features). + +## Feature resolution in `/etc/os-release` + +After resolving the feature graph, the builder writes the following keys into `/etc/os-release` via `features/base/exec.config` (defined in [ADR 0034](/reference/adr/0034-feature-terminology)): + +| Key | Content | +|---|---| +| `GARDENLINUX_CNAME` | The cname — feature encoding only (e.g. `aws-gardener_prod`) | +| `GARDENLINUX_PLATFORM` | The single authoritative platform identifier (e.g. `aws`); set to `frankenstein` when multiple platform features are present | +| `GARDENLINUX_FEATURES` | Comma-separated list of all features in the resolved feature set | +| `GARDENLINUX_FEATURES_PLATFORMS` | Comma-separated list of all features of type `platform` | +| `GARDENLINUX_FEATURES_ELEMENTS` | Comma-separated list of all features of type `element` | +| `GARDENLINUX_FEATURES_FLAGS` | Comma-separated list of all features of type `flag` | + +`GARDENLINUX_PLATFORM` is always a single token and is the value to use for all platform-routing decisions (publishing, testing, image naming). `GARDENLINUX_FEATURES_PLATFORMS` is informational only and must not be used for routing. + Each feature must contain an `info.yaml` file that adheres to the following structure: ## `info.yaml` file structure: From 310efc1c367d0e2eaa0cf83066caab8b1fe78155 Mon Sep 17 00:00:00 2001 From: Eike Waldt Date: Wed, 1 Jul 2026 16:27:39 +0200 Subject: [PATCH 2/3] fix: docs: add links to feature references Signed-off-by: Eike Waldt On-behalf-of: SAP --- docs/explanation/features.md | 16 ++++++++-------- docs/how-to/building-images.md | 4 ++-- docs/how-to/custom-feature.md | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/explanation/features.md b/docs/explanation/features.md index 248d49e..a6e4223 100644 --- a/docs/explanation/features.md +++ b/docs/explanation/features.md @@ -38,7 +38,7 @@ A feature is not just a package list, but a complete configuration unit that may - **Scripts** — Setup and lifecycle scripts - **Dependencies** — A list of other features to include or exclude -For example, the `gardener` element feature does not just install `containerd` — it also configures systemd services and includes other features such as `log` to set up logging. +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 @@ -48,9 +48,9 @@ The three feature types are defined in [ADR 0034](/reference/adr/0034-feature-te | 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`, `azure`, `gcp`, `kvm`, `baremetal`, `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`, `server`, `cloud`, `cis`, `firewall`, `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`, `_fips`, `_trustedboot`, `_usi` | +| **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/). @@ -65,10 +65,10 @@ When you specify features for a build, the builder resolves the complete feature 3. Remove any features listed in `features.exclude` lists (but only if they were transitively included) 4. Validate that the result forms a valid DAG (no cycles, no conflicts) -For example, if you request `aws` and `gardener`: +For example, if you request [`aws`](/reference/features/aws) and [`gardener`](/reference/features/gardener): -- The `aws` platform feature includes dependencies for cloud-init, kernel modules, etc. -- The `gardener` element feature includes the `log` feature for logging configuration +- 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 @@ -90,7 +90,7 @@ When a frankenstein build is created, the `GARDENLINUX_PLATFORM` value in `/etc/ ## 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). +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 diff --git a/docs/how-to/building-images.md b/docs/how-to/building-images.md index 5c32e98..37bddf7 100644 --- a/docs/how-to/building-images.md +++ b/docs/how-to/building-images.md @@ -54,7 +54,7 @@ Run the build script with the flavor (`{cname}-{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 `_`). @@ -107,7 +107,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 diff --git a/docs/how-to/custom-feature.md b/docs/how-to/custom-feature.md index 99618af..e1396b5 100644 --- a/docs/how-to/custom-feature.md +++ b/docs/how-to/custom-feature.md @@ -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 From c9a84891f05bd85872e58e5d77676774940eccb9 Mon Sep 17 00:00:00 2001 From: Eike Waldt Date: Wed, 8 Jul 2026 16:07:29 +0200 Subject: [PATCH 3/3] fix: incorporate PR feedback Signed-off-by: Eike Waldt On-behalf-of: SAP --- docs/explanation/builder.md | 11 ++- docs/explanation/features.md | 8 +-- docs/how-to/building-images.md | 11 ++- docs/reference/builder.md | 118 +++++++++++++++++---------------- docs/reference/features.md | 20 +++--- 5 files changed, 92 insertions(+), 76 deletions(-) diff --git a/docs/explanation/builder.md b/docs/explanation/builder.md index 0d968c5..89f009a 100644 --- a/docs/explanation/builder.md +++ b/docs/explanation/builder.md @@ -49,17 +49,16 @@ The build system is designed around three principles: ## Versioned Flavors as Build Inputs -The `./build` script takes a **flavor** (`{cname}-{arch}`) as its argument. The version is not supplied on the command line — it is derived automatically by calling `./get_version`, which reads the `VERSION` file in the repository root: +The `./build` script accepts a **cname** (`{cname}`), a **flavor** (`{cname}-{arch}`), or a **versioned flavor** (`{cname}-{arch}-{version}`) as its argument. + +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: - 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. -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: +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. -``` -./build {cname}-{arch} -# internally: make … DEFAULT_VERSION= {cname}-{arch}- -``` +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-`. diff --git a/docs/explanation/features.md b/docs/explanation/features.md index a6e4223..e4baf17 100644 --- a/docs/explanation/features.md +++ b/docs/explanation/features.md @@ -60,10 +60,10 @@ A complete list of features can be seen in the [Features Reference](/reference/f When you specify features for a build, the builder resolves the complete feature set by following the DAG: -1. Start with the explicitly requested features -2. Recursively include all features listed in each feature's `features.include` list -3. Remove any features listed in `features.exclude` lists (but only if they were transitively included) -4. Validate that the result forms a valid DAG (no cycles, no conflicts) +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): diff --git a/docs/how-to/building-images.md b/docs/how-to/building-images.md index 37bddf7..5710d07 100644 --- a/docs/how-to/building-images.md +++ b/docs/how-to/building-images.md @@ -59,7 +59,16 @@ Where: - `${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: diff --git a/docs/reference/builder.md b/docs/reference/builder.md index 7fe05cc..0a5d2dc 100644 --- a/docs/reference/builder.md +++ b/docs/reference/builder.md @@ -39,26 +39,30 @@ builder container. This means standard `make` flags such as `-j` are valid here. ### Options -| Option | Argument | Default | Description | -|---|---|---|---| -| `--container-engine` | `podman` \| `sudo podman` \| `docker` | `podman` | Container engine used to launch the builder container. See [Supported Container Engines](#supported-container-engines). | -| `--container-image` | `` | Pinned `ghcr.io/gardenlinux/builder:` | Overrides the builder container image. Pass `localhost/builder` to build and use a local builder image from the repository. | -| `--container-run-opts` | `` | Security and memory defaults | Replaces the entire set of container run options with a custom shell-quoted string. This overrides the default memory limit, seccomp, AppArmor, and label settings. Use with care. | -| `--target` | `` | `.build` | Directory where build artifacts are written. Created automatically if it does not exist. | -| `--privileged` | *(none)* | Off | Runs the builder container with `--privileged` and passes `--second-stage` to the container entrypoint. Required for two-stage builds that need elevated privileges inside the container. | -| `--kms` | *(none)* | Off | Forwards AWS credential environment variables (`AWS_DEFAULT_REGION`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`) into the build. Required when Secure Boot key operations during the build use AWS Key Management Service. | -| `--allow-frankenstein` | *(none)* | Off | Disables the [single-platform enforcement](/reference/adr/0020-enforce-single-platform-by-default-in-builder) by passing `ALLOW_FRANKENSTEIN=1` to the build. Allows composing a flavor from multiple platform features. See [ADR 0020](/reference/adr/0020-enforce-single-platform-by-default-in-builder) for the rationale. | -| `--resolve-cname` | *(none)* | Off | Resolves the given flavor argument to the artifact base name (`{cname}-{arch}-{version}-{short_commit}`), prints it to stdout, and exits. Requires exactly one flavor argument. Useful for generating reproducible artifact names in scripts. | -| `--print-container-image` | *(none)* | Off | Prints the pinned builder container image reference to stdout and exits immediately. Useful for scripts that need to pull or inspect the builder image independently of running a build. | -| `--apparmor-profile` | `` | Auto-detected | Applies the named AppArmor profile to the builder container, replacing the default `apparmor=unconfined`. If not set and Docker is used on a host with `kernel.apparmor_restrict_unprivileged_userns = 1`, the script detects the restriction and offers to create a `builder` profile at `/etc/apparmor.d/builder` automatically. | +| Option | Argument | Default | Description | +| ------------------------- | ------------------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--container-engine` | `podman` \| `sudo podman` \| `docker` | `podman` | Container engine used to launch the builder container. See [Supported Container Engines](#supported-container-engines). | +| `--container-image` | `` | Pinned `ghcr.io/gardenlinux/builder:` | Overrides the builder container image. Pass `localhost/builder` to build and use a local builder image from the repository. | +| `--container-run-opts` | `` | Security and memory defaults | Replaces the entire set of container run options with a custom shell-quoted string. This overrides the default memory limit, seccomp, AppArmor, and label settings. Use with care. | +| `--target` | `` | `.build` | Directory where build artifacts are written. Created automatically if it does not exist. | +| `--privileged` | _(none)_ | Off | Runs the builder container with `--privileged` and passes `--second-stage` to the container entrypoint. Required for two-stage builds that need elevated privileges inside the container. | +| `--kms` | _(none)_ | Off | Forwards AWS credential environment variables (`AWS_DEFAULT_REGION`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`) into the build. Required when Secure Boot key operations during the build use AWS Key Management Service. | +| `--allow-frankenstein` | _(none)_ | Off | Disables the [single-platform enforcement](/reference/adr/0020-enforce-single-platform-by-default-in-builder) by passing `ALLOW_FRANKENSTEIN=1` to the build. Allows composing a flavor from multiple platform features. See [ADR 0020](/reference/adr/0020-enforce-single-platform-by-default-in-builder) for the rationale. | +| `--resolve-cname` | _(none)_ | Off | Resolves the given flavor argument to the artifact base name (`{cname}-{arch}-{version}-{short_commit}`), prints it to stdout, and exits. Requires exactly one flavor argument. Useful for generating reproducible artifact names in scripts. | +| `--print-container-image` | _(none)_ | Off | Prints the pinned builder container image reference to stdout and exits immediately. Useful for scripts that need to pull or inspect the builder image independently of running a build. | +| `--apparmor-profile` | `` | Auto-detected | Applies the named AppArmor profile to the builder container, replacing the default `apparmor=unconfined`. If not set and Docker is used on a host with `kernel.apparmor_restrict_unprivileged_userns = 1`, the script detects the restriction and offers to create a `builder` profile at `/etc/apparmor.d/builder` automatically. | + +:::warning +The `--resolve-cname` flag will be renamed `--resolve-artifact-basename` in [builder#156](https://github.com/gardenlinux/builder/issues/156). +::: ### `make` flags Any argument not consumed by the option parser above is forwarded to `make` inside the builder container. The most commonly used `make` flag is: -| Flag | Argument | Description | -|---|---|---| +| Flag | Argument | Description | +| ---- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `-j` | `` | Number of flavors to build in parallel. Each parallel thread requires at least 8 GiB of RAM. There are no safeguards against memory exhaustion. | ### Flavor Syntax @@ -67,17 +71,17 @@ container. The most commonly used `make` flag is: [-...]-[] ``` -| Component | Position | Required | Description | -|---|---|---|---| -| `` | First | Yes | Target platform. See [Supported Platforms](#supported-platforms). | -| `` | Middle | No | One or more features from the `features/` directory, separated by `-`. Features whose names begin with `_` are appended directly without a preceding `-`. | -| `` | Last | No | Target CPU architecture. Defaults to the native host architecture. See [Supported Architectures](#supported-architectures). | +| Component | Position | Required | Description | +| ------------ | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `` | First | Yes | Target platform. See [Supported Platforms](#supported-platforms). | +| `` | Middle | No | One or more features from the `features/` directory, separated by `-`. Features whose names begin with `_` are appended directly without a preceding `-`. | +| `` | Last | No | Target CPU architecture. Defaults to the native host architecture. See [Supported Architectures](#supported-architectures). | ### Supported Architectures -| Value | Description | -|---|---| -| `amd64` | 64-bit x86 | +| Value | Description | +| ------- | -------------------- | +| `amd64` | 64-bit x86 | | `arm64` | 64-bit Arm (AArch64) | :::info @@ -88,37 +92,37 @@ user-mode emulation (`qemu-user-static`) on the build host. ### Supported Platforms -| Platform | Category | Description | -|---|---|---| -| [`ali`](/reference/features/ali) | Public cloud | Alibaba Cloud | -| [`aws`](/reference/features/aws) | Public cloud | Amazon Web Services | -| [`azure`](/reference/features/azure) | Public cloud | Microsoft Azure | -| [`bare`](/reference/features/bare) | Container | Bare (distroless) container base image | -| [`container`](/reference/features/container) | Container | Full container base image | -| [`gcp`](/reference/features/gcp) | Public cloud | Google Cloud Platform | -| [`gdch`](/reference/features/gdch) | Public cloud | Google Distributed Cloud Hosted | -| [`kvm`](/reference/features/kvm) | Hypervisor | KVM/QEMU virtualization | -| [`baremetal`](/reference/features/baremetal) | Bare metal | Physical server deployment | -| [`openstack`](/reference/features/openstack) | Private cloud | OpenStack | -| [`vmware`](/reference/features/vmware) | Hypervisor | VMware vSphere/ESXi | -| [`lima`](/reference/features/lima) | Local dev | Lima for macOS and Linux | +| Platform | Category | Description | +| -------------------------------------------- | ------------- | -------------------------------------- | +| [`ali`](/reference/features/ali) | Public cloud | Alibaba Cloud | +| [`aws`](/reference/features/aws) | Public cloud | Amazon Web Services | +| [`azure`](/reference/features/azure) | Public cloud | Microsoft Azure | +| [`bare`](/reference/features/bare) | Container | Bare (distroless) container base image | +| [`container`](/reference/features/container) | Container | Full container base image | +| [`gcp`](/reference/features/gcp) | Public cloud | Google Cloud Platform | +| [`gdch`](/reference/features/gdch) | Public cloud | Google Distributed Cloud Hosted | +| [`kvm`](/reference/features/kvm) | Hypervisor | KVM/QEMU virtualization | +| [`baremetal`](/reference/features/baremetal) | Bare metal | Physical server deployment | +| [`openstack`](/reference/features/openstack) | Private cloud | OpenStack | +| [`vmware`](/reference/features/vmware) | Hypervisor | VMware vSphere/ESXi | +| [`lima`](/reference/features/lima) | Local dev | Lima for macOS and Linux | ### Supported Container Engines -| Value | Description | -|---|---| -| `podman` | Rootless Podman (recommended). Requires a working rootless Podman setup. See the [Podman rootless setup guide](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md). | -| `sudo podman` | Podman with `sudo` for elevated privileges. | -| `docker` | Docker Engine. On systems where `kernel.apparmor_restrict_unprivileged_userns = 1`, an AppArmor profile is required (see `--apparmor-profile` above). | +| Value | Description | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `podman` | Rootless Podman (recommended). Requires a working rootless Podman setup. See the [Podman rootless setup guide](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md). | +| `sudo podman` | Podman with `sudo` for elevated privileges. | +| `docker` | Docker Engine. On systems where `kernel.apparmor_restrict_unprivileged_userns = 1`, an AppArmor profile is required (see `--apparmor-profile` above). | ### `build.config` File If a `build.config` file exists in the working directory, it is sourced by `./build` before the container is launched. It can override build variables that are otherwise set to their defaults. -| Variable | Default | Description | -|---|---|---| -| `tempfs_size` | `2G` | Size of the temporary filesystem used during the build, passed to the builder as `TEMPFS_SIZE`. Increase this if builds fail due to insufficient temporary space. | +| Variable | Default | Description | +| ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tempfs_size` | `2G` | Size of the temporary filesystem used during the build, passed to the builder as `TEMPFS_SIZE`. Increase this if builds fail due to insufficient temporary space. | --- @@ -136,24 +140,24 @@ and [`_secureboot`](/reference/features/_secureboot) images. ### Options -| Option / Argument | Description | -|---|---| -| `--kms` | Store private keys in AWS Key Management Service instead of local files. Requires valid AWS credentials via standard AWS environment variables. | -| `clean` | Remove previously generated certificate files before regenerating. Use this if a previous `./cert/build` run failed or produced incomplete output. | +| Option / Argument | Description | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--kms` | Store private keys in AWS Key Management Service instead of local files. Requires valid AWS credentials via standard AWS environment variables. | +| `clean` | Remove previously generated certificate files before regenerating. Use this if a previous `./cert/build` run failed or produced incomplete output. | ### Output Files After a successful run, the `cert/` directory contains: -| File | Format | Purpose | -|---|---|---| -| `secureboot.pk.esl` | ESL | AWS external enrollment — Platform Key | -| `secureboot.kek.esl` | ESL | AWS external enrollment — Key Exchange Key | -| `secureboot.db.esl` | ESL | AWS external enrollment — Signature Database | -| `secureboot.pk.der` | DER | GCP, Azure — Platform Key | -| `secureboot.kek.der` | DER | GCP, Azure — Key Exchange Key | -| `secureboot.db.der` | DER | GCP, Azure — Signature Database | -| `secureboot.db.crt` | PEM | Image signing during build | +| File | Format | Purpose | +| ------------------------ | ----------- | ---------------------------------------------------------------------- | +| `secureboot.pk.esl` | ESL | AWS external enrollment — Platform Key | +| `secureboot.kek.esl` | ESL | AWS external enrollment — Key Exchange Key | +| `secureboot.db.esl` | ESL | AWS external enrollment — Signature Database | +| `secureboot.pk.der` | DER | GCP, Azure — Platform Key | +| `secureboot.kek.der` | DER | GCP, Azure — Key Exchange Key | +| `secureboot.db.der` | DER | GCP, Azure — Signature Database | +| `secureboot.db.crt` | PEM | Image signing during build | | `secureboot.aws-efivars` | Binary blob | Pre-filled AWS UEFI variable store for external Secure Boot enrollment | For cloud-provider-specific enrollment steps, see [Deploying Secure Boot Images](/how-to/secure-boot). diff --git a/docs/reference/features.md b/docs/reference/features.md index ef67e0d..7797629 100644 --- a/docs/reference/features.md +++ b/docs/reference/features.md @@ -23,14 +23,18 @@ For feature type definitions and composition semantics, see [Features](/explanat After resolving the feature graph, the builder writes the following keys into `/etc/os-release` via `features/base/exec.config` (defined in [ADR 0034](/reference/adr/0034-feature-terminology)): -| Key | Content | -|---|---| -| `GARDENLINUX_CNAME` | The cname — feature encoding only (e.g. `aws-gardener_prod`) | -| `GARDENLINUX_PLATFORM` | The single authoritative platform identifier (e.g. `aws`); set to `frankenstein` when multiple platform features are present | -| `GARDENLINUX_FEATURES` | Comma-separated list of all features in the resolved feature set | -| `GARDENLINUX_FEATURES_PLATFORMS` | Comma-separated list of all features of type `platform` | -| `GARDENLINUX_FEATURES_ELEMENTS` | Comma-separated list of all features of type `element` | -| `GARDENLINUX_FEATURES_FLAGS` | Comma-separated list of all features of type `flag` | +| Key | Content | +| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `GARDENLINUX_CNAME` | The cname — feature encoding only (e.g. `aws-gardener_prod`) | +| `GARDENLINUX_PLATFORM` | The single authoritative platform identifier (e.g. `aws`); set to `frankenstein` when multiple platform features are present | +| `GARDENLINUX_FEATURES` | Comma-separated list of all features in the resolved feature set | +| `GARDENLINUX_FEATURES_PLATFORMS` | Comma-separated list of all features of type `platform` | +| `GARDENLINUX_FEATURES_ELEMENTS` | Comma-separated list of all features of type `element` | +| `GARDENLINUX_FEATURES_FLAGS` | Comma-separated list of all features of type `flag` | + +:::warning +`GARDENLINUX_CNAME` currently contains the versioned flavor (`{cname}-{arch}-{version}`) because `BUILDER_CNAME` in the builder is set to the full make target. Once [builder#156](https://github.com/gardenlinux/builder/issues/156) and [gardenlinux#5004](https://github.com/gardenlinux/gardenlinux/issues/5004) are resolved, `BUILDER_CNAME` will be corrected to carry only the feature encoding (e.g. `aws-gardener_prod`), and `GARDENLINUX_CNAME` will follow. +::: `GARDENLINUX_PLATFORM` is always a single token and is the value to use for all platform-routing decisions (publishing, testing, image naming). `GARDENLINUX_FEATURES_PLATFORMS` is informational only and must not be used for routing.