mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-07-06 17:13:24 -05:00
nixos/etc-overlay: ship empty /etc/machine-id on immutable /etc
The symlink to /var/lib/nixos/machine-id never persists the ID, systemd-machine-id-commit.service requires a writable /etc, and machine_id_commit() does not follow symlinks for its mountpoint check. So the backing file stays "uninitialized", every boot is ConditionFirstBoot=yes, and the machine-id is random per boot. Ship an empty regular file instead, systemd then overlays /run/machine-id for the session, ConditionFirstBoot is correctly "no", commit is cleanly condition-skipped, and the file is a usable bind target for users that want persistence. Fixes #523878
This commit is contained in:
parent
410a3a0797
commit
3eaafe4d48
2 changed files with 25 additions and 10 deletions
|
|
@ -182,16 +182,18 @@
|
|||
})
|
||||
|
||||
(lib.mkIf (config.system.etc.overlay.enable && !config.system.etc.overlay.mutable) {
|
||||
# Systemd requires /etc/machine-id exists or can be initialized on first
|
||||
# boot. This file should not be part of an image or system config because
|
||||
# it is unique to the machine, so it is initialized at first boot and
|
||||
# persisted in the system state directory, /var/lib/nixos.
|
||||
environment.etc."machine-id".source = lib.mkDefault "/var/lib/nixos/machine-id";
|
||||
boot.initrd.systemd.tmpfiles.settings.machine-id."/sysroot/var/lib/nixos/machine-id".f =
|
||||
lib.mkDefault
|
||||
{
|
||||
argument = "uninitialized";
|
||||
};
|
||||
# An empty regular file means systemd will bind mount /run/machine-id
|
||||
# on top, and ConditionFirstBoot will be false (the file will never
|
||||
# change, so this makes sense). See machine-id(5) "First Boot
|
||||
# Semantics". It also serves as a target to bind mount an actually
|
||||
# persistent machine-id onto. A symlink doesn't work here since
|
||||
# systemd-machine-id-commit checks /etc/machine-id itself for being a
|
||||
# mountpoint without following symlinks, so it would never commit
|
||||
# through a symlink.
|
||||
environment.etc.machine-id = lib.mkDefault {
|
||||
text = "";
|
||||
mode = "0444";
|
||||
};
|
||||
})
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -76,6 +76,19 @@
|
|||
with subtest("/etc is mounted as an overlay"):
|
||||
machine.succeed("findmnt --kernel --type overlay /etc")
|
||||
|
||||
with subtest("machine-id is set up without first-boot looping"):
|
||||
# The baked-in placeholder is an empty regular file; systemd overlays
|
||||
# /run/machine-id on top so the session has a valid ID while the
|
||||
# commit service is condition-skipped (no writable /etc to commit to).
|
||||
machine.succeed("stat --format '%F' /etc/machine-id | tee /dev/stderr | grep -q 'regular'")
|
||||
machine.succeed("grep -qE '^[0-9a-f]{32}$' /etc/machine-id")
|
||||
machine.fail("journalctl -b | grep -F 'System cannot boot: Missing /etc/machine-id'")
|
||||
machine.fail("journalctl -b | grep -F 'Detected first boot'")
|
||||
machine.fail("systemctl is-failed --quiet systemd-machine-id-commit.service")
|
||||
assert machine.succeed(
|
||||
"systemctl show -P ConditionResult systemd-machine-id-commit.service"
|
||||
).strip() == "no"
|
||||
|
||||
with subtest("modes work correctly"):
|
||||
machine.succeed("stat --format '%F' /etc/modetest | tee /dev/stderr | grep -q 'regular file'")
|
||||
machine.succeed("stat --format '%F' /etc/modetest2 | tee /dev/stderr | grep -q 'regular file'")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue