diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c59f26c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# live-image/ runs on Linux regardless of dev host. Windows CRLF +# auto-conversion breaks shell script interpretation and Makefile +# recipes, so pin LF for the whole tree. +live-image/** text eol=lf +.gitea/** text eol=lf +*.sh text eol=lf +Makefile text eol=lf diff --git a/internal/pxe/ipxe.go b/internal/pxe/ipxe.go index 87454f5..062a867 100644 --- a/internal/pxe/ipxe.go +++ b/internal/pxe/ipxe.go @@ -35,13 +35,20 @@ func BuildScript(p IPXEParams) string { if p.TLSCertFPR != "" { cmdline = append(cmdline, fmt.Sprintf("vetting.cert_fpr=%s", p.TLSCertFPR)) } - // Reduce kernel log noise during the test run; keep loglevel high enough - // for boot failures to still show up on the console. + // Verbose kernel + systemd logging on both the video console and the + // serial port so first-boot failures on unfamiliar hardware aren't + // invisible. Drop `quiet` entirely — once boot is stable we can + // re-add it. systemd.log_target=kmsg makes early systemd go through + // the same dmesg buffer as the kernel, so nothing is lost before + // journald comes up. cmdline = append(cmdline, "console=tty0", "console=ttyS0,115200n8", "ip=dhcp", - "quiet", + "loglevel=7", + "systemd.log_level=info", + "systemd.log_target=kmsg", + "systemd.journald.forward_to_console=1", ) var b strings.Builder diff --git a/live-image/Makefile b/live-image/Makefile index a60fe44..0bdee46 100644 --- a/live-image/Makefile +++ b/live-image/Makefile @@ -32,9 +32,11 @@ repack-initrd: @# copies (release tarball) don't have to follow links. @cp -fL build/vmlinuz build/vmlinuz.real && mv build/vmlinuz.real build/vmlinuz @rm -f build/initrd.img build/initrd.img.old build/vmlinuz.old - @# Kernel execs /init from the unpacked initramfs. systemd-sysv puts - @# init at /sbin/init; add the top-level symlink the kernel looks for. - @[ -e build/init ] || ln -sf sbin/init build/init + @# /init ships via mkosi.extra/init as a shell script that sets up + @# api-vfs mounts and execs systemd. Force the exec bit on here — + @# Windows checkouts don't preserve +x, and mkosi.extra copies the + @# source-tree mode straight through. + @chmod 0755 build/init @# Skip /boot: holds the old kernel + stub initrd, both superseded. @# Write to a sibling temp path so find doesn't race with the @# archive being written into the dir it's walking. diff --git a/live-image/mkosi.extra/init b/live-image/mkosi.extra/init new file mode 100755 index 0000000..e7a0bb4 --- /dev/null +++ b/live-image/mkosi.extra/init @@ -0,0 +1,31 @@ +#!/bin/sh +# /init — PID 1 entry point for the everything-in-initramfs live image. +# +# The kernel unpacks our cpio.zst into a ramfs, sees no root= parameter, +# and execs /init. Classic initramfs-tools has an elaborate /init that +# mounts a real rootfs and pivot_roots into it; we don't do that — +# there IS no other rootfs, the initramfs IS the rootfs. All we need +# to do is set up the api-vfs mounts systemd expects before PID 1 and +# hand off. +# +# Running systemd directly as PID 1 from kernel /init works (systemd +# detects it's PID 1 and boots normally), but only if /proc, /sys, /dev +# are pre-mounted. Systemd has fallback mount code for these, but it's +# fragile in the ramfs-rootfs case — doing it here explicitly makes +# first-boot failures easier to see and harder to hit. + +set -e + +echo "vetting-init: bootstrapping api-vfs" + +mount -t proc -o nosuid,noexec,nodev proc /proc +mount -t sysfs -o nosuid,noexec,nodev sysfs /sys +mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev +mkdir -p /dev/pts /dev/shm /run +mount -t devpts -o gid=5,mode=620,nosuid,noexec devpts /dev/pts +mount -t tmpfs -o mode=1777,nosuid,nodev tmpfs /dev/shm +mount -t tmpfs -o mode=0755,nosuid,nodev tmpfs /run + +echo "vetting-init: handing off to systemd" + +exec /lib/systemd/systemd