Skip to content

fix(images): force null UUID into machine-id before dracut#47

Open
passcod wants to merge 1 commit into
mainfrom
fix-machine-id-initramfs
Open

fix(images): force null UUID into machine-id before dracut#47
passcod wants to merge 1 commit into
mainfrom
fix-machine-id-initramfs

Conversation

@passcod
Copy link
Copy Markdown
Member

@passcod passcod commented May 14, 2026

Summary

Two pis flashed from the same image ended up with the same
/etc/machine-id. Tracing it back:

  • /boot/firmware/current/initrd.img contained a 33-byte
    /etc/machine-id matching the rootfs value bit-for-bit.
  • The dracut 10systemd module on noble (inst_multiple ... /etc/machine-id
    with a 0-byte fallback only when the file is missing) copies the host's
    /etc/machine-id verbatim — it does not regenerate.
  • Therefore /etc/machine-id was non-empty in the chroot at the moment
    dracut --force ran, despite the explicit truncate earlier in
    configure.sh. Something between the two is repopulating it. At
    switch-root, systemd-machine-id-commit propagates the baked value to
    the empty rootfs copy, so every flashed install inherits the same ID.

I haven't pinned down which step does the repopulation (the window is
narrow — hostname writes, KVER detection, then dracut — and none of
those should touch the file), but the fix doesn't depend on knowing: we
just write systemd's all-zeros "uninitialized" marker into
/etc/machine-id immediately before dracut --force. Whatever value
leaked back in gets overwritten with one systemd recognises as
uninitialized and regenerates per-install on first boot. The
post-chroot truncate in build.sh keeps the rootfs copy at zero bytes
per spec.

Adds a structure-test check that the initramfs's /etc/machine-id is
uninitialized (empty or all zeros) so this can't regress silently. Spec
extended at r[image.base.machine-id] to document the initramfs side
of the contract.

Recovery for already-flashed pis

sudo systemd-machine-id-setup --commit

— but only after deleting /etc/machine-id first, since the commit
path won't overwrite a populated file:

sudo rm /etc/machine-id
sudo systemd-machine-id-setup
sudo systemctl restart systemd-journald   # picks up the new ID

The 10systemd dracut module copies /etc/machine-id verbatim into the
initramfs. Truncating to zero bytes earlier in configure.sh is not
enough — something between that truncate and the dracut invocation
repopulates the file, baking a fixed UUID into the initramfs that then
propagates to every flashed install via systemd-machine-id-commit at
switch-root (observed in the field: two Pis from one image with
identical /etc/machine-id, matching the value bundled in
/boot/firmware/current/initrd.img).

Write systemd's all-zeros "uninitialized" marker right before dracut
runs so whatever value leaked back in is overwritten with one systemd
will regenerate per install on first boot. The post-chroot truncate in
build.sh keeps the rootfs copy at zero bytes per the spec.

Adds a test that the initramfs's /etc/machine-id is uninitialized
(empty or all zeros) so this can't regress silently.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant