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
2 changes: 1 addition & 1 deletion docs/skills/avoid-over-engineering.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ existing repo convention already does the job.
| "A forwarding recipe is harmless." | It duplicates the command surface and rots when the real recipe changes. |
| "I don't need to re-validate after a tiny cut." | `just validate` is the merge contract. Run it every time. |
| "This build dep isn't named in the commands, so it's unused." | `manual`/`script` element commands run in a sandbox that still needs `/bin/sh` and coreutils. Cutting the dep that supplies them breaks the build even if `make` itself is never called. |
| "The tool I depend on doesn't need grep/sed/gzip/etc." | Build tools like `dracut` and archive pipelines invoke `grep`, `sed`, `gzip`, `kmod` (`depmod`), and `ldconfig` internally. If the sandbox doesn't have them, the tool fails with opaque "command not found" (exitcode 127) or missing-library errors. |
| "The tool I depend on doesn't need grep/sed/gzip/etc." | Archive pipelines and build tools invoke `grep`, `sed`, `gzip`, `kmod` (`depmod`), and `ldconfig` internally. If the sandbox doesn't have them, the tool fails with opaque "command not found" (exitcode 127) or missing-library errors. |

## Red Flags

Expand Down
2 changes: 1 addition & 1 deletion docs/skills/ddi-installer-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ The release process is driven by `.github/workflows/build.yml`:
| Rationalization | Reality |
|---|---|
| "A bash script is simpler." | A bash script cannot run the systemd-native interactive installer TUI. Use `systemd-sysinstall`. |
| "Kernel image is at `/boot/vmlinuz`." | FSDK installs kernels into `/usr/lib/modules/<kver>/vmlinuz`. Toolchains (dracut, ukify, PXE export) must point to `/usr/lib/modules/<kver>/vmlinuz`. |
| "Kernel image is at `/boot/vmlinuz`." | FSDK installs kernels into `/usr/lib/modules/<kver>/vmlinuz`. Toolchains (ukify, PXE export) must point to `/usr/lib/modules/<kver>/vmlinuz`. |
| "Initrd archive tools (gzip, cpio) are in base-stack." | In FSDK 26.08, gzip and cpio are standalone components; elements packing or unpacking initrds must explicitly declare `components/gzip.bst` and `components/cpio.bst` in `build-depends`. |
| "Use knuckle instead." | knuckle is deprecated in favor of native `systemd-sysinstall` (systemd 261+). |
| "Hardcode `root=/dev/vda2` for QEMU." | Bare metal has different device names. Always use PARTUUID. |
Expand Down
3 changes: 1 addition & 2 deletions docs/skills/ddi-installer.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ offline installation.
| Rationalization | Reality |
|---|---|
| "A bash script is simpler." | A bash script cannot run the systemd-native interactive installer TUI. Use `systemd-sysinstall`. |
| "Kernel image is at `/boot/vmlinuz`." | FSDK installs kernels into `/usr/lib/modules/<kver>/vmlinuz`. Toolchains (dracut, ukify, PXE export) must point to `/usr/lib/modules/<kver>/vmlinuz`. |
| "dracut finds glibc libraries automatically." | In FSDK 26.08, glibc libraries live under `/usr/lib/x86_64-linux-gnu`. `dracut-install` requires `/etc/ld.so.conf` to include `/usr/lib/x86_64-linux-gnu` and `ldconfig` to generate `/etc/ld.so.cache` before dracut runs. |
| "Kernel image is at `/boot/vmlinuz`." | FSDK installs kernels into `/usr/lib/modules/<kver>/vmlinuz`. Toolchains (ukify, PXE export) must point to `/usr/lib/modules/<kver>/vmlinuz`. |
| "Initrd archive tools (gzip, cpio) are in base-stack." | In FSDK 26.08, gzip and cpio are standalone components; elements packing or unpacking initrds must explicitly declare `components/gzip.bst` and `components/cpio.bst` in `build-depends`. |
| "Use knuckle instead." | knuckle is deprecated in favor of native `systemd-sysinstall` (systemd 261+). |
| "Hardcode `root=/dev/vda2` for QEMU." | Bare metal has different device names. Always use PARTUUID. |
Expand Down
48 changes: 1 addition & 47 deletions elements/oci/bluefin-server-installer.bst
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,10 @@ description: |
build-depends:
# Toolchain for assembly
- base/base-stack.bst
- freedesktop-sdk.bst:components/dracut.bst
- freedesktop-sdk.bst:components/kmod.bst
- freedesktop-sdk.bst:components/cpio.bst # newc cpio archive creation
- freedesktop-sdk.bst:components/findutils.bst # find for cpio pipe
- freedesktop-sdk.bst:components/gzip.bst # gzip for initrd cpio
# grep/sed are required by dracut/dracut-install even though our commands don't name them.
- freedesktop-sdk.bst:components/grep.bst
- freedesktop-sdk.bst:components/sed.bst
- freedesktop-sdk.bst:components/zstd.bst # compress initrd + final disk
# ukify assembles the UKI (kernel + initrd + cmdline -> .efi)
- freedesktop-sdk.bst:components/systemd-ukify.bst
Expand Down Expand Up @@ -87,7 +83,7 @@ config:
mkdir -p /layer/boot
mkdir -p /target-root/boot/EFI/Linux /tmp /var/tmp

