From e3cd6444584dc2d018a39ad7f94769caf043e621 Mon Sep 17 00:00:00 2001 From: Ning Shang Date: Fri, 16 Apr 2021 10:15:25 -0700 Subject: [PATCH 1/3] iso-image: Use fixed-order mcopy instead of file globbing mcopy file globbing is non-deterministic with respect to the underlying file system. As a result, the current mcopy approach is less likely to reproduce efi.img on different machines. We replace mcopy file globbing with fixed-order mmd and mcopy operations for better determinism. We also use faketime on mmd for the same reason. We use faketime, mmd, and mcopy directly, becase they are already in PATH. Thank misuzu@ for the feedback. --- nixos/modules/installer/cd-dvd/iso-image.nix | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 324b38070e47..5910bfc05ac2 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -415,7 +415,24 @@ let echo "Image size: $image_size" truncate --size=$image_size "$out" faketime "2000-01-01 00:00:00" mkfs.vfat -i 12345678 -n EFIBOOT "$out" - mcopy -psvm -i "$out" ./EFI ./boot :: + + # Force a fixed order in mcopy for better determinism, and avoid file globbing + for d in $(find EFI -type d | sort); do + faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d" + done + + for d in $(find boot -type d | sort); do + faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d" + done + + for f in $(find EFI -type f | sort); do + mcopy -pvm -i "$out" "$f" "::/$f" + done + + for f in $(find boot -type f | sort); do + mcopy -pvm -i "$out" "$f" "::/$f" + done + # Verify the FAT partition. fsck.vfat -vn "$out" ''; # */ From 4db7eb476f30a819eacd1459d78bf8fe5b3bccb3 Mon Sep 17 00:00:00 2001 From: Ning Shang Date: Thu, 20 May 2021 11:01:17 -0700 Subject: [PATCH 2/3] iso-image: Workaround for better determinism in du output The value of du output depends on the underlying file system, and thus is not fully deterministic. This workaround rounds up the disk usage size to the nearest multiple of 1MB, to increase the probability that two du output values on two different file systems fall within the same 1MB window. Note that this workaround won't make du output 100% reproducible, but will increase the probability of getting deterministic builds across different file systems. --- nixos/modules/installer/cd-dvd/iso-image.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 5910bfc05ac2..c3d12bda28d7 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -405,7 +405,8 @@ let "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}" ./boot/ touch --date=@0 ./EFI ./boot - usage_size=$(du -sb --apparent-size . | tr -cd '[:digit:]') + # Round up to the nearest multiple of 1MB, for more deterministic du output + usage_size=$(( $(du -s --block-size=1M --apparent-size . | tr -cd '[:digit:]') * 1024 * 1024 )) # Make the image 110% as big as the files need to make up for FAT overhead image_size=$(( ($usage_size * 110) / 100 )) # Make the image fit blocks of 1M From 657e924ad853e099cbc36be50478e9877aa05a25 Mon Sep 17 00:00:00 2001 From: Ning Shang Date: Thu, 20 May 2021 12:17:04 -0700 Subject: [PATCH 3/3] iso-image: More concise code for fixed order mmd and mcopy operations Thanks @misuzu for the suggestions. --- nixos/modules/installer/cd-dvd/iso-image.nix | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index c3d12bda28d7..62fc097f9ddb 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -418,19 +418,11 @@ let faketime "2000-01-01 00:00:00" mkfs.vfat -i 12345678 -n EFIBOOT "$out" # Force a fixed order in mcopy for better determinism, and avoid file globbing - for d in $(find EFI -type d | sort); do + for d in $(find EFI boot -type d | sort); do faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d" done - for d in $(find boot -type d | sort); do - faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d" - done - - for f in $(find EFI -type f | sort); do - mcopy -pvm -i "$out" "$f" "::/$f" - done - - for f in $(find boot -type f | sort); do + for f in $(find EFI boot -type f | sort); do mcopy -pvm -i "$out" "$f" "::/$f" done