Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at python-updates 1615 lines 50 kB view raw
1{ 2 lib, 3 stdenv, 4 buildPackages, 5 bash, 6 bashInteractive, 7 busybox, 8 coreutils, 9 cpio, 10 dpkg, 11 e2fsprogs, 12 fetchurl, 13 glibc, 14 kmod, 15 linux, 16 makeInitrd, 17 makeModulesClosure, 18 mtdutils, 19 rpm, 20 runCommand, 21 util-linux, 22 virtiofsd, 23 writeScript, 24 writeText, 25 xz, 26 zstd, 27 28 # ---------------------------- 29 # The following arguments form the "interface" of `pkgs.vmTools`. 30 # Note that `img` is a real package, but is set to this default in `all-packages.nix`. 31 # ---------------------------- 32 customQemu ? null, 33 kernel ? linux, 34 img ? stdenv.hostPlatform.linux-kernel.target, 35 storeDir ? builtins.storeDir, 36 rootModules ? [ 37 "virtio_pci" 38 "virtio_mmio" 39 "virtio_blk" 40 "virtio_balloon" 41 "virtio_rng" 42 "ext4" 43 "virtiofs" 44 "crc32c_generic" 45 ], 46}: 47 48let 49 qemu-common = import ../../../nixos/lib/qemu-common.nix { inherit lib stdenv; }; 50 51 qemu = buildPackages.qemu_kvm; 52 53 modulesClosure = makeModulesClosure { 54 kernel = lib.getOutput "modules" kernel; 55 inherit rootModules; 56 firmware = kernel; 57 }; 58 59 hd = "vda"; # either "sda" or "vda" 60 61 initrdUtils = 62 runCommand "initrd-utils" 63 { 64 nativeBuildInputs = [ buildPackages.nukeReferences ]; 65 allowedReferences = [ 66 "out" 67 modulesClosure 68 ]; # prevent accidents like glibc being included in the initrd 69 } 70 '' 71 mkdir -p $out/bin 72 mkdir -p $out/lib 73 74 # Copy what we need from Glibc. 75 cp -p \ 76 ${stdenv.cc.libc}/lib/ld-*.so.? \ 77 ${stdenv.cc.libc}/lib/libc.so.* \ 78 ${stdenv.cc.libc}/lib/libm.so.* \ 79 ${stdenv.cc.libc}/lib/libresolv.so.* \ 80 ${stdenv.cc.libc}/lib/libpthread.so.* \ 81 ${zstd.out}/lib/libzstd.so.* \ 82 ${xz.out}/lib/liblzma.so.* \ 83 $out/lib 84 85 # Copy BusyBox. 86 cp -pd ${busybox}/bin/* $out/bin 87 cp -pd ${kmod}/bin/* $out/bin 88 89 # Run patchelf to make the programs refer to the copied libraries. 90 for i in $out/bin/* $out/lib/*; do if ! test -L $i; then nuke-refs $i; fi; done 91 92 for i in $out/bin/*; do 93 if [ -f "$i" -a ! -L "$i" ]; then 94 echo "patching $i..." 95 patchelf --set-interpreter $out/lib/ld-*.so.? --set-rpath $out/lib $i || true 96 fi 97 done 98 99 find $out/lib -type f \! -name 'ld*.so.?' | while read i; do 100 echo "patching $i..." 101 patchelf --set-rpath $out/lib $i 102 done 103 ''; # */ 104 105 stage1Init = writeScript "vm-run-stage1" '' 106 #! ${initrdUtils}/bin/ash -e 107 108 export PATH=${initrdUtils}/bin 109 110 mkdir /etc 111 echo -n > /etc/fstab 112 113 mount -t proc none /proc 114 mount -t sysfs none /sys 115 116 echo 2 > /proc/sys/vm/panic_on_oom 117 118 for o in $(cat /proc/cmdline); do 119 case $o in 120 mountDisk=*) 121 mountDisk=''${mountDisk#mountDisk=} 122 ;; 123 command=*) 124 set -- $(IFS==; echo $o) 125 command=$2 126 ;; 127 esac 128 done 129 130 echo "loading kernel modules..." 131 for i in $(cat ${modulesClosure}/insmod-list); do 132 insmod $i || echo "warning: unable to load $i" 133 done 134 135 mount -t devtmpfs devtmpfs /dev 136 ln -s /proc/self/fd /dev/fd 137 ln -s /proc/self/fd/0 /dev/stdin 138 ln -s /proc/self/fd/1 /dev/stdout 139 ln -s /proc/self/fd/2 /dev/stderr 140 141 ifconfig lo up 142 143 mkdir /fs 144 145 if test -z "$mountDisk"; then 146 mount -t tmpfs none /fs 147 elif [[ -e "$mountDisk" ]]; then 148 mount "$mountDisk" /fs 149 else 150 mount /dev/${hd} /fs 151 fi 152 153 mkdir -p /fs/dev 154 mount -o bind /dev /fs/dev 155 156 mkdir -p /fs/dev/shm /fs/dev/pts 157 mount -t tmpfs -o "mode=1777" none /fs/dev/shm 158 mount -t devpts none /fs/dev/pts 159 160 echo "mounting Nix store..." 161 mkdir -p /fs${storeDir} 162 mount -t virtiofs store /fs${storeDir} 163 164 mkdir -p /fs/tmp /fs/run /fs/var 165 mount -t tmpfs -o "mode=1777" none /fs/tmp 166 mount -t tmpfs -o "mode=755" none /fs/run 167 ln -sfn /run /fs/var/run 168 169 echo "mounting host's temporary directory..." 170 mkdir -p /fs/tmp/xchg 171 mount -t virtiofs xchg /fs/tmp/xchg 172 173 mkdir -p /fs/proc 174 mount -t proc none /fs/proc 175 176 mkdir -p /fs/sys 177 mount -t sysfs none /fs/sys 178 179 mkdir -p /fs/etc 180 ln -sf /proc/mounts /fs/etc/mtab 181 echo "127.0.0.1 localhost" > /fs/etc/hosts 182 # Ensures tools requiring /etc/passwd will work (e.g. nix) 183 if [ ! -e /fs/etc/passwd ]; then 184 echo "root:x:0:0:System administrator:/root:/bin/sh" > /fs/etc/passwd 185 fi 186 187 echo "starting stage 2 ($command)" 188 exec switch_root /fs $command 189 ''; 190 191 initrd = makeInitrd { 192 contents = [ 193 { 194 object = stage1Init; 195 symlink = "/init"; 196 } 197 ]; 198 }; 199 200 stage2Init = writeScript "vm-run-stage2" '' 201 #! ${bash}/bin/sh 202 set -euo pipefail 203 source /tmp/xchg/saved-env 204 if [ -f /tmp/xchg/.attrs.sh ]; then 205 source /tmp/xchg/.attrs.sh 206 export NIX_ATTRS_JSON_FILE=/tmp/xchg/.attrs.json 207 export NIX_ATTRS_SH_FILE=/tmp/xchg/.attrs.sh 208 fi 209 210 export NIX_STORE=${storeDir} 211 export NIX_BUILD_TOP=/tmp 212 export TMPDIR=/tmp 213 export PATH=/empty 214 cd "$NIX_BUILD_TOP" 215 216 source $stdenv/setup 217 218 if ! test -e /bin/sh; then 219 ${coreutils}/bin/mkdir -p /bin 220 ${coreutils}/bin/ln -s ${bash}/bin/sh /bin/sh 221 fi 222 223 # Set up automatic kernel module loading. 224 export MODULE_DIR=${lib.getOutput "modules" kernel}/lib/modules/ 225 ${coreutils}/bin/cat <<EOF > /run/modprobe 226 #! ${bash}/bin/sh 227 export MODULE_DIR=$MODULE_DIR 228 exec ${kmod}/bin/modprobe "\$@" 229 EOF 230 ${coreutils}/bin/chmod 755 /run/modprobe 231 echo /run/modprobe > /proc/sys/kernel/modprobe 232 233 # For debugging: if this is the second time this image is run, 234 # then don't start the build again, but instead drop the user into 235 # an interactive shell. 236 if test -n "$origBuilder" -a ! -e /.debug; then 237 exec < /dev/null 238 ${coreutils}/bin/touch /.debug 239 declare -a argsArray=() 240 concatTo argsArray origArgs 241 "$origBuilder" "''${argsArray[@]}" 242 echo $? > /tmp/xchg/in-vm-exit 243 244 ${busybox}/bin/mount -o remount,ro dummy / 245 246 ${busybox}/bin/poweroff -f 247 else 248 export PATH=/bin:/usr/bin:${coreutils}/bin 249 echo "Starting interactive shell..." 250 echo "(To run the original builder: \$origBuilder \$origArgs)" 251 exec ${busybox}/bin/setsid ${bashInteractive}/bin/bash < /dev/${qemu-common.qemuSerialDevice} &> /dev/${qemu-common.qemuSerialDevice} 252 fi 253 ''; 254 255 qemuCommandLinux = '' 256 ${if (customQemu != null) then customQemu else (qemu-common.qemuBinary qemu)} \ 257 -nographic -no-reboot \ 258 -device virtio-rng-pci \ 259 -chardev socket,id=store,path=virtio-store.sock \ 260 -device vhost-user-fs-pci,chardev=store,tag=store \ 261 -chardev socket,id=xchg,path=virtio-xchg.sock \ 262 -device vhost-user-fs-pci,chardev=xchg,tag=xchg \ 263 ''${diskImage:+-drive file=$diskImage,if=virtio,cache=unsafe,werror=report} \ 264 -kernel ${kernel}/${img} \ 265 -initrd ${initrd}/initrd \ 266 -append "console=${qemu-common.qemuSerialDevice} panic=1 command=${stage2Init} mountDisk=$mountDisk loglevel=4" \ 267 $QEMU_OPTS 268 ''; 269 270 vmRunCommand = 271 qemuCommand: 272 writeText "vm-run" '' 273 ${coreutils}/bin/mkdir xchg 274 export > xchg/saved-env 275 276 if [ -f "''${NIX_ATTRS_SH_FILE-}" ]; then 277 ${coreutils}/bin/cp $NIX_ATTRS_JSON_FILE $NIX_ATTRS_SH_FILE xchg 278 source "$NIX_ATTRS_SH_FILE" 279 fi 280 source $stdenv/setup 281 282 eval "$preVM" 283 284 if [ "$enableParallelBuilding" = 1 ]; then 285 QEMU_NR_VCPUS=0 286 if [ ''${NIX_BUILD_CORES:-0} = 0 ]; then 287 QEMU_NR_VCPUS="$(nproc)" 288 else 289 QEMU_NR_VCPUS="$NIX_BUILD_CORES" 290 fi 291 # qemu only supports 255 vCPUs (see error from `qemu-system-x86_64 -smp 256`) 292 if [ "$QEMU_NR_VCPUS" -gt 255 ]; then 293 QEMU_NR_VCPUS=255 294 fi 295 QEMU_OPTS+=" -smp cpus=$QEMU_NR_VCPUS" 296 fi 297 298 # Write the command to start the VM to a file so that the user can 299 # debug inside the VM if the build fails (when Nix is called with 300 # the -K option to preserve the temporary build directory). 301 ${coreutils}/bin/cat > ./run-vm <<EOF 302 #! ${bash}/bin/sh 303 ''${diskImage:+diskImage=$diskImage} 304 # GitHub Actions runners seems to not allow installing seccomp filter: https://github.com/rcambrj/nix-pi-loader/issues/1#issuecomment-2605497516 305 # Since we are running in a sandbox already, the difference between seccomp and none is minimal 306 ${virtiofsd}/bin/virtiofsd --xattr --socket-path virtio-store.sock --sandbox none --seccomp none --shared-dir "${storeDir}" & 307 ${virtiofsd}/bin/virtiofsd --xattr --socket-path virtio-xchg.sock --sandbox none --seccomp none --shared-dir xchg & 308 309 # Wait until virtiofsd has created these sockets to avoid race condition. 310 until [[ -e virtio-store.sock ]]; do ${coreutils}/bin/sleep 1; done 311 until [[ -e virtio-xchg.sock ]]; do ${coreutils}/bin/sleep 1; done 312 313 ${qemuCommand} 314 EOF 315 316 ${coreutils}/bin/chmod +x ./run-vm 317 source ./run-vm 318 319 if ! test -e xchg/in-vm-exit; then 320 echo "Virtual machine didn't produce an exit code." 321 exit 1 322 fi 323 324 exitCode="$(${coreutils}/bin/cat xchg/in-vm-exit)" 325 if [ "$exitCode" != "0" ]; then 326 exit "$exitCode" 327 fi 328 329 eval "$postVM" 330 ''; 331 332 # A bash script fragment that produces a disk image at `destination`. 333 createEmptyImage = 334 { 335 # Disk image size in MiB (1024*1024 bytes) 336 size, 337 # Name that will be written to ${destination}/nix-support/full-name 338 fullName, 339 # Where to write the image files, defaulting to $out 340 destination ? "$out", 341 }: 342 '' 343 mkdir -p ${destination} 344 diskImage=${destination}/disk-image.qcow2 345 ${qemu}/bin/qemu-img create -f qcow2 $diskImage "${toString size}M" 346 347 mkdir ${destination}/nix-support 348 echo "${fullName}" > ${destination}/nix-support/full-name 349 ''; 350 351 defaultCreateRootFS = '' 352 mkdir /mnt 353 ${e2fsprogs}/bin/mkfs.ext4 /dev/${hd} 354 ${util-linux}/bin/mount -t ext4 /dev/${hd} /mnt 355 356 if test -e /mnt/.debug; then 357 exec ${bash}/bin/sh 358 fi 359 touch /mnt/.debug 360 361 mkdir /mnt/proc /mnt/dev /mnt/sys 362 ''; 363 364 /* 365 Run a derivation in a Linux virtual machine (using Qemu/KVM). By 366 default, there is no disk image; the root filesystem is a tmpfs, 367 and the nix store is shared with the host (via the 9P protocol). 368 Thus, any pure Nix derivation should run unmodified, e.g. the 369 call 370 371 runInLinuxVM patchelf 372 373 will build the derivation `patchelf' inside a VM. The attribute 374 `preVM' can optionally contain a shell command to be evaluated 375 *before* the VM is started (i.e., on the host). The attribute 376 `memSize' specifies the memory size of the VM in MiB (1024*1024 377 bytes), defaulting to 512. The attribute `diskImage' can 378 optionally specify a file system image to be attached to /dev/sda. 379 (Note that currently we expect the image to contain a filesystem, 380 not a full disk image with a partition table etc.) 381 382 If the build fails and Nix is run with the `-K' option, a script 383 `run-vm' will be left behind in the temporary build directory 384 that allows you to boot into the VM and debug it interactively. 385 */ 386 387 runInLinuxVM = 388 drv: 389 lib.overrideDerivation drv ( 390 { 391 memSize ? 512, 392 QEMU_OPTS ? "", 393 args, 394 builder, 395 ... 396 }: 397 { 398 requiredSystemFeatures = [ "kvm" ]; 399 builder = "${bash}/bin/sh"; 400 args = [ 401 "-e" 402 (vmRunCommand qemuCommandLinux) 403 ]; 404 origArgs = args; 405 origBuilder = builder; 406 QEMU_OPTS = "${QEMU_OPTS} -m ${toString memSize} -object memory-backend-memfd,id=mem,size=${toString memSize}M,share=on -machine memory-backend=mem"; 407 passAsFile = [ ]; # HACK fix - see https://github.com/NixOS/nixpkgs/issues/16742 408 } 409 ); 410 411 extractFs = 412 { 413 file, 414 fs ? null, 415 }: 416 runInLinuxVM ( 417 stdenv.mkDerivation { 418 name = "extract-file"; 419 buildInputs = [ util-linux ]; 420 buildCommand = '' 421 ln -s ${kernel}/lib /lib 422 ${kmod}/bin/modprobe loop 423 ${kmod}/bin/modprobe ext4 424 ${kmod}/bin/modprobe hfs 425 ${kmod}/bin/modprobe hfsplus 426 ${kmod}/bin/modprobe squashfs 427 ${kmod}/bin/modprobe iso9660 428 ${kmod}/bin/modprobe ufs 429 ${kmod}/bin/modprobe cramfs 430 431 mkdir -p $out 432 mkdir -p tmp 433 mount -o loop,ro,ufstype=44bsd ${lib.optionalString (fs != null) "-t ${fs} "}${file} tmp || 434 mount -o loop,ro ${lib.optionalString (fs != null) "-t ${fs} "}${file} tmp 435 cp -Rv tmp/* $out/ || exit 0 436 ''; 437 } 438 ); 439 440 extractMTDfs = 441 { 442 file, 443 fs ? null, 444 }: 445 runInLinuxVM ( 446 stdenv.mkDerivation { 447 name = "extract-file-mtd"; 448 buildInputs = [ 449 util-linux 450 mtdutils 451 ]; 452 buildCommand = '' 453 ln -s ${kernel}/lib /lib 454 ${kmod}/bin/modprobe mtd 455 ${kmod}/bin/modprobe mtdram total_size=131072 456 ${kmod}/bin/modprobe mtdchar 457 ${kmod}/bin/modprobe mtdblock 458 ${kmod}/bin/modprobe jffs2 459 ${kmod}/bin/modprobe zlib 460 461 mkdir -p $out 462 mkdir -p tmp 463 464 dd if=${file} of=/dev/mtd0 465 mount ${lib.optionalString (fs != null) "-t ${fs} "}/dev/mtdblock0 tmp 466 467 cp -R tmp/* $out/ 468 ''; 469 } 470 ); 471 472 /* 473 Like runInLinuxVM, but run the build not using the stdenv from 474 the Nix store, but using the tools provided by /bin, /usr/bin 475 etc. from the specified filesystem image, which typically is a 476 filesystem containing a non-NixOS Linux distribution. 477 */ 478 479 runInLinuxImage = 480 drv: 481 runInLinuxVM ( 482 lib.overrideDerivation drv (attrs: { 483 mountDisk = attrs.mountDisk or true; 484 485 /* 486 Mount `image' as the root FS, but use a temporary copy-on-write 487 image since we don't want to (and can't) write to `image'. 488 */ 489 preVM = '' 490 diskImage=$(pwd)/disk-image.qcow2 491 origImage=${attrs.diskImage} 492 if test -d "$origImage"; then origImage="$origImage/disk-image.qcow2"; fi 493 ${qemu}/bin/qemu-img create -F ${attrs.diskImageFormat} -b "$origImage" -f qcow2 $diskImage 494 ''; 495 496 /* 497 Inside the VM, run the stdenv setup script normally, but at the 498 very end set $PATH and $SHELL to the `native' paths for the 499 distribution inside the VM. 500 */ 501 postHook = '' 502 PATH=/usr/bin:/bin:/usr/sbin:/sbin 503 SHELL=/bin/sh 504 eval "$origPostHook" 505 ''; 506 507 origPostHook = lib.optionalString (attrs ? postHook) attrs.postHook; 508 509 # Don't run Nix-specific build steps like patchelf. 510 fixupPhase = "true"; 511 }) 512 ); 513 514 /* 515 Create a filesystem image of the specified size and fill it with 516 a set of RPM packages. 517 */ 518 519 fillDiskWithRPMs = 520 { 521 size ? 4096, 522 rpms, 523 name, 524 fullName, 525 preInstall ? "", 526 postInstall ? "", 527 runScripts ? true, 528 createRootFS ? defaultCreateRootFS, 529 QEMU_OPTS ? "", 530 memSize ? 512, 531 unifiedSystemDir ? false, 532 }: 533 534 runInLinuxVM ( 535 stdenv.mkDerivation { 536 inherit 537 name 538 preInstall 539 postInstall 540 rpms 541 QEMU_OPTS 542 memSize 543 ; 544 preVM = createEmptyImage { inherit size fullName; }; 545 546 buildCommand = '' 547 ${createRootFS} 548 549 chroot=$(type -tP chroot) 550 551 # Make the Nix store available in /mnt, because that's where the RPMs live. 552 mkdir -p /mnt${storeDir} 553 ${util-linux}/bin/mount -o bind ${storeDir} /mnt${storeDir} 554 # Some programs may require devices in /dev to be available (e.g. /dev/random) 555 ${util-linux}/bin/mount -o bind /dev /mnt/dev 556 557 # Newer distributions like Fedora 18 require /lib etc. to be 558 # symlinked to /usr. 559 ${lib.optionalString unifiedSystemDir '' 560 mkdir -p /mnt/usr/bin /mnt/usr/lib /mnt/usr/lib64 561 ln -s /usr/bin /mnt/bin 562 ln -s /usr/bin /mnt/sbin 563 ln -s /usr/bin /mnt/usr/sbin 564 ln -s /usr/lib /mnt/lib 565 ln -s /usr/lib64 /mnt/lib64 566 ${util-linux}/bin/mount -t proc none /mnt/proc 567 ''} 568 569 echo "unpacking RPMs..." 570 set +o pipefail 571 for i in $rpms; do 572 echo "$i..." 573 ${rpm}/bin/rpm2cpio "$i" | chroot /mnt ${cpio}/bin/cpio -i --make-directories --unconditional 574 done 575 576 eval "$preInstall" 577 578 echo "initialising RPM DB..." 579 PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ 580 ldconfig -v || true 581 PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ 582 rpm --initdb 583 584 ${util-linux}/bin/mount -o bind /tmp /mnt/tmp 585 586 echo "installing RPMs..." 587 PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ 588 rpm -iv --nosignature ${lib.optionalString (!runScripts) "--noscripts"} $rpms 589 590 echo "running post-install script..." 591 eval "$postInstall" 592 593 rm /mnt/.debug 594 595 ${util-linux}/bin/umount /mnt${storeDir} /mnt/tmp /mnt/dev ${lib.optionalString unifiedSystemDir "/mnt/proc"} 596 ${util-linux}/bin/umount /mnt 597 ''; 598 599 passthru = { inherit fullName; }; 600 } 601 ); 602 603 /* 604 Generate a script that can be used to run an interactive session 605 in the given image. 606 */ 607 608 makeImageTestScript = 609 image: 610 writeScript "image-test" '' 611 #! ${bash}/bin/sh 612 if test -z "$1"; then 613 echo "Syntax: $0 <copy-on-write-temp-file>" 614 exit 1 615 fi 616 diskImage="$1" 617 if ! test -e "$diskImage"; then 618 ${qemu}/bin/qemu-img create -b ${image}/disk-image.qcow2 -f qcow2 -F qcow2 "$diskImage" 619 fi 620 export TMPDIR=$(mktemp -d) 621 export out=/dummy 622 export origBuilder= 623 export origArgs= 624 mkdir $TMPDIR/xchg 625 export > $TMPDIR/xchg/saved-env 626 mountDisk=1 627 ${qemuCommandLinux} 628 ''; 629 630 /* 631 Build RPM packages from the tarball `src' in the Linux 632 distribution installed in the filesystem `diskImage'. The 633 tarball must contain an RPM specfile. 634 */ 635 636 buildRPM = 637 attrs: 638 runInLinuxImage ( 639 stdenv.mkDerivation ( 640 { 641 prePhases = [ 642 "prepareImagePhase" 643 "sysInfoPhase" 644 ]; 645 dontConfigure = true; 646 647 outDir = "rpms/${attrs.diskImage.name}"; 648 649 prepareImagePhase = '' 650 if test -n "$extraRPMs"; then 651 for rpmdir in $extraRPMs ; do 652 rpm -iv $(ls $rpmdir/rpms/*/*.rpm | grep -v 'src\.rpm' | sort | head -1) 653 done 654 fi 655 ''; 656 657 sysInfoPhase = '' 658 echo "System/kernel: $(uname -a)" 659 if test -e /etc/fedora-release; then echo "Fedora release: $(cat /etc/fedora-release)"; fi 660 if test -e /etc/SuSE-release; then echo "SUSE release: $(cat /etc/SuSE-release)"; fi 661 echo "installed RPM packages" 662 rpm -qa --qf "%{Name}-%{Version}-%{Release} (%{Arch}; %{Distribution}; %{Vendor})\n" 663 ''; 664 665 buildPhase = '' 666 eval "$preBuild" 667 668 srcName="$(rpmspec --srpm -q --qf '%{source}' *.spec)" 669 cp "$src" "$srcName" # `ln' doesn't work always work: RPM requires that the file is owned by root 670 671 export HOME=/tmp/home 672 mkdir $HOME 673 674 rpmout=/tmp/rpmout 675 mkdir $rpmout $rpmout/SPECS $rpmout/BUILD $rpmout/RPMS $rpmout/SRPMS 676 677 echo "%_topdir $rpmout" >> $HOME/.rpmmacros 678 679 if [ `uname -m` = i686 ]; then extra="--target i686-linux"; fi 680 rpmbuild -vv $extra -ta "$srcName" 681 682 eval "$postBuild" 683 ''; 684 685 installPhase = '' 686 eval "$preInstall" 687 688 mkdir -p $out/$outDir 689 find $rpmout -name "*.rpm" -exec cp {} $out/$outDir \; 690 691 for i in $out/$outDir/*.rpm; do 692 echo "Generated RPM/SRPM: $i" 693 rpm -qip $i 694 done 695 696 eval "$postInstall" 697 ''; # */ 698 } 699 // attrs 700 ) 701 ); 702 703 /* 704 Create a filesystem image of the specified size and fill it with 705 a set of Debian packages. `debs' must be a list of list of 706 .deb files, namely, the Debian packages grouped together into 707 strongly connected components. See deb/deb-closure.nix. 708 */ 709 710 fillDiskWithDebs = 711 { 712 size ? 4096, 713 debs, 714 name, 715 fullName, 716 postInstall ? null, 717 createRootFS ? defaultCreateRootFS, 718 QEMU_OPTS ? "", 719 memSize ? 512, 720 ... 721 }@args: 722 723 runInLinuxVM ( 724 stdenv.mkDerivation ( 725 { 726 inherit 727 name 728 postInstall 729 QEMU_OPTS 730 memSize 731 ; 732 733 debs = (lib.intersperse "|" debs); 734 735 preVM = createEmptyImage { inherit size fullName; }; 736 737 buildCommand = '' 738 ${createRootFS} 739 740 PATH=$PATH:${ 741 lib.makeBinPath [ 742 dpkg 743 glibc 744 xz 745 ] 746 } 747 748 # Unpack the .debs. We do this to prevent pre-install scripts 749 # (which have lots of circular dependencies) from barfing. 750 echo "unpacking Debs..." 751 752 for deb in $debs; do 753 if test "$deb" != "|"; then 754 echo "$deb..." 755 dpkg-deb --extract "$deb" /mnt 756 fi 757 done 758 759 # Make the Nix store available in /mnt, because that's where the .debs live. 760 mkdir -p /mnt/inst${storeDir} 761 ${util-linux}/bin/mount -o bind ${storeDir} /mnt/inst${storeDir} 762 ${util-linux}/bin/mount -o bind /proc /mnt/proc 763 ${util-linux}/bin/mount -o bind /dev /mnt/dev 764 765 # Misc. files/directories assumed by various packages. 766 echo "initialising Dpkg DB..." 767 touch /mnt/etc/shells 768 touch /mnt/var/lib/dpkg/status 769 touch /mnt/var/lib/dpkg/available 770 touch /mnt/var/lib/dpkg/diversions 771 772 # Now install the .debs. This is basically just to register 773 # them with dpkg and to make their pre/post-install scripts 774 # run. 775 echo "installing Debs..." 776 777 export DEBIAN_FRONTEND=noninteractive 778 779 oldIFS="$IFS" 780 IFS="|" 781 for component in $debs; do 782 IFS="$oldIFS" 783 echo 784 echo ">>> INSTALLING COMPONENT: $component" 785 debs= 786 for i in $component; do 787 debs="$debs /inst/$i"; 788 done 789 chroot=$(type -tP chroot) 790 791 # Create a fake start-stop-daemon script, as done in debootstrap. 792 mv "/mnt/sbin/start-stop-daemon" "/mnt/sbin/start-stop-daemon.REAL" 793 echo "#!/bin/true" > "/mnt/sbin/start-stop-daemon" 794 chmod 755 "/mnt/sbin/start-stop-daemon" 795 796 PATH=/usr/bin:/bin:/usr/sbin:/sbin $chroot /mnt \ 797 /usr/bin/dpkg --install --force-all $debs < /dev/null || true 798 799 # Move the real start-stop-daemon back into its place. 800 mv "/mnt/sbin/start-stop-daemon.REAL" "/mnt/sbin/start-stop-daemon" 801 done 802 803 echo "running post-install script..." 804 eval "$postInstall" 805 806 rm /mnt/.debug 807 808 ${util-linux}/bin/umount /mnt/inst${storeDir} 809 ${util-linux}/bin/umount /mnt/proc 810 ${util-linux}/bin/umount /mnt/dev 811 ${util-linux}/bin/umount /mnt 812 ''; 813 814 passthru = { inherit fullName; }; 815 } 816 // args 817 ) 818 ); 819 820 /* 821 Generate a Nix expression containing fetchurl calls for the 822 closure of a set of top-level RPM packages from the 823 `primary.xml.gz' file of a Fedora or openSUSE distribution. 824 */ 825 826 rpmClosureGenerator = 827 { 828 name, 829 packagesLists, 830 urlPrefixes, 831 packages, 832 archs ? [ ], 833 }: 834 assert (builtins.length packagesLists) == (builtins.length urlPrefixes); 835 runCommand "${name}.nix" 836 { 837 nativeBuildInputs = [ 838 buildPackages.perl 839 buildPackages.perlPackages.URI 840 buildPackages.perlPackages.XMLSimple 841 buildPackages.zstd 842 ]; 843 inherit archs; 844 } 845 '' 846 ${lib.concatImapStrings (i: pl: '' 847 echo "decompressing ${pl}..." 848 case ${pl} in 849 *.zst) 850 zstd -d < ${pl} > ./packages_${toString i}.xml 851 ;; 852 *.xz | *.lzma) 853 xz -d < ${pl} > ./packages_${toString i}.xml 854 ;; 855 *.bz2) 856 bunzip2 < ${pl} > ./packages_${toString i}.xml 857 ;; 858 *.gz) 859 gunzip < ${pl} > ./packages_${toString i}.xml 860 ;; 861 *) 862 cp ${pl} ./packages_${toString i}.xml 863 ;; 864 esac 865 '') packagesLists} 866 perl -w ${rpm/rpm-closure.pl} \ 867 ${ 868 lib.concatImapStrings (i: pl: "./packages_${toString i}.xml ${pl.snd} ") ( 869 lib.zipLists packagesLists urlPrefixes 870 ) 871 } \ 872 ${toString packages} > $out 873 ''; 874 875 /* 876 Helper function that combines rpmClosureGenerator and 877 fillDiskWithRPMs to generate a disk image from a set of package 878 names. 879 */ 880 881 makeImageFromRPMDist = 882 { 883 name, 884 fullName, 885 size ? 4096, 886 urlPrefix ? "", 887 urlPrefixes ? [ urlPrefix ], 888 packagesList ? "", 889 packagesLists ? [ packagesList ], 890 packages, 891 extraPackages ? [ ], 892 preInstall ? "", 893 postInstall ? "", 894 archs ? [ 895 "noarch" 896 "i386" 897 ], 898 runScripts ? true, 899 createRootFS ? defaultCreateRootFS, 900 QEMU_OPTS ? "", 901 memSize ? 512, 902 unifiedSystemDir ? false, 903 }: 904 905 fillDiskWithRPMs { 906 inherit 907 name 908 fullName 909 size 910 preInstall 911 postInstall 912 runScripts 913 createRootFS 914 unifiedSystemDir 915 QEMU_OPTS 916 memSize 917 ; 918 rpms = import (rpmClosureGenerator { 919 inherit 920 name 921 packagesLists 922 urlPrefixes 923 archs 924 ; 925 packages = packages ++ extraPackages; 926 }) { inherit fetchurl; }; 927 }; 928 929 /* 930 Like `rpmClosureGenerator', but now for Debian/Ubuntu releases 931 (i.e. generate a closure from a Packages.bz2 file). 932 */ 933 934 debClosureGenerator = 935 { 936 name, 937 packagesLists, 938 urlPrefix, 939 packages, 940 }: 941 942 runCommand "${name}.nix" 943 { 944 nativeBuildInputs = [ 945 buildPackages.perl 946 buildPackages.dpkg 947 buildPackages.nixfmt 948 ]; 949 } 950 '' 951 for i in ${toString packagesLists}; do 952 echo "adding $i..." 953 case $i in 954 *.xz | *.lzma) 955 xz -d < $i >> ./Packages 956 ;; 957 *.bz2) 958 bunzip2 < $i >> ./Packages 959 ;; 960 *.gz) 961 gzip -dc < $i >> ./Packages 962 ;; 963 esac 964 done 965 966 perl -w ${deb/deb-closure.pl} \ 967 ./Packages ${urlPrefix} ${toString packages} > $out 968 nixfmt $out 969 ''; 970 971 /* 972 Helper function that combines debClosureGenerator and 973 fillDiskWithDebs to generate a disk image from a set of package 974 names. 975 */ 976 977 makeImageFromDebDist = 978 { 979 name, 980 fullName, 981 size ? 4096, 982 urlPrefix, 983 packagesList ? "", 984 packagesLists ? [ packagesList ], 985 packages, 986 extraPackages ? [ ], 987 postInstall ? "", 988 extraDebs ? [ ], 989 createRootFS ? defaultCreateRootFS, 990 QEMU_OPTS ? "", 991 memSize ? 512, 992 ... 993 }@args: 994 995 let 996 expr = debClosureGenerator { 997 inherit name packagesLists urlPrefix; 998 packages = packages ++ extraPackages; 999 }; 1000 in 1001 (fillDiskWithDebs ( 1002 { 1003 inherit 1004 name 1005 fullName 1006 size 1007 postInstall 1008 createRootFS 1009 QEMU_OPTS 1010 memSize 1011 ; 1012 debs = import expr { inherit fetchurl; } ++ extraDebs; 1013 } 1014 // args 1015 )) 1016 // { 1017 inherit expr; 1018 }; 1019 1020 # The set of supported RPM-based distributions. 1021 1022 rpmDistros = { 1023 fedora42x86_64 = { 1024 name = "fedora-42-x86_64"; 1025 fullName = "Fedora 42 (x86_64)"; 1026 packagesList = fetchurl { 1027 url = "https://dl.fedoraproject.org/pub/fedora/linux/releases/42/Everything/x86_64/os/repodata/cd483b35df017d68b73a878a392bbf666a43d75db54c386e4720bc369eb5c3a3-primary.xml.zst"; 1028 hash = "sha256-zUg7Nd8BfWi3OoeKOSu/ZmpD1121TDhuRyC8Np61w6M="; 1029 }; 1030 urlPrefix = "https://dl.fedoraproject.org/pub/fedora/linux/releases/42/Everything/x86_64/os"; 1031 archs = [ 1032 "noarch" 1033 "x86_64" 1034 ]; 1035 packages = commonFedoraPackages; 1036 unifiedSystemDir = true; 1037 }; 1038 1039 fedora43x86_64 = { 1040 name = "fedora-43-x86_64"; 1041 fullName = "Fedora 43 (x86_64)"; 1042 packagesList = fetchurl { 1043 url = "https://dl.fedoraproject.org/pub/fedora/linux/releases/43/Everything/x86_64/os/repodata/fffa3e9f63fffd3d21b8ea5e9bb0fe349a7ed1d4e09777a618cec93a2bcc305f-primary.xml.zst"; 1044 hash = "sha256-//o+n2P//T0huOpem7D+NJp+0dTgl3emGM7JOivMMF8="; 1045 }; 1046 urlPrefix = "https://dl.fedoraproject.org/pub/fedora/linux/releases/43/Everything/x86_64/os"; 1047 archs = [ 1048 "noarch" 1049 "x86_64" 1050 ]; 1051 packages = commonFedoraPackages ++ [ "gpgverify" ]; 1052 unifiedSystemDir = true; 1053 }; 1054 1055 # Rocky Linux's /pub/rocky/9/ URL is rolling and changes with each minor release. We use the 1056 # vault instead, which provides stable URLs for specific minor versions. 1057 rocky9x86_64 = { 1058 name = "rocky-9.6-x86_64"; 1059 fullName = "Rocky Linux 9.6 (x86_64)"; 1060 packagesLists = [ 1061 (fetchurl { 1062 url = "https://dl.rockylinux.org/vault/rocky/9.6/BaseOS/x86_64/os/repodata/9965e429a90787a87a07eed62872d046411fb7dded524b96d74c4ce1eade327a-primary.xml.gz"; 1063 hash = "sha256-mWXkKakHh6h6B+7WKHLQRkEft93tUkuW10xM4ereMno="; 1064 }) 1065 (fetchurl { 1066 url = "https://dl.rockylinux.org/vault/rocky/9.6/AppStream/x86_64/os/repodata/8cc9f795679c3365c06b6135f685ebf4188a5863a5f52f09f8cabd4f09c4dfa1-primary.xml.gz"; 1067 hash = "sha256-jMn3lWecM2XAa2E19oXr9BiKWGOl9S8J+Mq9TwnE36E="; 1068 }) 1069 ]; 1070 urlPrefixes = [ 1071 "https://dl.rockylinux.org/vault/rocky/9.6/BaseOS/x86_64/os" 1072 "https://dl.rockylinux.org/vault/rocky/9.6/AppStream/x86_64/os" 1073 ]; 1074 archs = [ 1075 "noarch" 1076 "x86_64" 1077 ]; 1078 packages = commonRockyPackages ++ [ 1079 "annobin" 1080 ]; 1081 unifiedSystemDir = true; 1082 }; 1083 1084 # Rocky Linux's /pub/rocky/10/ URL is rolling and changes with each minor release. We use the 1085 # vault instead, which provides stable URLs for specific minor versions. 1086 rocky10x86_64 = { 1087 name = "rocky-10.0-x86_64"; 1088 fullName = "Rocky Linux 10.0 (x86_64)"; 1089 packagesLists = [ 1090 (fetchurl { 1091 url = "https://dl.rockylinux.org/vault/rocky/10.0/BaseOS/x86_64/os/repodata/484d5c43cdb1058dd1328a6b891f45c85f1cb2620c528f2ef423d4b9feb9e2f0-primary.xml.gz"; 1092 hash = "sha256-SE1cQ82xBY3RMopriR9FyF8csmIMUo8u9CPUuf654vA="; 1093 }) 1094 (fetchurl { 1095 url = "https://dl.rockylinux.org/vault/rocky/10.0/AppStream/x86_64/os/repodata/32c93064142d89f3f19c11e92642c5abd8368418f7ab3f3bdd752e4afa9b5b23-primary.xml.gz"; 1096 hash = "sha256-MskwZBQtifPxnBHpJkLFq9g2hBj3qz873XUuSvqbWyM="; 1097 }) 1098 ]; 1099 urlPrefixes = [ 1100 "https://dl.rockylinux.org/vault/rocky/10.0/BaseOS/x86_64/os" 1101 "https://dl.rockylinux.org/vault/rocky/10.0/AppStream/x86_64/os" 1102 ]; 1103 archs = [ 1104 "noarch" 1105 "x86_64" 1106 ]; 1107 packages = commonRockyPackages ++ [ 1108 "annobin-plugin-gcc" 1109 ]; 1110 unifiedSystemDir = true; 1111 }; 1112 1113 # AlmaLinux's repo.almalinux.org URLs are rolling and change with each minor release. 1114 # We use vault.almalinux.org instead, which provides stable URLs for specific versions. 1115 alma9x86_64 = { 1116 name = "alma-9.6-x86_64"; 1117 fullName = "AlmaLinux 9.6 (x86_64)"; 1118 packagesLists = [ 1119 (fetchurl { 1120 url = "https://vault.almalinux.org/9.6/BaseOS/x86_64/os/repodata/26d6cf944c86ef850773e61919e892a375ff10bb2254003e1d71673db9900b07-primary.xml.gz"; 1121 hash = "sha256-JtbPlEyG74UHc+YZGeiSo3X/ELsiVAA+HXFnPbmQCwc="; 1122 }) 1123 (fetchurl { 1124 url = "https://vault.almalinux.org/9.6/AppStream/x86_64/os/repodata/afb5d18b78d819d826d3d0e32ba439da7b9e0fd91d726dd833366496b1b8ca20-primary.xml.gz"; 1125 hash = "sha256-r7XRi3jYGdgm09DjK6Q52nueD9kdcm3YMzZklrG4yiA="; 1126 }) 1127 ]; 1128 urlPrefixes = [ 1129 "https://vault.almalinux.org/9.6/BaseOS/x86_64/os" 1130 "https://vault.almalinux.org/9.6/AppStream/x86_64/os" 1131 ]; 1132 archs = [ 1133 "noarch" 1134 "x86_64" 1135 ]; 1136 packages = commonAlmaPackages ++ [ 1137 "annobin" 1138 ]; 1139 unifiedSystemDir = true; 1140 }; 1141 1142 alma10x86_64 = { 1143 name = "alma-10.0-x86_64"; 1144 fullName = "AlmaLinux 10.0 (x86_64)"; 1145 packagesLists = [ 1146 (fetchurl { 1147 url = "https://vault.almalinux.org/10.0/BaseOS/x86_64/os/repodata/4d88695fa7ccb6298897fa9682ac1ded4628df342ffe08312846225e4469e3e4-primary.xml.gz"; 1148 hash = "sha256-TYhpX6fMtimIl/qWgqwd7UYo3zQv/ggxKEYiXkRp4+Q="; 1149 }) 1150 (fetchurl { 1151 url = "https://vault.almalinux.org/10.0/AppStream/x86_64/os/repodata/11ac32065bae6f2c2451803458690fc550e79f93a4ea9f438930f0c228964791-primary.xml.gz"; 1152 hash = "sha256-EawyBluubywkUYA0WGkPxVDnn5Ok6p9DiTDwwiiWR5E="; 1153 }) 1154 ]; 1155 urlPrefixes = [ 1156 "https://vault.almalinux.org/10.0/BaseOS/x86_64/os" 1157 "https://vault.almalinux.org/10.0/AppStream/x86_64/os" 1158 ]; 1159 archs = [ 1160 "noarch" 1161 "x86_64" 1162 ]; 1163 packages = commonAlmaPackages ++ [ 1164 "annobin-plugin-gcc" 1165 ]; 1166 unifiedSystemDir = true; 1167 }; 1168 1169 # Oracle provides versioned URLs for baseos (e.g., OL9/7/baseos/base/) but not for appstream. 1170 # We can't mix versioned baseos with rolling appstream due to package version dependencies, 1171 # so we use rolling URLs for both. These may need hash updates when Oracle releases new versions. 1172 oracle9x86_64 = { 1173 name = "oracle-9-x86_64"; 1174 fullName = "Oracle Linux 9 (x86_64)"; 1175 packagesLists = [ 1176 (fetchurl { 1177 url = "https://yum.oracle.com/repo/OracleLinux/OL9/baseos/latest/x86_64/repodata/bc292d67f73fc606db1872d5ba8804da06a514efe64523247035f0d3b678fb63-primary.xml.gz"; 1178 hash = "sha256-vCktZ/c/xgbbGHLVuogE2galFO/mRSMkcDXw07Z4+2M="; 1179 }) 1180 (fetchurl { 1181 url = "https://yum.oracle.com/repo/OracleLinux/OL9/appstream/x86_64/repodata/6fabacadf7cdf22cbb21dc296f58e6b852d5b8ec9a927e214231477ef90083f9-primary.xml.gz"; 1182 hash = "sha256-b6usrffN8iy7Idwpb1jmuFLVuOyakn4hQjFHfvkAg/k="; 1183 }) 1184 ]; 1185 urlPrefixes = [ 1186 "https://yum.oracle.com/repo/OracleLinux/OL9/baseos/latest/x86_64" 1187 "https://yum.oracle.com/repo/OracleLinux/OL9/appstream/x86_64" 1188 ]; 1189 archs = [ 1190 "noarch" 1191 "x86_64" 1192 ]; 1193 packages = commonOraclePackages ++ [ 1194 "annobin" 1195 ]; 1196 unifiedSystemDir = true; 1197 }; 1198 1199 # Amazon Linux 2023 uses GUID-based URLs that don't allow directory listing. 1200 # To update: The GUID corresponds to a specific AL2023 release version. You can find the 1201 # current GUID by either: 1202 # 1. Running an AL2023 container: `docker run -it amazonlinux:2023 dnf repolist -v` 1203 # and extracting the GUID from the Repo-baseurl field 1204 # 2. Checking https://github.com/docker-library/repo-info/blob/master/repos/amazonlinux/local/latest.md 1205 # which tracks the repository URLs from the official Docker image 1206 # Release notes: https://docs.aws.amazon.com/linux/al2023/release-notes/relnotes.html 1207 amazon2023x86_64 = { 1208 name = "amazon-2023-x86_64"; 1209 fullName = "Amazon Linux 2023 (x86_64)"; 1210 packagesList = fetchurl { 1211 url = "https://cdn.amazonlinux.com/al2023/core/guids/6fa961924efb4835a7e8de43c89726dca28a5cf5906f891262d8f78a31ea3aaf/x86_64/repodata/primary.xml.gz"; 1212 hash = "sha256-Ezdsc8a2aOIbyXvQ/nyanWe1fl089VgtfegaPcu2oo4="; 1213 }; 1214 urlPrefix = "https://cdn.amazonlinux.com/al2023/core/guids/6fa961924efb4835a7e8de43c89726dca28a5cf5906f891262d8f78a31ea3aaf/x86_64"; 1215 archs = [ 1216 "noarch" 1217 "x86_64" 1218 ]; 1219 packages = commonAmazonPackages ++ [ 1220 "annobin-plugin-gcc" 1221 ]; 1222 unifiedSystemDir = true; 1223 }; 1224 1225 }; 1226 1227 # The set of supported Dpkg-based distributions. 1228 1229 debDistros = { 1230 # Ubuntu's snapshot service returns the same data for 22.04 regardless of the timestamp in the 1231 # URL. The hashes don't change between mirror://ubuntu and snapshot.ubuntu.com, so this is fine. 1232 ubuntu2204i386 = { 1233 name = "ubuntu-22.04-jammy-i386"; 1234 fullName = "Ubuntu 22.04 Jammy (i386)"; 1235 packagesLists = [ 1236 (fetchurl { 1237 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy/main/binary-i386/Packages.xz"; 1238 hash = "sha256-iZBmwT0ep4v+V3sayybbOgZBOFFZwPGpOKtmuLMMVPQ="; 1239 }) 1240 (fetchurl { 1241 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy/universe/binary-i386/Packages.xz"; 1242 hash = "sha256-DO2LdpZ9rDDBhWj2gvDWd0TJJVZHxKsYTKTi6GXjm1E="; 1243 }) 1244 (fetchurl { 1245 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-updates/main/binary-i386/Packages.xz"; 1246 hash = "sha256-g95BtOoMxacZEHMBbcMes4a1P9HKf/QGOMOPr+OKayo="; 1247 }) 1248 (fetchurl { 1249 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-updates/universe/binary-i386/Packages.xz"; 1250 hash = "sha256-VbazaDDJKSUyQchGmw5f+FYAr4PIXWZJSBF0WVC5j+0="; 1251 }) 1252 (fetchurl { 1253 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-security/main/binary-i386/Packages.xz"; 1254 hash = "sha256-SkP4PqjUAbEMtktR5WQm/3jQl9O0T2VOVTP9QIYIVkQ="; 1255 }) 1256 (fetchurl { 1257 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-security/universe/binary-i386/Packages.xz"; 1258 hash = "sha256-citjk8LAGSRlXgOXgf3oe9vBCUC6/DJGhRJl/3ppN9c="; 1259 }) 1260 ]; 1261 urlPrefix = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z"; 1262 packages = commonDebPackages ++ [ 1263 "diffutils" 1264 "libc-bin" 1265 ]; 1266 }; 1267 1268 ubuntu2204x86_64 = { 1269 name = "ubuntu-22.04-jammy-amd64"; 1270 fullName = "Ubuntu 22.04 Jammy (amd64)"; 1271 packagesLists = [ 1272 (fetchurl { 1273 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy/main/binary-amd64/Packages.xz"; 1274 hash = "sha256-N8tX8VVMv6ccWinun/7hipqMF4K7BWjgh0t/9M6PnBE="; 1275 }) 1276 (fetchurl { 1277 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy/universe/binary-amd64/Packages.xz"; 1278 hash = "sha256-0pyyTJP+xfQyVXBrzn60bUd5lSA52MaKwbsUpvNlXOI="; 1279 }) 1280 (fetchurl { 1281 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-updates/main/binary-amd64/Packages.xz"; 1282 hash = "sha256-I57YuLZ458RljXfp1xFxqQLGNJh9uu8kQC0hc88XZro="; 1283 }) 1284 (fetchurl { 1285 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-updates/universe/binary-amd64/Packages.xz"; 1286 hash = "sha256-ZXobWMi7tkakZ89GoyKpiRhRxMRXud0DOerSfzz5CPE="; 1287 }) 1288 (fetchurl { 1289 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-security/main/binary-amd64/Packages.xz"; 1290 hash = "sha256-cifTPY1iyckkaLd7dp+VPRlF0viWKrWXhM8HVWaMuUw="; 1291 }) 1292 (fetchurl { 1293 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/jammy-security/universe/binary-amd64/Packages.xz"; 1294 hash = "sha256-LTSOGbzkv0KrF2JM6oVT1Ml2KQkySXMbKNMBb9AyfQM="; 1295 }) 1296 ]; 1297 urlPrefix = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z"; 1298 packages = commonDebPackages ++ [ 1299 "diffutils" 1300 "libc-bin" 1301 ]; 1302 }; 1303 1304 ubuntu2404x86_64 = { 1305 name = "ubuntu-24.04-noble-amd64"; 1306 fullName = "Ubuntu 24.04 Noble (amd64)"; 1307 packagesLists = [ 1308 (fetchurl { 1309 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/noble/main/binary-amd64/Packages.xz"; 1310 hash = "sha256-KmoZnhAxpcJ5yzRmRtWUmT81scA91KgqqgMjmA3ZJFE="; 1311 }) 1312 (fetchurl { 1313 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/noble/universe/binary-amd64/Packages.xz"; 1314 hash = "sha256-upBX+huRQ4zIodJoCNAMhTif4QHQwUliVN+XI2QFWZo="; 1315 }) 1316 (fetchurl { 1317 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/noble-updates/main/binary-amd64/Packages.xz"; 1318 hash = "sha256-leBJ29a2C2qdIPdjSSuwkHKUSq8GEC9L0DgdxHWZ55s="; 1319 }) 1320 (fetchurl { 1321 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/noble-updates/universe/binary-amd64/Packages.xz"; 1322 hash = "sha256-CWYA0A4ytptWdClW3ACdIH4hKscblDh5OgxExP4VdJA="; 1323 }) 1324 (fetchurl { 1325 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/noble-security/main/binary-amd64/Packages.xz"; 1326 hash = "sha256-TYs8ugCYqzOleH2OebdrpB8E68PfxB+7sRb+PlfANEo="; 1327 }) 1328 (fetchurl { 1329 url = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z/dists/noble-security/universe/binary-amd64/Packages.xz"; 1330 hash = "sha256-bK9R8CUjLQ1V4GP7/KqZooSnKHF5+T5SuBs0butC82M="; 1331 }) 1332 ]; 1333 urlPrefix = "https://snapshot.ubuntu.com/ubuntu/20260101T000000Z"; 1334 packages = commonDebPackages ++ [ 1335 "diffutils" 1336 "libc-bin" 1337 ]; 1338 }; 1339 1340 debian11i386 = { 1341 name = "debian-11.11-bullseye-i386"; 1342 fullName = "Debian 11.11 Bullseye (i386)"; 1343 packagesList = fetchurl { 1344 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/bullseye/main/binary-i386/Packages.xz"; 1345 hash = "sha256-kUg1VBUO6co/5bKloxncta49191oCeF05Hm399+UuDA="; 1346 }; 1347 urlPrefix = "https://snapshot.debian.org/archive/debian/20260105T082626Z"; 1348 packages = commonDebianPackages; 1349 }; 1350 1351 debian11x86_64 = { 1352 name = "debian-11.11-bullseye-amd64"; 1353 fullName = "Debian 11.11 Bullseye (amd64)"; 1354 packagesList = fetchurl { 1355 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/bullseye/main/binary-amd64/Packages.xz"; 1356 hash = "sha256-HDQFREKX6thkcRwY5kvOSBDbY7SDQKL52BGC2fI1rXE="; 1357 }; 1358 urlPrefix = "https://snapshot.debian.org/archive/debian/20260105T082626Z"; 1359 packages = commonDebianPackages; 1360 }; 1361 1362 debian12i386 = { 1363 name = "debian-12.12-bookworm-i386"; 1364 fullName = "Debian 12.12 Bookworm (i386)"; 1365 packagesLists = [ 1366 (fetchurl { 1367 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/bookworm/main/binary-i386/Packages.xz"; 1368 hash = "sha256-nIijsNoHUYkrL6eiwN4FCLHnJy/Bv/RMvnbMIHvieVI="; 1369 }) 1370 (fetchurl { 1371 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/bookworm-backports/main/binary-i386/Packages.xz"; 1372 hash = "sha256-/ja7+DNIKc2ZUIXiocTjLbaD2EPsfeyZcd5ndEMapp4="; 1373 }) 1374 ]; 1375 urlPrefix = "https://snapshot.debian.org/archive/debian/20260105T082626Z"; 1376 packages = commonDebianPackages; 1377 }; 1378 1379 debian12x86_64 = { 1380 name = "debian-12.12-bookworm-amd64"; 1381 fullName = "Debian 12.12 Bookworm (amd64)"; 1382 packagesLists = [ 1383 (fetchurl { 1384 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/bookworm/main/binary-amd64/Packages.xz"; 1385 hash = "sha256-PfjQeu3tXmXZhH7foSD6WyFrvY4PfwSN/v5pBeShIBE="; 1386 }) 1387 (fetchurl { 1388 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/bookworm-backports/main/binary-amd64/Packages.xz"; 1389 hash = "sha256-S3NSvw1kX2zxzMh+WYhY58VUR7iLrTEIuXwwSK6itIs="; 1390 }) 1391 ]; 1392 urlPrefix = "https://snapshot.debian.org/archive/debian/20260105T082626Z"; 1393 packages = commonDebianPackages; 1394 }; 1395 1396 debian13i386 = { 1397 name = "debian-13.2-trixie-i386"; 1398 fullName = "Debian 13.2 Trixie (i386)"; 1399 packagesLists = [ 1400 (fetchurl { 1401 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/trixie/main/binary-i386/Packages.xz"; 1402 hash = "sha256-9zozvFZoWiv3wNe9rb+kPwSOgc5G5f4zmNpdoet5A78="; 1403 }) 1404 (fetchurl { 1405 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/trixie-backports/main/binary-i386/Packages.xz"; 1406 hash = "sha256-hEBAQ73Jnv8zp9YvNXWLEObyrSlQNBNBj/XoofJL7eI="; 1407 }) 1408 ]; 1409 urlPrefix = "https://snapshot.debian.org/archive/debian/20260105T082626Z"; 1410 packages = commonDebianPackages; 1411 }; 1412 1413 debian13x86_64 = { 1414 name = "debian-13.2-trixie-amd64"; 1415 fullName = "Debian 13.2 Trixie (amd64)"; 1416 packagesLists = [ 1417 (fetchurl { 1418 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/trixie/main/binary-amd64/Packages.xz"; 1419 hash = "sha256-g7f+tKljUXAC4gxJfzSC8+j0GbiwRZjonv25tYuvxtU="; 1420 }) 1421 (fetchurl { 1422 url = "https://snapshot.debian.org/archive/debian/20260105T082626Z/dists/trixie-backports/main/binary-amd64/Packages.xz"; 1423 hash = "sha256-9OoR36FsyK7MQMLHLFMRJ9O11WKq9JCfGwnprpztxNw="; 1424 }) 1425 ]; 1426 urlPrefix = "https://snapshot.debian.org/archive/debian/20260105T082626Z"; 1427 packages = commonDebianPackages; 1428 }; 1429 }; 1430 1431 # Base packages for all RHEL-family distros (Fedora, Rocky, Alma, etc.) 1432 baseRHELFamilyPackages = [ 1433 "autoconf" 1434 "automake" 1435 "basesystem" 1436 "bzip2" 1437 "curl" 1438 "diffutils" 1439 "findutils" 1440 "gawk" 1441 "gcc-c++" 1442 "glibc-gconv-extra" 1443 "gzip" 1444 "make" 1445 "patch" 1446 "perl" 1447 "rpm" 1448 "rpm-build" 1449 "tar" 1450 "unzip" 1451 ]; 1452 1453 commonFedoraPackages = baseRHELFamilyPackages ++ [ 1454 "annobin-plugin-gcc" 1455 "fedora-release" 1456 "gcc-plugin-annobin" 1457 "pkgconf-pkg-config" 1458 ]; 1459 1460 commonRockyPackages = baseRHELFamilyPackages ++ [ 1461 "gcc-plugin-annobin" 1462 "pkgconf" 1463 "rocky-release" 1464 ]; 1465 1466 commonAlmaPackages = baseRHELFamilyPackages ++ [ 1467 "almalinux-release" 1468 "gcc-plugin-annobin" 1469 "pkgconf" 1470 ]; 1471 1472 commonOraclePackages = baseRHELFamilyPackages ++ [ 1473 "gcc-plugin-annobin" 1474 "oraclelinux-release" 1475 "pkgconf" 1476 ]; 1477 1478 commonAmazonPackages = baseRHELFamilyPackages ++ [ 1479 "gcc-plugin-annobin" 1480 "pkgconf" 1481 "system-release" 1482 ]; 1483 1484 # Common packages for openSUSE images. 1485 commonOpenSUSEPackages = [ 1486 "aaa_base" 1487 "autoconf" 1488 "automake" 1489 "bzip2" 1490 "curl" 1491 "diffutils" 1492 "findutils" 1493 "gawk" 1494 "gcc-c++" 1495 "gzip" 1496 "make" 1497 "patch" 1498 "perl" 1499 "pkg-config" 1500 "rpm" 1501 "tar" 1502 "unzip" 1503 "util-linux" 1504 "gnu-getopt" 1505 ]; 1506 1507 # Common packages for Debian/Ubuntu images. 1508 commonDebPackages = [ 1509 "base-passwd" 1510 "dpkg" 1511 "libc6-dev" 1512 "perl" 1513 "bash" 1514 "dash" 1515 "gzip" 1516 "bzip2" 1517 "tar" 1518 "grep" 1519 "mawk" 1520 "sed" 1521 "findutils" 1522 "g++" 1523 "make" 1524 "curl" 1525 "patch" 1526 "locales" 1527 "coreutils" 1528 # Needed by checkinstall: 1529 "util-linux" 1530 "file" 1531 "dpkg-dev" 1532 "pkg-config" 1533 # Needed because it provides /etc/login.defs, whose absence causes 1534 # the "passwd" post-installs script to fail. 1535 "login" 1536 "passwd" 1537 ]; 1538 1539 commonDebianPackages = commonDebPackages ++ [ 1540 "sysvinit" 1541 "diff" 1542 ]; 1543 1544 /* 1545 A set of functions that build the Linux distributions specified 1546 in `rpmDistros' and `debDistros'. For instance, 1547 `diskImageFuns.ubuntu1004x86_64 { }' builds an Ubuntu 10.04 disk 1548 image containing the default packages specified above. Overrides 1549 of the default image parameters can be given. In particular, 1550 `extraPackages' specifies the names of additional packages from 1551 the distribution that should be included in the image; `packages' 1552 allows the entire set of packages to be overridden; and `size' 1553 sets the size of the disk in MiB (1024*1024 bytes). E.g., 1554 `diskImageFuns.ubuntu1004x86_64 { extraPackages = ["firefox"]; 1555 size = 8192; }' builds an 8 GiB image containing Firefox in 1556 addition to the default packages. 1557 */ 1558 diskImageFuns = 1559 (lib.mapAttrs ( 1560 name: as: as2: 1561 makeImageFromRPMDist (as // as2) 1562 ) rpmDistros) 1563 // (lib.mapAttrs ( 1564 name: as: as2: 1565 makeImageFromDebDist (as // as2) 1566 ) debDistros); 1567 1568 # Shorthand for `diskImageFuns.<attr> { extraPackages = ... }'. 1569 diskImageExtraFuns = lib.mapAttrs ( 1570 name: f: extraPackages: 1571 f { inherit extraPackages; } 1572 ) diskImageFuns; 1573 1574 /* 1575 Default disk images generated from the `rpmDistros' and 1576 `debDistros' sets. 1577 */ 1578 diskImages = lib.mapAttrs (name: f: f { }) diskImageFuns; 1579in 1580{ 1581 inherit 1582 buildRPM 1583 commonDebPackages 1584 commonDebianPackages 1585 commonFedoraPackages 1586 commonOpenSUSEPackages 1587 createEmptyImage 1588 debClosureGenerator 1589 debDistros 1590 defaultCreateRootFS 1591 diskImageExtraFuns 1592 diskImageFuns 1593 diskImages 1594 extractFs 1595 extractMTDfs 1596 fillDiskWithDebs 1597 fillDiskWithRPMs 1598 hd 1599 initrd 1600 initrdUtils 1601 makeImageFromDebDist 1602 makeImageFromRPMDist 1603 makeImageTestScript 1604 modulesClosure 1605 qemu 1606 qemuCommandLinux 1607 rpmClosureGenerator 1608 rpmDistros 1609 runInLinuxImage 1610 runInLinuxVM 1611 stage1Init 1612 stage2Init 1613 vmRunCommand 1614 ; 1615}