# ── Step 1b: Generate target OS UKI (dracut + ukify) ────────────────
# ── Step 1b: Generate target OS UKI (ukify) ─────────────────────────
- |
set -eux
TARGET_KVER="$(basename "$(find /target-root/usr/lib/modules -mindepth 1 -maxdepth 1 -type d | head -n1)")"
Expand All @@ -105,38 +101,8 @@ config:

depmod -b /target-root "${TARGET_KVER}" || true

# Configure dynamic linker search paths so ldconfig indexes FSDK libraries
# (e.g. libc.so.6, libgcc_s.so.1, libkmod.so) for dracut-install
printf '/usr/lib/x86_64-linux-gnu\n/usr/lib/x86_64-linux-gnu/systemd\n' > /etc/ld.so.conf
if [ -d /etc/ld.so.conf.d ]; then
echo 'include /etc/ld.so.conf.d/*.conf' >> /etc/ld.so.conf
fi
ldconfig

# Build target-root linker cache and stage it at /etc/ld.so.cache for dracut
mkdir -p /target-root/tmp /target-root/etc
printf '/usr/lib/x86_64-linux-gnu\n/usr/lib/x86_64-linux-gnu/systemd\n' > /target-root/tmp/ld.so.conf
if [ -d /target-root/etc/ld.so.conf.d ]; then
echo 'include /etc/ld.so.conf.d/*.conf' >> /target-root/tmp/ld.so.conf
fi
ldconfig -r /target-root -f /tmp/ld.so.conf
rm -f /target-root/tmp/ld.so.conf
cp /target-root/etc/ld.so.cache /etc/ld.so.cache

# Run dracut in generic (non-hostonly) mode and explicitly add XFS, VirtIO, and NVMe storage drivers.
dracut -v --reproducible --no-machineid --no-hostonly \
--add-drivers "virtio virtio_blk virtio_pci virtio_scsi nvme nvme_core xfs erofs overlay zfs spl" \
--filesystems "xfs vfat zfs" \
--install /etc/ld.so.cache \
--kmoddir "/target-root/usr/lib/modules/${TARGET_KVER}" \
--kernel-image "${TARGET_KERNEL}" \
--kver "${TARGET_KVER}" \
--kernel-cmdline "rw console=ttyS0,115200 console=tty0 quiet loglevel=3 audit=0" \
/tmp/bluefin-server-target.initramfs

