fix(disk): explicit all-plain partition layout (VM-verified) + bib raw output dir fix - #4
Closed
dx4homelab wants to merge 2 commits into
Closed
fix(disk): explicit all-plain partition layout (VM-verified) + bib raw output dir fix#4dx4homelab wants to merge 2 commits into
dx4homelab wants to merge 2 commits into
Conversation
…t dir
Two changes, the second discovered while validating the first.
LVM layout (iso/disk.toml)
--------------------------
Replaces the single [[customizations.filesystem]] entry — the simple and
advanced (customizations.disk) forms are alternatives, not additive.
z170asrock is swapping its boot NVMe from 931 GB to 4 TB. Measured live
2026-07-29, that host has NO LVM today: one 20 GiB xfs partition carries
/sysroot + /var + /etc, and ~911 GB of the drive is unallocated because the dd
install was never grown. (docs/hardware-inventory.md described a vg4base +
vg4home layout that has not existed since the uCore migration.)
vg4base now holds root (16 GiB) and var (10 GiB). Splitting /var out of root is
the one structural change and it earns its keep on an unattended server: if
container images, logs or Postgres fill a shared filesystem you cannot stage an
ostree upgrade or cleanly log in to fix it. FCOS supports a separate /var as a
first-class configuration.
Nothing is needed in the image for this — lvm2, device-mapper, the dracut 70lvm
module and coreos-populate-lvmdevices.service are already present, and lsinitrd
confirms LVM is already in the initramfs.
bootc-image-builder minsize semantics
-------------------------------------
Documented in the file because it is not in the upstream docs and cost two
builds to pin down. `minsize` on the lvm partition is REQUIRED (omitting it
fails with "minsize is required"), and it is NOT the size of the volume group:
it is applied to the ROOT lv, root's own minsize is ignored, other LVs get
their own minsize, and the VG becomes the sum.
VG 26 GiB + root 16 GiB + var 10 GiB -> root=26G var=10G VG=36G raw 37.2 GiB
VG 16 GiB + root 16 GiB + var 10 GiB -> root=16G var=10G VG=26G raw 27.2 GiB
Not just image size: XFS cannot shrink, so an oversized root LV is space that
can never be handed back to var.
Justfile: bib raw output lands in output/image, not output/raw
--------------------------------------------------------------
The post-build step cleared output/${type} before `mv -f`. bib's subdir name
does not track --type: iso -> bootiso (already special-cased), raw -> image,
qcow2 -> qcow2. So for raw builds output/image was never cleared, mv failed
with "cannot overwrite 'output/image': Directory not empty", and the recipe
exited 1 while leaving the PREVIOUS build's disk.raw in place. A green-looking
build that silently ships a stale artifact. Replaced with an explicit
type -> dir mapping.
Verified by building three times and loop-mounting each result:
partition table 1M bios_grub / 200M EFI / 1G xfs /boot / 26G LVM2_member
/boot and EFI outside LVM, as required by the bootloader
vg4base root 16.00g xfs label=root (holds boot, ostree, var)
var 10.00g xfs label=var
APST karg present in /loader.1/entries/ostree-1.conf, so a dd'd
system is protected from its first boot
raw 29208084480 bytes, staged and sha256-verified to
/mnt/pny2xxG/server4homelab/july-29-2026/
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reverses course on LVM-on-root/-var. Three layouts were built, loop-mounted and
confirmed byte-correct, and all three failed to boot. FCOS/uCore cannot carry a
boot-critical filesystem on LVM:
1. root on an LV — the initramfs has NO LVM support at all:
dracut modules present : crypt, dm (no lvm)
lvm files in initramfs : none
FCOS finds root by LABEL, nothing can activate the VG, so:
dev-disk-by-label-root.device: Job ... failed with result 'timeout'
Started emergency.service - Emergency Shell
rd.lvm.lv= does not help; there is no LVM tooling to act on it.
2. root plain, /boot omitted — bib only auto-creates /boot when root is on an
LV, and customizations.disk gives exactly what you declare:
error: grub_search_label:527: no such device: boot.
error: grub_loader_boot:196: you need to load the kernel first.
3. root plain + /boot + /var on an LV — boots into the real root, then:
Timed out waiting for device dev-...-<var LV fs UUID>
Dependency failed for var.mount - /var
The image ships lvm2-monitor, lvm2-lvmpolld, lvm-devices-import and
coreos-populate-lvmdevices but NO activation unit (no lvm2-activation*, no
lvm2-pvscan@). And coreos-populate-lvmdevices declares
RequiresMountsFor=/var/lib — it needs /var mounted, which is the very thing
blocked. Circular, so it can never help here.
This layout is all-plain and mirrors what already runs on z170asrock:
1M bios_grub | 200M ESP | 1G xfs /boot (label boot) | 20G xfs / (label root)
Root is last, so it grows with plain `growpart <disk> <n> && xfs_growfs /`.
/boot is declared explicitly because the baked grub.cfg does
`search --label boot` and bib will not create it for a plain root.
VM-verified (qemu, OVMF, emulated NVMe, COW overlay grown to 4T so the GPT
alt-header condition matches a real dd):
GRUB loaded the kernel from /boot
initramfs found /dev/disk/by-label/root; XFS (nvme0n1p4) mounted
ostree-prepare-root: composefs mounted successfully
reached "localhost login:" — no emergency mode
nvme_core.default_ps_max_latency_us=0 present in the running cmdline
LVM is not abandoned, just moved out of the boot path: per-app LVs created
AFTER install and mounted under /var/lib/<app> with nofail and a device
timeout. That is all the snapshot-to-ZFS workflow needs. Documented in the file.
A loop-mount proves the bytes are right, not that it boots — all three failures
passed loop-mount inspection. Always VM-boot a change to this file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Owner
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two changes
iso/disk.toml, verified by booting it in a VM.mvcan no longer leave a previous build'sdisk.rawin place.Why there is no LVM in the boot path
FCOS/uCore cannot carry a boot-critical filesystem on LVM. Three attempts, all of which built cleanly and passed loop-mount inspection:
1 — root on an LV. The initramfs has no LVM support whatsoever:
FCOS locates root by LABEL; with no way to activate the VG the label never appears:
rd.lvm.lv=does not help — there is no LVM tooling in the initramfs to act on the karg.2 — root plain,
/bootomitted. bib only auto-creates/boot"when the root partition is on an LVM logical volume", andcustomizations.diskgives you exactly what you declare:3 — root plain +
/boot+/varon an LV. Boots into the real root, then:The image ships
lvm2-monitor,lvm2-lvmpolld,lvm-devices-importandcoreos-populate-lvmdevices, but no activation unit — nolvm2-activation*, nolvm2-pvscan@. Andcoreos-populate-lvmdevicescannot help: it declaresRequiresMountsFor=/var/lib, so it needs/varmounted, which is the very thing blocked. Circular.The layout that ships
Mirrors what already runs on z170asrock. Root is the last partition, so it grows with a plain
growpart <disk> <n> && xfs_growfs /./bootis declared explicitly because the bakedgrub.cfgdoessearch --label boot.VM verification
qemu + OVMF, emulated NVMe (so the device is
nvme0n1, matching the server), COW overlay over the realdisk.rawgrown to 4 TiB so the GPT-alt-header-not-at-end condition matches a realdd:Two benign messages:
failed to create symbolic link '/var/log'(present in every boot, including working ones) andzincati.servicefailing (no Ignition config in a bare VM; uCore usesrpm-ostreed-automaticanyway).Justfile: bib raw output lands in
output/image, notoutput/rawThe post-build step cleared
output/${type}beforemv -f. bib's subdir name does not track--type:--typeisobootiso(already special-cased)rawimage← the bugqcow2qcow2So
output/imagewas never cleared,mvfailed withcannot overwrite 'output/image': Directory not empty, and the recipe exited 1 while leaving the previous build'sdisk.rawin place. A July 21 image survived a July 29 build this way and was nearly verified as if it were new. Replaced with an explicit type→dir mapping.LVM is not abandoned — just moved out of the boot path
Per-app LVs created after install, mounted under
/var/lib/<app>withnofail,x-systemd.device-timeout=30so a problem degrades instead of hanging a headless box. That is all the snapshot→ZFS workflow needs:Standing rule added to the file
Always VM-boot a change to
disk.tomlbefore writing it to hardware. All three failures above passed loop-mount inspection. Byte-correct on disk is not the same as bootable.🤖 Generated with Claude Code