From fc6501100fcee40c3f5845f0beb4d550492986c0 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 22 Sep 2026 21:36:20 -0700 Subject: [PATCH] refactor(os): apply rootfs tmpfiles at build time only dstack-image.conf lived in /usr/lib/tmpfiles.d, so besides shaping the build root it was re-run on every boot against the read-only verity root, where it can only succeed as a no-op or fail. Move it out of the skeleton and apply it from mkosi.finalize, after mkosi's own tmpfiles pass, so the image no longer carries a boot-time step that needs explaining. Running last, it also overrides the package defaults for the /var directories itself (e.g. tpm2-tss's 2775 keystore), which makes the .dstack-keep skeleton markers and their RemoveFiles= cleanup redundant. dstack-firstboot.service did the same with mkdir -p on directories the build already creates; drop it and its preset entry. --- os/mkosi/README.md | 6 ++++-- os/mkosi/mkosi.conf | 6 ------ os/mkosi/mkosi.finalize | 2 ++ .../etc/systemd/system/dstack-firstboot.service | 11 ----------- .../usr/lib/systemd/system-preset/80-dstack.preset | 1 - .../mkosi.skeleton/var/lib/containerd/.dstack-keep | 0 os/mkosi/mkosi.skeleton/var/lib/docker/.dstack-keep | 0 .../var/lib/tpm2-tss/system/keystore/.dstack-keep | 0 os/mkosi/mkosi.skeleton/var/mail/.dstack-keep | 0 os/mkosi/mkosi.skeleton/var/volatile/.dstack-keep | 0 .../tmpfiles.d/dstack-image.conf => rootfs.tmpfiles} | 0 os/mkosi/scripts/normalize-skeleton-modes.sh | 2 +- os/mkosi/tests/acceptance.sh | 4 +--- 13 files changed, 8 insertions(+), 24 deletions(-) delete mode 100644 os/mkosi/mkosi.skeleton/etc/systemd/system/dstack-firstboot.service delete mode 100644 os/mkosi/mkosi.skeleton/var/lib/containerd/.dstack-keep delete mode 100644 os/mkosi/mkosi.skeleton/var/lib/docker/.dstack-keep delete mode 100644 os/mkosi/mkosi.skeleton/var/lib/tpm2-tss/system/keystore/.dstack-keep delete mode 100644 os/mkosi/mkosi.skeleton/var/mail/.dstack-keep delete mode 100644 os/mkosi/mkosi.skeleton/var/volatile/.dstack-keep rename os/mkosi/{mkosi.skeleton/usr/lib/tmpfiles.d/dstack-image.conf => rootfs.tmpfiles} (100%) diff --git a/os/mkosi/README.md b/os/mkosi/README.md index 2311478ea..03ec3054c 100644 --- a/os/mkosi/README.md +++ b/os/mkosi/README.md @@ -157,7 +157,7 @@ would produce invalid or unparseable TDX measurement material. The distribution snapshot, build-only packages, guest packages, profiles, source mounts, source-date epoch, tools tree, package cleanup, file removal, -systemd presets, tmpfiles, service masks and the build/postinstall/finalize/ +systemd presets, service masks and the build/postinstall/finalize/ postoutput/clean lifecycle are mkosi-native. The native tar output is replaced in `mkosi.postoutput` by the identically named Yocto-compatible archive, so no unrelated mkosi rootfs artifact escapes the staging directory. @@ -182,6 +182,8 @@ Only four project-specific mechanisms remain: The tiny postinstall hook is also retained because mkosi's native `MachineId=` supports a UUID, `random`, or `uninitialized`, while the Yocto contract requires -an existing but empty `/etc/machine-id`. Rust and Go distributions are pinned by +an existing but empty `/etc/machine-id`. `mkosi.finalize` applies +`rootfs.tmpfiles` instead of shipping it in tmpfiles.d, where it would re-run +on every boot against the read-only root. Rust and Go distributions are pinned by version and SHA-256 inside the mkosi build overlay because Debian trixie's Rust package is too old for this workspace; they never come from the host. diff --git a/os/mkosi/mkosi.conf b/os/mkosi/mkosi.conf index 24b0a5a24..e8a16c249 100644 --- a/os/mkosi/mkosi.conf +++ b/os/mkosi/mkosi.conf @@ -84,12 +84,6 @@ Packages= # dstack-prepare treats as fatal. libxmlsec1t64-openssl libxmlsec1t64 -RemoveFiles= - /var/lib/containerd/.dstack-keep - /var/lib/docker/.dstack-keep - /var/lib/tpm2-tss/system/keystore/.dstack-keep - /var/mail/.dstack-keep - /var/volatile/.dstack-keep # No KernelCommandLine= here on purpose. mkosi only consumes it on bootable # paths (UKI build, bootloader entries, the vm/qemu verbs), all unreachable # with Bootable=no, so the value it used to carry was dead config that diff --git a/os/mkosi/mkosi.finalize b/os/mkosi/mkosi.finalize index 38032a15c..1707aa8d8 100755 --- a/os/mkosi/mkosi.finalize +++ b/os/mkosi/mkosi.finalize @@ -13,6 +13,8 @@ ARTIFACTS="$WORK/artifacts" source "$SELF/versions.env" "$SELF/scripts/normalize-skeleton-modes.sh" "$TREE" "$FLAVOR" +# After mkosi's own tmpfiles pass, so these override package defaults. +systemd-tmpfiles --root="$TREE" --create "$SELF/rootfs.tmpfiles" "$SELF/scripts/write-os-release.sh" \ "$TREE" "$DSTACK_VERSION" "$DSTACK_CODENAME" mkdir -p "$KSTAGE/usr/lib" "$OUTPUTDIR/.image-tools" diff --git a/os/mkosi/mkosi.skeleton/etc/systemd/system/dstack-firstboot.service b/os/mkosi/mkosi.skeleton/etc/systemd/system/dstack-firstboot.service deleted file mode 100644 index 207c85abf..000000000 --- a/os/mkosi/mkosi.skeleton/etc/systemd/system/dstack-firstboot.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Initialize dstack immutable guest state -Before=docker.service dstack-prepare.service - -[Service] -Type=oneshot -ExecStart=/usr/bin/mkdir -p /dstack /dstack/.host-shared /var/lib/docker /var/lib/containerd /etc/wireguard -RemainAfterExit=yes - -[Install] -WantedBy=multi-user.target diff --git a/os/mkosi/mkosi.skeleton/usr/lib/systemd/system-preset/80-dstack.preset b/os/mkosi/mkosi.skeleton/usr/lib/systemd/system-preset/80-dstack.preset index b51076f2a..0255d827e 100644 --- a/os/mkosi/mkosi.skeleton/usr/lib/systemd/system-preset/80-dstack.preset +++ b/os/mkosi/mkosi.skeleton/usr/lib/systemd/system-preset/80-dstack.preset @@ -7,7 +7,6 @@ enable chrony.service enable docker.service enable var-volatile.mount enable dstack-volatile-binds.service -enable dstack-firstboot.service enable dstack-prepare.service enable dstack-guest-agent.socket enable dstack-guest-agent.service diff --git a/os/mkosi/mkosi.skeleton/var/lib/containerd/.dstack-keep b/os/mkosi/mkosi.skeleton/var/lib/containerd/.dstack-keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/os/mkosi/mkosi.skeleton/var/lib/docker/.dstack-keep b/os/mkosi/mkosi.skeleton/var/lib/docker/.dstack-keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/os/mkosi/mkosi.skeleton/var/lib/tpm2-tss/system/keystore/.dstack-keep b/os/mkosi/mkosi.skeleton/var/lib/tpm2-tss/system/keystore/.dstack-keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/os/mkosi/mkosi.skeleton/var/mail/.dstack-keep b/os/mkosi/mkosi.skeleton/var/mail/.dstack-keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/os/mkosi/mkosi.skeleton/var/volatile/.dstack-keep b/os/mkosi/mkosi.skeleton/var/volatile/.dstack-keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/os/mkosi/mkosi.skeleton/usr/lib/tmpfiles.d/dstack-image.conf b/os/mkosi/rootfs.tmpfiles similarity index 100% rename from os/mkosi/mkosi.skeleton/usr/lib/tmpfiles.d/dstack-image.conf rename to os/mkosi/rootfs.tmpfiles diff --git a/os/mkosi/scripts/normalize-skeleton-modes.sh b/os/mkosi/scripts/normalize-skeleton-modes.sh index 758b5e617..f8b5e4887 100755 --- a/os/mkosi/scripts/normalize-skeleton-modes.sh +++ b/os/mkosi/scripts/normalize-skeleton-modes.sh @@ -28,7 +28,7 @@ for skeleton in "${skeletons[@]}"; do else chmod 0644 "$destination" fi - done < <(find "$skeleton" -type f ! -name .dstack-keep -print0) + done < <(find "$skeleton" -type f -print0) # -mindepth 1 keeps the skeleton root itself out of the loop; without it # the empty relative path would chmod the rootfs root as a side effect. diff --git a/os/mkosi/tests/acceptance.sh b/os/mkosi/tests/acceptance.sh index e2114dacc..44fb408ef 100755 --- a/os/mkosi/tests/acceptance.sh +++ b/os/mkosi/tests/acceptance.sh @@ -191,10 +191,8 @@ grep -q 'objcopy --strip-debug' "$D/mkosi.build" grep -q 'depmod -b.*KERNEL_VERSION-dstack' "$D/mkosi.build" grep -q '^CleanPackageMetadata=yes$' "$D/mkosi.conf" grep -q '^WithDocs=no$' "$D/mkosi.conf" -grep -q '/var/lib/docker/.dstack-keep' "$D/mkosi.conf" -grep -q '! -name .dstack-keep' "$D/scripts/normalize-skeleton-modes.sh" grep -q '/var/lib/tpm2-tss/system/keystore 0755' \ - "$D/mkosi.skeleton/usr/lib/tmpfiles.d/dstack-image.conf" + "$D/rootfs.tmpfiles" grep -q '/var/lib/dpkg' "$D/mkosi.profiles/prod/mkosi.conf" if grep -q '^[[:space:]]*ovmf$' "$D/mkosi.conf"; then echo 'distribution OVMF must not be installed in the guest rootfs' >&2