ukify build \
--linux="${TARGET_KERNEL}" \
--initrd=/tmp/bluefin-server-target.initramfs \
--cmdline="rw console=ttyS0,115200 console=tty0 quiet loglevel=3 audit=0" \
--output=/target-root/boot/EFI/Linux/bluefin-server.efi
cp /target-root/boot/EFI/Linux/bluefin-server.efi /layer/usr/lib/bluefin-server/bluefin-server.efi
Expand Down Expand Up @@ -184,16 +150,6 @@ config:
#!/bin/bash
set -euo pipefail

# Ensure storage controller modules and filesystems are loaded before probing devices
modprobe -q nvme || true
modprobe -q nvme_core || true
modprobe -q usb-storage || true
modprobe -q uas || true
modprobe -q ahci || true
modprobe -q sd_mod || true
modprobe -q xfs || true
udevadm trigger --subsystem-match=block || true
udevadm settle --timeout=15 || true
# Auto-detect target disk for unattended install (any raw disk of type "disk" that is not the installer, is not read-only, and has size > 0)
TARGET_DISK=""
INSTALLER_PART="$(readlink -f /dev/disk/by-partlabel/bluefin-installer-data 2>/dev/null || true)"
Expand Down Expand Up @@ -293,8 +249,6 @@ config:
mkdir -p /layer/etc/systemd/system/systemd-sysinstall.service.d
cat > /layer/etc/systemd/system/systemd-sysinstall.service.d/override.conf << 'EOF'
[Unit]
After=systemd-udev-settle.service
Wants=systemd-udev-settle.service
SuccessAction=poweroff
FailureAction=poweroff

Expand Down
38 changes: 25 additions & 13 deletions tests/unit/test_installer_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,37 @@ def test_ddi_generates_module_indexes_for_runtime_filesystem_drivers() -> None:
assert "> /layer/etc/hosts" in ddi_element


def test_target_initramfs_preloads_sysext_filesystem_drivers() -> None:
def test_target_uki_build_does_not_invoke_dracut() -> None:
installer_element = INSTALLER_ELEMENT.read_text(encoding="utf-8")

assert (
'--add-drivers "virtio virtio_blk virtio_pci virtio_scsi nvme nvme_core xfs erofs overlay zfs spl"'
in installer_element
data = yaml.safe_load(installer_element)
dep_names = [
dep if isinstance(dep, str) else dep.get("filename", "")
for dep in data.get("build-depends", [])
]
commands = data.get("config", {}).get("commands", [])
commands_text = "\n".join(
cmd if isinstance(cmd, str) else "\n".join(cmd) for cmd in commands
)

assert "freedesktop-sdk.bst:components/dracut.bst" not in dep_names
assert "freedesktop-sdk.bst:components/grep.bst" not in dep_names
assert "freedesktop-sdk.bst:components/sed.bst" not in dep_names
assert "dracut" not in commands_text
assert "--add-drivers" not in commands_text
assert "ld.so.cache" not in commands_text
target_uki_cmd = commands[1] if len(commands) > 1 else ""
assert '--linux="${TARGET_KERNEL}"' in target_uki_cmd
assert "--initrd" not in target_uki_cmd


def test_installer_loads_storage_drivers_and_settles_udev() -> None:
def test_installer_omits_module_force_load_and_udev_settle_workarounds() -> None:
installer_element = INSTALLER_ELEMENT.read_text(encoding="utf-8")

assert "modprobe -q nvme || true" in installer_element
assert "modprobe -q nvme_core || true" in installer_element
assert "modprobe -q usb-storage || true" in installer_element
assert "modprobe -q uas || true" in installer_element
assert "udevadm settle --timeout=15 || true" in installer_element
assert "After=systemd-udev-settle.service" in installer_element
assert "Wants=systemd-udev-settle.service" in installer_element
assert "modprobe -q nvme" not in installer_element
assert "modprobe -q usb-storage" not in installer_element
assert "udevadm settle --timeout=15" not in installer_element
assert "After=systemd-udev-settle.service" not in installer_element
assert "Wants=systemd-udev-settle.service" not in installer_element

def test_interactive_installer_uses_local_virtual_console() -> None:
installer_element = INSTALLER_ELEMENT.read_text(encoding="utf-8")
Expand Down
Loading