From c107af671d5e71975946f29327415ab0eb1946fc Mon Sep 17 00:00:00 2001 From: Hardik Dodiya Date: Mon, 16 Feb 2026 13:53:12 +0100 Subject: [PATCH] Improve documentation --- README.md | 3 + REUSE.toml | 1 + docs/README.md | 4 + docs/manual-oci-image-build.md | 177 +++++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 docs/README.md create mode 100644 docs/manual-oci-image-build.md diff --git a/README.md b/README.md index c1f110e..6177962 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ The GitHub Actions workflow triggers on pushes to the `main` branch and performs ## Configuration The configuration for OS artifacts is managed through the `os_image_artifacts.yml` file located in the `.github` directory. Currently only `amd64` and `arm64` platforms are supported. +## Documentation +- Manual build (Garden Linux -> `ironcore-image`): `docs/manual-oci-image-build.md` + ### Example Configuration ```yaml amd64: diff --git a/REUSE.toml b/REUSE.toml index 4ab9057..e526851 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -9,6 +9,7 @@ path = [ ".gitignore", "CODEOWNERS", "REUSE.toml", + "docs/**", ] precedence = "aggregate" SPDX-FileCopyrightText = "2024 SAP SE or an SAP affiliate company and IronCore contributors" diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..499745c --- /dev/null +++ b/docs/README.md @@ -0,0 +1,4 @@ +# Documentation + +- `manual-oci-image-build.md`: Manual workflow to build Garden Linux artifacts and package/push them as OCI images using `ironcore-image` (metal-api focused). + diff --git a/docs/manual-oci-image-build.md b/docs/manual-oci-image-build.md new file mode 100644 index 0000000..d5da13a --- /dev/null +++ b/docs/manual-oci-image-build.md @@ -0,0 +1,177 @@ +# Manual OCI Image Build (Garden Linux -> ironcore-image) for metal-api machinery + +This document describes a **manual** workflow to build Garden Linux artifacts and package them as an OCI image using `ironcore-image`. + +The resulting OCI image format is what the metal-api machinery expects: kernel (`vmlinuz`), initramfs (`initrd`), optional `root.squashfs`, and optionally a UKI (`.uki`). + +## Prerequisites + +- A Linux build host (the commands below assume standard Linux tooling). +- Tools: `git`, `tar`, `cpio`, `xz`, and `ukify` (from `systemd` / `systemd-ukify`, depending on your distro). +- `ironcore-image` binary built from the `ironcore-image` repository (`make build` produces `./bin/ironcore-image`). + +## 1) Build Garden Linux artifacts + +Clone Garden Linux (this repo contains the `./build` scripts that produce the PXE boot artifacts): + +```bash +git clone https://github.com/gardenlinux/gardenlinux +cd gardenlinux +``` + +Build one of the metal targets (choose the one that fits your use case). Each command runs a build pipeline and writes outputs under `.build/`: + +```bash +# "vanilla" metal PXE artifact +./build metal_pxe + +# CAPI-focused metal artifact +./build metal-capi + +# Gardener-focused metal PXE artifact +./build metal-gardener_pxe +``` + +What to expect after `./build ...`: + +- A `.build/` directory gets created. +- Inside `.build/` you will find one or more target-specific archives (tarballs). Those archives contain the actual boot artifacts used by the metal-api machinery, typically including: + - `vmlinuz` (Linux kernel) + - `initrd` (initramfs/initramd) + - `root.squashfs` (root filesystem image) + +### Extract the PXE artifact + +In `.build/`, pick the tarball that matches your architecture and Garden Linux version and extract it: + +```bash +cd .build +tar -xvzf metal_pxe-amd64--local.pxe.tar.gz +``` + +Notes: + +- Use `tar -xvzf` for `.tar.gz` archives (gzip). +- If your archive ends with `.tar.xz`, use `tar -xvJf .tar.xz` instead. + +After extraction, locate `vmlinuz`, `initrd`, and `root.squashfs` in the extracted directory tree (the exact paths depend on the target and Garden Linux version). + +## 2) Optional: Append `root.squashfs` to `initrd` + +In some setups it is useful to embed the squashfs into the initramfs by appending an additional xz-compressed cpio archive to the existing `initrd`. This can simplify artifact handling (you ship one initrd blob that already contains the squashfs). + +Run the following in the directory where `initrd` and `root.squashfs` are located: + +```bash +cp initrd initrd.orig +echo root.squashfs | cpio -H newc -o | xz --check=crc32 >> initrd +``` + +What this does: + +- `echo root.squashfs | cpio -H newc -o` creates a tiny cpio archive (newc format) that contains the file `root.squashfs` (as a payload file). +- `xz --check=crc32` compresses that cpio archive. +- `>> initrd` appends the compressed cpio stream to the end of the existing `initrd` (initramfs). + +If you do not want this behavior, keep using the original `initrd` (or restore from `initrd.orig`) and ship `root.squashfs` separately. + +## 3) Prepare the kernel command line (`cmdline`) + +Create a file named `cmdline` next to your boot artifacts: + +```text +initrd=initrd gl.ovl=/:tmpfs gl.live=1 ip=any console=ttyS0,115200 console=tty0 earlyprintk=ttyS0,115200 consoleblank=0 ignition.firstboot=1 ignition.config.url=http:///ignition ignition.config.url.append.uuid=true ignition.platform.id=metal rd.break SYSTEMD_SULOGIN_FORCE=1 +``` + +Notes: + +- This file becomes the kernel command line used by both PXE flows and the UKI build step below. +- Replace `http:///ignition` with your actual Ignition endpoint. +- `rd.break` and `SYSTEMD_SULOGIN_FORCE=1` are typically used for debugging / emergency access. For production images, remove them unless you explicitly need them. + +## 4) Build a UKI (Unified Kernel Image) with `ukify` + +From the directory containing `vmlinuz`, `initrd`, and `cmdline`: + +```bash +ukify build \ + --linux vmlinuz \ + --initrd initrd \ + --stub "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" \ + --cmdline "@cmdline" \ + --output today.uki +``` + +What this does: + +- Produces a single `.uki` artifact that bundles the kernel, initrd, and command line for UEFI-based boot flows. +- The stub path is distro-dependent; adjust `--stub` if your system stores the EFI stub elsewhere. + +## 5) Build and push the OCI image with `ironcore-image` + +### Build `ironcore-image` + +In the `ironcore-image` repository: + +```bash +make build +``` + +This should produce `./bin/ironcore-image`. + +### Prepare a standard image reference (placeholders) + +Use a versioned tag that encodes the upstream Garden Linux version and the metal flavor/variant. A simple convention that works well in practice is: + +```text +///gardenlinux:-metal--manual +``` + +Examples (replace placeholders with real values): + +- `ghcr.io/ironcore-dev/os-images/gardenlinux:1877.12-metal-manual` +- `ghcr.io/ironcore-dev/os-images/gardenlinux/capi:1877.12-metal-manual` +- `ghcr.io/ironcore-dev/os-images/gardenlinux/gardener:1877.12-metal-manual` + +Suggested `` values to keep naming consistent with the Garden Linux build target you used: + +- `vanilla` for `./build metal_pxe` +- `capi` for `./build metal-capi` +- `gardener` for `./build metal-gardener_pxe` + +### Build the image + +Copy the artifacts into the `ironcore-image` repo (or adjust paths accordingly). The example below assumes: + +- `bin/vmlinuz` +- `bin/initrd` +- `bin/root.squashfs` +- `bin/today.uki` + +Build the OCI image: + +```bash +./bin/ironcore-image build \ + --tag ///gardenlinux:-metal--manual \ + --config arch=amd64,squashfs=bin/root.squashfs,initramfs=bin/initrd,kernel=bin/vmlinuz,uki=bin/today.uki +``` + +What the `--config` values mean: + +- `arch=amd64`: target architecture for the image artifacts. +- `kernel=...`: points to the `vmlinuz` you extracted/built. +- `initramfs=...`: points to the `initrd` you extracted/built (optionally with appended squashfs). +- `squashfs=...`: points to the `root.squashfs` root filesystem image. If you fully embedded `root.squashfs` into `initrd` and do not want to ship it as a separate artifact, omit `squashfs=...`. +- `uki=...`: points to the UKI built via `ukify` (optional, but included here to support UKI boot flows). + +### Push the image + +Push the built image reference to GHCR: + +```bash +./bin/ironcore-image push \ + ///gardenlinux:-metal--manual \ + --push-sub-manifests +``` + +`--push-sub-manifests` is commonly used when publishing multi-platform images/manifests; keep it enabled if your workflow expects the sub-manifests to be pushed as well.