nixos/systemd-boot-builder: rebuild secret-bearing initrds atomically each run

Appending to the existing file made it grow on every rebuild and a
failed script could leave it half-written. Always rebuild from the
pristine initrd into a temp file and rename into place.
This commit is contained in:
r-vdp
2026-05-04 12:16:42 +02:00
parent 6ef460ec9d
commit 6eba7d60f3
@@ -88,29 +88,26 @@ class InitrdWithSecretsWriter:
initrd_secrets: Path
def write_boot_file(self, path: Path) -> None:
if path.exists():
# TODO: This is for matching old behavior. Previously, we
# appended secrets to initrd every time no matter what, so
# we must continue doing that. One potential alternative
# would be running the secret script on an empty file and
# using the hashed contents of that file as part of the
# key that the path name is based on.
run([self.initrd_secrets, path])
else:
with tempfile.NamedTemporaryFile(
mode="wb",
dir=path.parent,
delete=False,
prefix=path.name,
suffix=".tmp",
) as tmp:
with open(self.source, mode="rb") as source_file:
shutil.copyfileobj(source_file, tmp)
tmp.flush()
run([self.initrd_secrets, tmp.name])
os.fsync(tmp.fileno())
tmp.close()
os.rename(tmp.name, path)
# Secrets can change between rebuilds, so always rebuild from the
# pristine initrd into a temp file and rename into place.
tmp = tempfile.NamedTemporaryFile(
mode="wb",
dir=path.parent,
delete=False,
prefix=path.name,
suffix=".tmp",
)
try:
with open(self.source, mode="rb") as source_file:
shutil.copyfileobj(source_file, tmp)
tmp.close()
run([self.initrd_secrets, tmp.name])
with open(tmp.name, "rb") as f:
os.fsync(f.fileno())
except BaseException:
os.unlink(tmp.name)
raise
os.rename(tmp.name, path)
@dataclass