Skip to main content

max / alloy

Stop dracut failing on /root, then make its errors fatal dracut preserves /root whenever it is a symlink, unconditionally and from its own main script rather than from any module or config file (dracut.sh:1949-1950). In the bootc layout /root points at var/roothome, /var is populated at install time rather than in a container image, so dracut-install resolved the link, found nothing, and printed "ERROR: installing '/root'" on every build since the beginning. One empty directory in the builder ends it. The error was harmless, which was the problem. make-iso.sh said "expect one error from this that does not matter" and moved on, and a build whose normal output contains dracut[E] and ERROR teaches whoever reads it to skim past both. With /root gone the check can be the strict one it could not be while a known error was expected: dracut's output is captured and any error fails the build. One message stays allowlisted, matched by its whole sentence rather than a pattern so the allowance cannot widen into "errors about logging are fine". dracut tests for /dev/log or a logger binary before it installs anything, so --install logger does not satisfy it. It concerns logging from inside the initramfs and nothing else.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-31 01:46 UTC
Signed with PGP, not checked
Commit: e88fa908ac2e799e18ec3bb269e5fcce3f0ad651
Parent: 8cae979
2 files changed, +45 insertions, -5 deletions
@@ -27,6 +27,30 @@
27 27 rsync \
28 28 && dnf clean all
29 29
30 + # Give dracut somewhere for /root to point.
31 + #
32 + # dracut preserves /root whenever it is a symlink, unconditionally and from
33 + # its own main script rather than from any module or config file:
34 + #
35 + # dracut.sh:1949 [ -L /root ]
36 + # dracut.sh:1950 inst_symlink /root
37 + #
38 + # In the bootc layout /root is a symlink to var/roothome, /var is populated
39 + # at install time rather than in a container image, and so dracut-install
40 + # resolved the link to /var/roothome, found nothing, and printed
41 + # "ERROR: installing '/root'" followed by a FAILED line, on every single
42 + # build. It was harmless — the initramfs was complete and the live boot
43 + # worked — which is exactly the problem: a build whose normal output
44 + # contains dracut[E] and ERROR teaches whoever reads it to skim past both,
45 + # and the next real failure arrives in a log already full of them.
46 + #
47 + # One empty directory ends it. The cost is an empty /root in the live
48 + # initramfs, which is where a root home belongs anyway. Fixed here in the
49 + # builder rather than in the shipped image, because it is the builder's own
50 + # filesystem dracut walks and the installed system already gets its
51 + # /var/roothome from bootc.
52 + RUN mkdir -p /var/roothome
53 +
30 54 COPY build/make-iso.sh /usr/local/bin/make-iso
31 55 RUN chmod +x /usr/local/bin/make-iso
32 56
@@ -108,20 +108,36 @@
108 108 --add "dmsquash-live" \
109 109 --omit "ostree bootc" \
110 110 --add-drivers "squashfs loop overlay iso9660 sr_mod sd_mod usb_storage virtio_blk virtio_scsi virtio_pci" \
111 - "$WORK/iso/boot/initramfs.img"
111 + "$WORK/iso/boot/initramfs.img" 2>&1 | tee "$WORK/dracut.log"
112 112
113 113 # dracut reports module failures on stderr and still exits 0, so a broken
114 114 # initramfs ships looking like a success. Check the result instead.
115 115 #
116 - # Expect one error from this that does not matter: dracut-install cannot
117 - # install `/root`, because in the bootc layout /root is a symlink to
118 - # var/roothome and nothing has mounted a var here. dracut carries on and
119 - # the initramfs is complete.
116 + # This build used to print `ERROR: installing '/root'` and a FAILED line
117 + # every time, harmlessly: /root is a symlink to var/roothome in the bootc
118 + # layout and no var is populated in a container. The builder now creates
119 + # /var/roothome (see build/Containerfile.iso), so that error is gone rather
120 + # than tolerated, and this check can be the strict one it could not be
121 + # while a known error was expected in normal output.
122 + #
123 + # One message is still allowlisted, by its exact text. dracut tests for
124 + # /dev/log or a logger binary before it installs anything and warns when it
125 + # finds neither; `--install logger` does not satisfy it, because the test
126 + # runs first. It concerns logging from inside the initramfs and nothing
127 + # else. Matching the whole sentence rather than a pattern keeps the
128 + # allowance from widening into "errors mentioning logging are fine".
120 129 #
121 130 # grep -c rather than grep -q: grep -q exits at the first match, which
122 131 # SIGPIPEs lsinitrd, and under `set -o pipefail` that reads as a failed
123 132 # check on a perfectly good initramfs. It cost a build to work that out.
124 133 [ -s "$WORK/iso/boot/initramfs.img" ] || { echo "dracut produced no initramfs" >&2; exit 1; }
134 + unexpected="$(grep -E 'dracut\[E\]|dracut-install: ERROR|FAILED' "$WORK/dracut.log" \
135 + | grep -vF "No '/dev/log' or 'logger' included for syslog logging" || true)"
136 + if [ -n "$unexpected" ]; then
137 + echo "dracut reported errors this build does not expect:" >&2
138 + printf '%s\n' "$unexpected" | sed 's/^/ /' >&2
139 + exit 1
140 + fi
125 141 found="$(lsinitrd "$WORK/iso/boot/initramfs.img" 2>/dev/null | grep -c dmsquash || true)"
126 142 [ "${found:-0}" -gt 0 ] \
127 143 || { echo "initramfs has no dmsquash-live; it cannot mount the live root" >&2; exit 1; }