diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 2bf64b3a1986..e19d9f17cfb7 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -238,3 +238,6 @@ e0fe216f4912dd88a021d12a44155fd2cfeb31c8 # nixos/movim: format with nixfmt-rfc-style 43c1654cae47cbf987cb63758c06245fa95c1e3b + +# nixos/iso-image.nix: nixfmt +da9a092c34cef6947d7aee2b134f61df45171631 diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix index 81d59f55db7c..eda704381db0 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-gnome.nix @@ -1,11 +1,11 @@ # This module defines a NixOS installation CD that contains GNOME. -{ pkgs, ... }: +{ lib, pkgs, ... }: { imports = [ ./installation-cd-graphical-calamares.nix ]; - isoImage.edition = "gnome"; + isoImage.edition = lib.mkDefault "gnome"; services.xserver.desktopManager.gnome = { # Add Firefox and other tools useful for installation to the launcher diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix index c322efb683d6..a8a30ca42b52 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma5.nix @@ -1,12 +1,12 @@ # This module defines a NixOS installation CD that contains X11 and # Plasma 5. -{ pkgs, ... }: +{ lib, pkgs, ... }: { imports = [ ./installation-cd-graphical-calamares.nix ]; - isoImage.edition = "plasma5"; + isoImage.edition = lib.mkDefault "plasma5"; services.xserver.desktopManager.plasma5 = { enable = true; diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma6.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma6.nix index e420300e4166..f71a624156cd 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma6.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma6.nix @@ -1,11 +1,11 @@ # This module defines a NixOS installation CD that contains Plasma 6. -{ pkgs, ... }: +{ lib, pkgs, ... }: { imports = [ ./installation-cd-graphical-calamares.nix ]; - isoImage.edition = "plasma6"; + isoImage.edition = lib.mkDefault "plasma6"; services.desktopManager.plasma6.enable = true; diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-combined.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-combined.nix new file mode 100644 index 000000000000..832b775ad8bd --- /dev/null +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-combined.nix @@ -0,0 +1,52 @@ +# This configuration uses a specialisation for each desired boot +# configuration, and a common parent configuration for all of them +# that's hidden. This allows users to import this module alongside +# their own and get the full array of specialisations inheriting the +# users' settings. + +{ lib, ... }: +{ + imports = [ ./installation-cd-base.nix ]; + isoImage.edition = "graphical"; + isoImage.showConfiguration = lib.mkDefault false; + + specialisation = { + gnome.configuration = + { config, ... }: + { + imports = [ ./installation-cd-graphical-calamares-gnome.nix ]; + isoImage.showConfiguration = true; + isoImage.configurationName = "GNOME (Linux LTS)"; + }; + + gnome_latest_kernel.configuration = + { config, ... }: + { + imports = [ + ./installation-cd-graphical-calamares-gnome.nix + ./latest-kernel.nix + ]; + isoImage.showConfiguration = true; + isoImage.configurationName = "GNOME (Linux ${config.boot.kernelPackages.kernel.version})"; + }; + + plasma.configuration = + { config, ... }: + { + imports = [ ./installation-cd-graphical-calamares-plasma6.nix ]; + isoImage.showConfiguration = true; + isoImage.configurationName = "Plasma (Linux LTS)"; + }; + + plasma_latest_kernel.configuration = + { config, ... }: + { + imports = [ + ./installation-cd-graphical-calamares-plasma6.nix + ./latest-kernel.nix + ]; + isoImage.showConfiguration = true; + isoImage.configurationName = "Plasma (Linux ${config.boot.kernelPackages.kernel.version})"; + }; + }; +} diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix index b3c605e3f94d..7b355b191455 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix @@ -1,11 +1,11 @@ # This module defines a NixOS installation CD that contains GNOME. -{ ... }: +{ lib, ... }: { imports = [ ./installation-cd-graphical-base.nix ]; - isoImage.edition = "gnome"; + isoImage.edition = lib.mkDefault "gnome"; services.xserver.desktopManager.gnome = { # Add Firefox and other tools useful for installation to the launcher diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix index 4f7b7d4b2bf9..f41d34c65e79 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix @@ -1,12 +1,12 @@ # This module defines a NixOS installation CD that contains X11 and # Plasma 5. -{ pkgs, ... }: +{ lib, pkgs, ... }: { imports = [ ./installation-cd-graphical-base.nix ]; - isoImage.edition = "plasma5"; + isoImage.edition = lib.mkDefault "plasma5"; services.xserver.desktopManager.plasma5 = { enable = true; diff --git a/nixos/modules/installer/cd-dvd/installation-cd-minimal-combined.nix b/nixos/modules/installer/cd-dvd/installation-cd-minimal-combined.nix new file mode 100644 index 000000000000..38f70d0c44f8 --- /dev/null +++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal-combined.nix @@ -0,0 +1,14 @@ +{ lib, ... }: + +{ + imports = [ ./installation-cd-minimal.nix ]; + + isoImage.configurationName = lib.mkDefault "(Linux LTS)"; + + specialisation.latest_kernel.configuration = + { config, ... }: + { + imports = [ ./latest-kernel.nix ]; + isoImage.configurationName = "(Linux ${config.boot.kernelPackages.kernel.version})"; + }; +} diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 442e82d76916..35afdc3a3f76 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -1,88 +1,133 @@ # This module creates a bootable ISO image containing the given NixOS # configuration. The derivation for the ISO image will be placed in # config.system.build.isoImage. -{ config, lib, pkgs, ... }: +{ + config, + lib, + pkgs, + ... +}: let - /** - * Given a list of `options`, concats the result of mapping each options - * to a menuentry for use in grub. - * - * * defaults: {name, image, params, initrd} - * * options: [ option... ] - * * option: {name, params, class} - */ + # Builds a single menu entry menuBuilderGrub2 = - defaults: options: lib.concatStrings - ( - map - (option: '' - menuentry '${defaults.name} ${ - # Name appended to menuentry defaults to params if no specific name given. - option.name or (lib.optionalString (option ? params) "(${option.params})") - }' ${lib.optionalString (option ? class) " --class ${option.class}"} { - # Fallback to UEFI console for boot, efifb sometimes has difficulties. - terminal_output console + { + name, + class, + image, + params, + initrd, + }: + '' + menuentry '${name}' --class ${class} { + # Fallback to UEFI console for boot, efifb sometimes has difficulties. + terminal_output console - linux ${defaults.image} \''${isoboot} ${defaults.params} ${ - option.params or "" + linux ${image} \''${isoboot} ${params} + initrd ${initrd} + } + ''; + + # Builds all menu entries + buildMenuGrub2 = + { + cfg ? config, + params ? [ ], + }: + let + menuConfig = { + name = lib.concatStrings [ + cfg.isoImage.prependToMenuLabel + cfg.system.nixos.distroName + " " + cfg.system.nixos.label + cfg.isoImage.appendToMenuLabel + (lib.optionalString (cfg.isoImage.configurationName != null) (" " + cfg.isoImage.configurationName)) + ]; + params = "init=${cfg.system.build.toplevel}/init ${toString cfg.boot.kernelParams} ${toString params}"; + image = "/boot/${cfg.boot.kernelPackages.kernel + "/" + cfg.system.boot.loader.kernelFile}"; + initrd = "/boot/${cfg.system.build.initialRamdisk + "/" + cfg.system.boot.loader.initrdFile}"; + class = "installer"; + }; + in + '' + ${lib.optionalString cfg.isoImage.showConfiguration (menuBuilderGrub2 menuConfig)} + ${lib.concatStringsSep "\n" ( + lib.mapAttrsToList ( + specName: + { configuration, ... }: + buildMenuGrub2 { + cfg = configuration; + inherit params; } - initrd ${defaults.initrd} - } - '') - options - ) - ; + ) cfg.specialisation + )} + ''; - /** - * Builds the default options. - */ - buildMenuGrub2 = buildMenuAdditionalParamsGrub2 ""; - - targetArch = - if config.boot.loader.grub.forcei686 then - "ia32" - else - pkgs.stdenv.hostPlatform.efiArch; - - /** - * Given params to add to `params`, build a set of default options. - * Use this one when creating a variant (e.g. hidpi) - */ - buildMenuAdditionalParamsGrub2 = additional: - let - finalCfg = { - name = "${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}"; - params = "init=${config.system.build.toplevel}/init ${additional} ${toString config.boot.kernelParams}"; - image = "/boot/${config.system.boot.loader.kernelFile}"; - initrd = "/boot/initrd"; - }; - - in - menuBuilderGrub2 - finalCfg - [ - { class = "installer"; } - { class = "nomodeset"; params = "nomodeset"; } - { class = "copytoram"; params = "copytoram"; } - { class = "debug"; params = "debug"; } - ] - ; + targetArch = if config.boot.loader.grub.forcei686 then "ia32" else pkgs.stdenv.hostPlatform.efiArch; # Timeout in syslinux is in units of 1/10 of a second. # null means max timeout (35996, just under 1h in 1/10 seconds) # 0 means disable timeout - syslinuxTimeout = if config.boot.loader.timeout == null then - 35996 - else - config.boot.loader.timeout * 10; + syslinuxTimeout = + if config.boot.loader.timeout == null then 35996 else config.boot.loader.timeout * 10; # Timeout in grub is in seconds. # null means max timeout (infinity) # 0 means disable timeout - grubEfiTimeout = if config.boot.loader.timeout == null then - -1 - else - config.boot.loader.timeout; + grubEfiTimeout = if config.boot.loader.timeout == null then -1 else config.boot.loader.timeout; + + optionsSubMenus = [ + { + title = "Copy ISO Files to RAM"; + class = "copytoram"; + params = [ "copytoram" ]; + } + { + title = "No modesetting"; + class = "nomodeset"; + params = [ "nomodeset" ]; + } + { + title = "Debug Console Output"; + class = "debug"; + params = [ "debug" ]; + } + # If we boot into a graphical environment where X is autoran + # and always crashes, it makes the media unusable. Allow the user + # to disable this. + { + title = "Disable display-manager"; + class = "quirk-disable-displaymanager"; + params = [ + "systemd.mask=display-manager.service" + "plymouth.enable=0" + ]; + } + # Some laptop and convertibles have the panel installed in an + # inconvenient way, rotated away from the keyboard. + # Those entries makes it easier to use the installer. + { + title = "Rotate framebuffer Clockwise"; + class = "rotate-90cw"; + params = [ "fbcon=rotate:1" ]; + } + { + title = "Rotate framebuffer Upside-Down"; + class = "rotate-180"; + params = [ "fbcon=rotate:2" ]; + } + { + title = "Rotate framebuffer Counter-Clockwise"; + class = "rotate-90ccw"; + params = [ "fbcon=rotate:3" ]; + } + # Serial access is a must! + { + title = "Serial console=ttyS0,115200n8"; + class = "serial"; + params = [ "console=ttyS0,115200n8" ]; + } + ]; # The configuration file for syslinux. @@ -97,6 +142,35 @@ let # * COM32 entries (chainload, reboot, poweroff) are not recognized. They # result in incorrect boot entries. + menuBuilderIsolinux = + { + cfg ? config, + label, + params ? [ ], + }: + '' + ${lib.optionalString cfg.isoImage.showConfiguration '' + LABEL ${label} + MENU LABEL ${cfg.isoImage.prependToMenuLabel}${cfg.system.nixos.distroName} ${cfg.system.nixos.label}${cfg.isoImage.appendToMenuLabel}${ + lib.optionalString (cfg.isoImage.configurationName != null) (" " + cfg.isoImage.configurationName) + } + LINUX /boot/${cfg.boot.kernelPackages.kernel + "/" + cfg.system.boot.loader.kernelFile} + APPEND init=${cfg.system.build.toplevel}/init ${toString cfg.boot.kernelParams} ${toString params} + INITRD /boot/${cfg.system.build.initialRamdisk + "/" + cfg.system.boot.loader.initrdFile} + ''} + + ${lib.concatStringsSep "\n\n" ( + lib.mapAttrsToList ( + name: specCfg: + menuBuilderIsolinux { + cfg = specCfg.configuration; + label = "${label}-${name}"; + inherit params; + } + ) cfg.specialisation + )} + ''; + baseIsolinuxCfg = '' SERIAL 0 115200 TIMEOUT ${builtins.toString syslinuxTimeout} @@ -107,39 +181,27 @@ let DEFAULT boot - LABEL boot - MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} - LINUX /boot/${config.system.boot.loader.kernelFile} - APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} - INITRD /boot/${config.system.boot.loader.initrdFile} + ${menuBuilderIsolinux { label = "boot"; }} - # A variant to boot with 'nomodeset' - LABEL boot-nomodeset - MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (nomodeset) - LINUX /boot/${config.system.boot.loader.kernelFile} - APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset - INITRD /boot/${config.system.boot.loader.initrdFile} + MENU BEGIN Options - # A variant to boot with 'copytoram' - LABEL boot-copytoram - MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (copytoram) - LINUX /boot/${config.system.boot.loader.kernelFile} - APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram - INITRD /boot/${config.system.boot.loader.initrdFile} + ${lib.concatMapStringsSep "\n" ( + { + title, + class, + params, + }: + '' + MENU BEGIN ${title} + ${menuBuilderIsolinux { + label = "boot-${class}"; + inherit params; + }} + MENU END + '' + ) optionsSubMenus} - # A variant to boot with verbose logging to the console - LABEL boot-debug - MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug) - LINUX /boot/${config.system.boot.loader.kernelFile} - APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7 - INITRD /boot/${config.system.boot.loader.initrdFile} - - # A variant to boot with a serial console enabled - LABEL boot-serial - MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (serial console=ttyS0,115200n8) - LINUX /boot/${config.system.boot.loader.kernelFile} - APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} console=ttyS0,115200n8 - INITRD /boot/${config.system.boot.loader.initrdFile} + MENU END ''; isolinuxMemtest86Entry = '' @@ -149,25 +211,28 @@ let APPEND ${toString config.boot.loader.grub.memtest86.params} ''; - isolinuxCfg = lib.concatStringsSep "\n" - ([ baseIsolinuxCfg ] ++ lib.optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry); + isolinuxCfg = lib.concatStringsSep "\n" ( + [ baseIsolinuxCfg ] ++ lib.optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry + ); - refindBinary = if targetArch == "x64" || targetArch == "aa64" then "refind_${targetArch}.efi" else null; + refindBinary = + if targetArch == "x64" || targetArch == "aa64" then "refind_${targetArch}.efi" else null; # Setup instructions for rEFInd. refind = if refindBinary != null then '' - # Adds rEFInd to the ISO. - cp -v ${pkgs.refind}/share/refind/${refindBinary} $out/EFI/BOOT/ + # Adds rEFInd to the ISO. + cp -v ${pkgs.refind}/share/refind/${refindBinary} $out/EFI/BOOT/ '' else - "# No refind for ${targetArch}" - ; + "# No refind for ${targetArch}"; grubPkgs = if config.boot.loader.grub.forcei686 then pkgs.pkgsi686Linux else pkgs; grubMenuCfg = '' + set textmode=${lib.boolToString (config.isoImage.forceTextMode)} + # # Menu configuration # @@ -178,23 +243,25 @@ let insmod gfxterm insmod png set gfxpayload=keep - set gfxmode=${lib.concatStringsSep "," [ - # GRUB will use the first valid mode listed here. - # `auto` will sometimes choose the smallest valid mode it detects. - # So instead we'll list a lot of possibly valid modes :/ - #"3840x2160" - #"2560x1440" - "1920x1200" - "1920x1080" - "1366x768" - "1280x800" - "1280x720" - "1200x1920" - "1024x768" - "800x1280" - "800x600" - "auto" - ]} + set gfxmode=${ + lib.concatStringsSep "," [ + # GRUB will use the first valid mode listed here. + # `auto` will sometimes choose the smallest valid mode it detects. + # So instead we'll list a lot of possibly valid modes :/ + #"3840x2160" + #"2560x1440" + "1920x1200" + "1920x1080" + "1366x768" + "1280x800" + "1280x720" + "1200x1920" + "1024x768" + "800x1280" + "800x600" + "auto" + ] + } if [ "\$textmode" == "false" ]; then terminal_output gfxterm @@ -207,128 +274,29 @@ let set menu_color_highlight=white/blue fi - ${ # When there is a theme configured, use it, otherwise use the background image. - if config.isoImage.grubTheme != null then '' - # Sets theme. - set theme=(\$root)/EFI/BOOT/grub-theme/theme.txt - # Load theme fonts - $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/BOOT/grub-theme/%P\n") - '' else '' - if background_image (\$root)/EFI/BOOT/efi-background.png; then - # Black background means transparent background when there - # is a background image set... This seems undocumented :( - set color_normal=black/black - set color_highlight=white/blue + ${ + # When there is a theme configured, use it, otherwise use the background image. + if config.isoImage.grubTheme != null then + '' + # Sets theme. + set theme=(\$root)/EFI/BOOT/grub-theme/theme.txt + # Load theme fonts + $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/BOOT/grub-theme/%P\n") + '' else - # Falls back again to proper colors. - set menu_color_normal=cyan/blue - set menu_color_highlight=white/blue - fi - ''} - ''; - - # The EFI boot image. - # Notes about grub: - # * Yes, the grubMenuCfg has to be repeated in all submenus. Otherwise you - # will get white-on-black console-like text on sub-menus. *sigh* - efiDir = pkgs.runCommand "efi-directory" { - nativeBuildInputs = [ pkgs.buildPackages.grub2_efi ]; - strictDeps = true; - } '' - mkdir -p $out/EFI/BOOT - - # Add a marker so GRUB can find the filesystem. - touch $out/EFI/nixos-installer-image - - # ALWAYS required modules. - MODULES=( - # Basic modules for filesystems and partition schemes - "fat" - "iso9660" - "part_gpt" - "part_msdos" - - # Basic stuff - "normal" - "boot" - "linux" - "configfile" - "loopback" - "chain" - "halt" - - # Allows rebooting into firmware setup interface - "efifwsetup" - - # EFI Graphics Output Protocol - "efi_gop" - - # User commands - "ls" - - # System commands - "search" - "search_label" - "search_fs_uuid" - "search_fs_file" - "echo" - - # We're not using it anymore, but we'll leave it in so it can be used - # by user, with the console using "C" - "serial" - - # Graphical mode stuff - "gfxmenu" - "gfxterm" - "gfxterm_background" - "gfxterm_menu" - "test" - "loadenv" - "all_video" - "videoinfo" - - # File types for graphical mode - "png" - ) - - echo "Building GRUB with modules:" - for mod in ''${MODULES[@]}; do - echo " - $mod" - done - - # Modules that may or may not be available per-platform. - echo "Adding additional modules:" - for mod in efi_uga; do - if [ -f ${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget}/$mod.mod ]; then - echo " - $mod" - MODULES+=("$mod") - fi - done - - # Make our own efi program, we can't rely on "grub-install" since it seems to - # probe for devices, even with --skip-fs-probe. - grub-mkimage \ - --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} \ - -o $out/EFI/BOOT/BOOT${lib.toUpper targetArch}.EFI \ - -p /EFI/BOOT \ - -O ${grubPkgs.grub2_efi.grubTarget} \ - ''${MODULES[@]} - cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/BOOT/ - - cat < $out/EFI/BOOT/grub.cfg - - set textmode=${lib.boolToString (config.isoImage.forceTextMode)} - set timeout=${toString grubEfiTimeout} - - clear - # This message will only be viewable on the default (UEFI) console. - echo "" - echo "Loading graphical boot menu..." - echo "" - echo "Press 't' to use the text boot menu on this console..." - echo "" - - ${grubMenuCfg} + '' + if background_image (\$root)/EFI/BOOT/efi-background.png; then + # Black background means transparent background when there + # is a background image set... This seems undocumented :( + set color_normal=black/black + set color_highlight=white/blue + else + # Falls back again to proper colors. + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi + '' + } hiddenentry 'Text mode' --hotkey 't' { loadfont (\$root)/EFI/BOOT/unicode.pf2 @@ -337,141 +305,220 @@ let } ${lib.optionalString (config.isoImage.grubTheme != null) '' - hiddenentry 'GUI mode' --hotkey 'g' { - $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/BOOT/grub-theme/%P\n") - set textmode=false - terminal_output gfxterm - } + hiddenentry 'GUI mode' --hotkey 'g' { + $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/BOOT/grub-theme/%P\n") + set textmode=false + terminal_output gfxterm + } ''} - - # If the parameter iso_path is set, append the findiso parameter to the kernel - # line. We need this to allow the nixos iso to be booted from grub directly. - if [ \''${iso_path} ] ; then - set isoboot="findiso=\''${iso_path}" - fi - - # - # Menu entries - # - - ${buildMenuGrub2} - submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu { - ${grubMenuCfg} - submenu "Suggests resolution @720p" --class hidpi-720p { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "video=1280x720@60"} - } - submenu "Suggests resolution @1080p" --class hidpi-1080p { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "video=1920x1080@60"} - } - - # If we boot into a graphical environment where X is autoran - # and always crashes, it makes the media unusable. Allow the user - # to disable this. - submenu "Disable display-manager" --class quirk-disable-displaymanager { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "systemd.mask=display-manager.service"} - } - - # Some laptop and convertibles have the panel installed in an - # inconvenient way, rotated away from the keyboard. - # Those entries makes it easier to use the installer. - submenu "" {return} - submenu "Rotate framebuffer Clockwise" --class rotate-90cw { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:1"} - } - submenu "Rotate framebuffer Upside-Down" --class rotate-180 { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:2"} - } - submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:3"} - } - - # As a proof of concept, mainly. (Not sure it has accessibility merits.) - submenu "" {return} - submenu "Use black on white" --class accessibility-blakconwhite { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "vt.default_red=0xFF,0xBC,0x4F,0xB4,0x56,0xBC,0x4F,0x00,0xA1,0xCF,0x84,0xCA,0x8D,0xB4,0x84,0x68 vt.default_grn=0xFF,0x55,0xBA,0xBA,0x4D,0x4D,0xB3,0x00,0xA0,0x8F,0xB3,0xCA,0x88,0x93,0xA4,0x68 vt.default_blu=0xFF,0x58,0x5F,0x58,0xC5,0xBD,0xC5,0x00,0xA8,0xBB,0xAB,0x97,0xBD,0xC7,0xC5,0x68"} - } - - # Serial access is a must! - submenu "" {return} - submenu "Serial console=ttyS0,115200n8" --class serial { - ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 "console=ttyS0,115200n8"} - } - } - - ${lib.optionalString (refindBinary != null) '' - # GRUB apparently cannot do "chainloader" operations on "CD". - if [ "\$root" != "cd0" ]; then - menuentry 'rEFInd' --class refind { - # Force root to be the FAT partition - # Otherwise it breaks rEFInd's boot - search --set=root --no-floppy --fs-uuid 1234-5678 - chainloader (\$root)/EFI/BOOT/${refindBinary} - } - fi - ''} - menuentry 'Firmware Setup' --class settings { - fwsetup - clear - echo "" - echo "If you see this message, your EFI system doesn't support this feature." - echo "" - } - menuentry 'Shutdown' --class shutdown { - halt - } - EOF - - grub-script-check $out/EFI/BOOT/grub.cfg - - ${refind} ''; - efiImg = pkgs.runCommand "efi-image_eltorito" { - nativeBuildInputs = [ pkgs.buildPackages.mtools pkgs.buildPackages.libfaketime pkgs.buildPackages.dosfstools ]; - strictDeps = true; - } - # Be careful about determinism: du --apparent-size, - # dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i) - '' - mkdir ./contents && cd ./contents - mkdir -p ./EFI/BOOT - cp -rp "${efiDir}"/EFI/BOOT/{grub.cfg,*.EFI,*.efi} ./EFI/BOOT + # The EFI boot image. + # Notes about grub: + # * Yes, the grubMenuCfg has to be repeated in all submenus. Otherwise you + # will get white-on-black console-like text on sub-menus. *sigh* + efiDir = + pkgs.runCommand "efi-directory" + { + nativeBuildInputs = [ pkgs.buildPackages.grub2_efi ]; + strictDeps = true; + } + '' + mkdir -p $out/EFI/BOOT - # Rewrite dates for everything in the FS - find . -exec touch --date=2000-01-01 {} + + # Add a marker so GRUB can find the filesystem. + touch $out/EFI/nixos-installer-image - # 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 - block_size=$((1024*1024)) - image_size=$(( ($image_size / $block_size + 1) * $block_size )) - echo "Usage size: $usage_size" - echo "Image size: $image_size" - truncate --size=$image_size "$out" - mkfs.vfat --invariant -i 12345678 -n EFIBOOT "$out" + # ALWAYS required modules. + MODULES=( + # Basic modules for filesystems and partition schemes + "fat" + "iso9660" + "part_gpt" + "part_msdos" - # 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 + # Basic stuff + "normal" + "boot" + "linux" + "configfile" + "loopback" + "chain" + "halt" - for f in $(find EFI -type f | sort); do - mcopy -pvm -i "$out" "$f" "::/$f" - done + # Allows rebooting into firmware setup interface + "efifwsetup" - # Verify the FAT partition. - fsck.vfat -vn "$out" - ''; # */ + # EFI Graphics Output Protocol + "efi_gop" + + # User commands + "ls" + + # System commands + "search" + "search_label" + "search_fs_uuid" + "search_fs_file" + "echo" + + # We're not using it anymore, but we'll leave it in so it can be used + # by user, with the console using "C" + "serial" + + # Graphical mode stuff + "gfxmenu" + "gfxterm" + "gfxterm_background" + "gfxterm_menu" + "test" + "loadenv" + "all_video" + "videoinfo" + + # File types for graphical mode + "png" + ) + + echo "Building GRUB with modules:" + for mod in ''${MODULES[@]}; do + echo " - $mod" + done + + # Modules that may or may not be available per-platform. + echo "Adding additional modules:" + for mod in efi_uga; do + if [ -f ${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget}/$mod.mod ]; then + echo " - $mod" + MODULES+=("$mod") + fi + done + + # Make our own efi program, we can't rely on "grub-install" since it seems to + # probe for devices, even with --skip-fs-probe. + grub-mkimage \ + --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} \ + -o $out/EFI/BOOT/BOOT${lib.toUpper targetArch}.EFI \ + -p /EFI/BOOT \ + -O ${grubPkgs.grub2_efi.grubTarget} \ + ''${MODULES[@]} + cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/BOOT/ + + cat < $out/EFI/BOOT/grub.cfg + + set timeout=${toString grubEfiTimeout} + + clear + # This message will only be viewable on the default (UEFI) console. + echo "" + echo "Loading graphical boot menu..." + echo "" + echo "Press 't' to use the text boot menu on this console..." + echo "" + + ${grubMenuCfg} + + # If the parameter iso_path is set, append the findiso parameter to the kernel + # line. We need this to allow the nixos iso to be booted from grub directly. + if [ \''${iso_path} ] ; then + set isoboot="findiso=\''${iso_path}" + fi + + # + # Menu entries + # + + ${buildMenuGrub2 { }} + submenu "Options" --class submenu --class hidpi { + ${grubMenuCfg} + + ${lib.concatMapStringsSep "\n" ( + { + title, + class, + params, + }: + '' + submenu "${title}" --class ${class} { + ${grubMenuCfg} + ${buildMenuGrub2 { inherit params; }} + } + '' + ) optionsSubMenus} + } + + ${lib.optionalString (refindBinary != null) '' + # GRUB apparently cannot do "chainloader" operations on "CD". + if [ "\$root" != "cd0" ]; then + menuentry 'rEFInd' --class refind { + # Force root to be the FAT partition + # Otherwise it breaks rEFInd's boot + search --set=root --no-floppy --fs-uuid 1234-5678 + chainloader (\$root)/EFI/BOOT/${refindBinary} + } + fi + ''} + menuentry 'Firmware Setup' --class settings { + fwsetup + clear + echo "" + echo "If you see this message, your EFI system doesn't support this feature." + echo "" + } + menuentry 'Shutdown' --class shutdown { + halt + } + EOF + + grub-script-check $out/EFI/BOOT/grub.cfg + + ${refind} + ''; + + efiImg = + pkgs.runCommand "efi-image_eltorito" + { + nativeBuildInputs = [ + pkgs.buildPackages.mtools + pkgs.buildPackages.libfaketime + pkgs.buildPackages.dosfstools + ]; + strictDeps = true; + } + # Be careful about determinism: du --apparent-size, + # dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i) + '' + mkdir ./contents && cd ./contents + mkdir -p ./EFI/BOOT + cp -rp "${efiDir}"/EFI/BOOT/{grub.cfg,*.EFI,*.efi} ./EFI/BOOT + + # Rewrite dates for everything in the FS + find . -exec touch --date=2000-01-01 {} + + + # 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 + block_size=$((1024*1024)) + image_size=$(( ($image_size / $block_size + 1) * $block_size )) + echo "Usage size: $usage_size" + echo "Image size: $image_size" + truncate --size=$image_size "$out" + mkfs.vfat --invariant -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 + 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 + + # Verify the FAT partition. + fsck.vfat -vn "$out" + ''; # */ in @@ -534,7 +581,9 @@ in isoImage.volumeID = lib.mkOption { # nixos-$EDITION-$RELEASE-$ARCH - default = "nixos${lib.optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}"}-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}"; + default = "nixos${ + lib.optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}" + }-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}"; type = lib.types.str; description = '' Specifies the label or volume ID of the generated ISO image. @@ -612,9 +661,9 @@ in isoImage.efiSplashImage = lib.mkOption { default = pkgs.fetchurl { - url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/efi-background.png"; - sha256 = "18lfwmp8yq923322nlb9gxrh5qikj1wsk6g5qvdh31c4h5b1538x"; - }; + url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/efi-background.png"; + sha256 = "18lfwmp8yq923322nlb9gxrh5qikj1wsk6g5qvdh31c4h5b1538x"; + }; description = '' The splash image to use in the EFI bootloader. ''; @@ -622,9 +671,9 @@ in isoImage.splashImage = lib.mkOption { default = pkgs.fetchurl { - url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png"; - sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd"; - }; + url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png"; + sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd"; + }; description = '' The splash image to use in the legacy-boot bootloader. ''; @@ -695,6 +744,19 @@ in ''; }; + isoImage.configurationName = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + example = "GNOME"; + description = '' + The name of the configuration in the title of the boot entry. + ''; + }; + + isoImage.showConfiguration = lib.mkEnableOption "show this configuration in the menu" // { + default = true; + }; + isoImage.forceTextMode = lib.mkOption { default = false; type = lib.types.bool; @@ -714,50 +776,51 @@ in # store them in lib so we can mkImageMediaOverride the # entire file system layout in installation media (only) config.lib.isoFileSystems = { - "/" = lib.mkImageMediaOverride - { - fsType = "tmpfs"; - options = [ "mode=0755" ]; - }; + "/" = lib.mkImageMediaOverride { + fsType = "tmpfs"; + options = [ "mode=0755" ]; + }; # Note that /dev/root is a symlink to the actual root device # specified on the kernel command line, created in the stage 1 # init script. - "/iso" = lib.mkImageMediaOverride - { device = "/dev/root"; - neededForBoot = true; - noCheck = true; - }; + "/iso" = lib.mkImageMediaOverride { + device = "/dev/root"; + neededForBoot = true; + noCheck = true; + }; # In stage 1, mount a tmpfs on top of /nix/store (the squashfs # image) to make this a live CD. - "/nix/.ro-store" = lib.mkImageMediaOverride - { fsType = "squashfs"; - device = "/iso/nix-store.squashfs"; - options = [ "loop" ] ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2") "threads=multi"; - neededForBoot = true; - }; + "/nix/.ro-store" = lib.mkImageMediaOverride { + fsType = "squashfs"; + device = "/iso/nix-store.squashfs"; + options = [ + "loop" + ] ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2") "threads=multi"; + neededForBoot = true; + }; - "/nix/.rw-store" = lib.mkImageMediaOverride - { fsType = "tmpfs"; - options = [ "mode=0755" ]; - neededForBoot = true; - }; + "/nix/.rw-store" = lib.mkImageMediaOverride { + fsType = "tmpfs"; + options = [ "mode=0755" ]; + neededForBoot = true; + }; - "/nix/store" = lib.mkImageMediaOverride - { fsType = "overlay"; - device = "overlay"; - options = [ - "lowerdir=/nix/.ro-store" - "upperdir=/nix/.rw-store/store" - "workdir=/nix/.rw-store/work" - ]; - depends = [ - "/nix/.ro-store" - "/nix/.rw-store/store" - "/nix/.rw-store/work" - ]; - }; + "/nix/store" = lib.mkImageMediaOverride { + fsType = "overlay"; + device = "overlay"; + options = [ + "lowerdir=/nix/.ro-store" + "upperdir=/nix/.rw-store/store" + "workdir=/nix/.rw-store/work" + ]; + depends = [ + "/nix/.ro-store" + "/nix/.rw-store/store" + "/nix/.rw-store/work" + ]; + }; }; config = { @@ -771,22 +834,42 @@ in assertion = !(lib.stringLength config.isoImage.volumeID > 32); # https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor # Volume Identifier can only be 32 bytes - message = let - length = lib.stringLength config.isoImage.volumeID; - howmany = toString length; - toomany = toString (length - 32); - in - "isoImage.volumeID ${config.isoImage.volumeID} is ${howmany} characters. That is ${toomany} characters longer than the limit of 32."; + message = + let + length = lib.stringLength config.isoImage.volumeID; + howmany = toString length; + toomany = toString (length - 32); + in + "isoImage.volumeID ${config.isoImage.volumeID} is ${howmany} characters. That is ${toomany} characters longer than the limit of 32."; } + ( + let + badSpecs = lib.filterAttrs ( + specName: specCfg: specCfg.configuration.isoImage.volumeID != config.isoImage.volumeID + ) config.specialisation; + in + { + assertion = badSpecs == { }; + message = '' + All specialisations must use the same 'isoImage.volumeID'. + + Specialisations with different volumeIDs: + + ${lib.concatMapStringsSep "\n" (specName: '' + - ${specName} + '') (builtins.attrNames badSpecs)} + ''; + } + ) ]; # Don't build the GRUB menu builder script, since we don't need it # here and it causes a cyclic dependency. boot.loader.grub.enable = false; - environment.systemPackages = [ grubPkgs.grub2 ] - ++ lib.optional (config.isoImage.makeBiosBootable) pkgs.syslinux - ; + environment.systemPackages = [ + grubPkgs.grub2 + ] ++ lib.optional (config.isoImage.makeBiosBootable) pkgs.syslinux; system.extraDependencies = [ grubPkgs.grub2_efi ]; # In stage 1 of the boot, mount the CD as the root FS by label so @@ -797,66 +880,99 @@ in # UUID of the USB stick. It would be nicer to write # `root=/dev/disk/by-label/...' here, but UNetbootin doesn't # recognise that. - boot.kernelParams = - [ "root=LABEL=${config.isoImage.volumeID}" - "boot.shell_on_fail" - ]; + boot.kernelParams = [ + "root=LABEL=${config.isoImage.volumeID}" + "boot.shell_on_fail" + ]; fileSystems = config.lib.isoFileSystems; - boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ]; + boot.initrd.availableKernelModules = [ + "squashfs" + "iso9660" + "uas" + "overlay" + ]; - boot.initrd.kernelModules = [ "loop" "overlay" ]; + boot.initrd.kernelModules = [ + "loop" + "overlay" + ]; # Closures to be copied to the Nix store on the CD, namely the init # script and the top-level system configuration directory. isoImage.storeContents = - [ config.system.build.toplevel ] ++ - lib.optional config.isoImage.includeSystemBuildDependencies - config.system.build.toplevel.drvPath; + [ config.system.build.toplevel ] + ++ lib.optional config.isoImage.includeSystemBuildDependencies config.system.build.toplevel.drvPath; # Individual files to be included on the CD, outside of the Nix # store on the CD. isoImage.contents = + let + cfgFiles = + cfg: + lib.optionals cfg.isoImage.showConfiguration ([ + { + source = cfg.boot.kernelPackages.kernel + "/" + cfg.system.boot.loader.kernelFile; + target = "/boot/" + cfg.boot.kernelPackages.kernel + "/" + cfg.system.boot.loader.kernelFile; + } + { + source = cfg.system.build.initialRamdisk + "/" + cfg.system.boot.loader.initrdFile; + target = "/boot/" + cfg.system.build.initialRamdisk + "/" + cfg.system.boot.loader.initrdFile; + } + ]) + ++ lib.concatLists ( + lib.mapAttrsToList (_: { configuration, ... }: cfgFiles configuration) cfg.specialisation + ); + in [ - { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile; - target = "/boot/" + config.system.boot.loader.kernelFile; - } - { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile; - target = "/boot/" + config.system.boot.loader.initrdFile; - } - { source = pkgs.writeText "version" config.system.nixos.label; + { + source = pkgs.writeText "version" config.system.nixos.label; target = "/version.txt"; } - ] ++ lib.optionals (config.isoImage.makeBiosBootable) [ - { source = config.isoImage.splashImage; + ] + ++ lib.unique (cfgFiles config) + ++ lib.optionals (config.isoImage.makeBiosBootable) [ + { + source = config.isoImage.splashImage; target = "/isolinux/background.png"; } - { source = pkgs.writeText "isolinux.cfg" isolinuxCfg; + { + source = pkgs.writeText "isolinux.cfg" isolinuxCfg; target = "/isolinux/isolinux.cfg"; } - { source = "${pkgs.syslinux}/share/syslinux"; + { + source = "${pkgs.syslinux}/share/syslinux"; target = "/isolinux"; } - ] ++ lib.optionals config.isoImage.makeEfiBootable [ - { source = efiImg; + ] + ++ lib.optionals config.isoImage.makeEfiBootable [ + { + source = efiImg; target = "/boot/efi.img"; } - { source = "${efiDir}/EFI"; + { + source = "${efiDir}/EFI"; target = "/EFI"; } - { source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/BOOT/grub.cfg") + "/grub"; + { + source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/BOOT/grub.cfg") + "/grub"; target = "/boot/grub"; } - { source = config.isoImage.efiSplashImage; + { + source = config.isoImage.efiSplashImage; target = "/EFI/BOOT/efi-background.png"; } - ] ++ lib.optionals (config.boot.loader.grub.memtest86.enable && config.isoImage.makeBiosBootable) [ - { source = "${pkgs.memtest86plus}/memtest.bin"; + ] + ++ lib.optionals (config.boot.loader.grub.memtest86.enable && config.isoImage.makeBiosBootable) [ + { + source = "${pkgs.memtest86plus}/memtest.bin"; target = "/boot/memtest.bin"; } - ] ++ lib.optionals (config.isoImage.grubTheme != null) [ - { source = config.isoImage.grubTheme; + ] + ++ lib.optionals (config.isoImage.grubTheme != null) [ + { + source = config.isoImage.grubTheme; target = "/EFI/BOOT/grub-theme"; } ]; @@ -866,35 +982,40 @@ in # Create the ISO image. image.extension = if config.isoImage.compressImage then "iso.zst" else "iso"; image.filePath = "iso/${config.image.fileName}"; - image.baseName = "nixos${lib.optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}" }-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}"; + image.baseName = "nixos${ + lib.optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}" + }-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}"; system.build.image = config.system.build.isoImage; - system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({ - inherit (config.isoImage) compressImage volumeID contents; - isoName = "${config.image.baseName}.iso"; - bootable = config.isoImage.makeBiosBootable; - bootImage = "/isolinux/isolinux.bin"; - syslinux = if config.isoImage.makeBiosBootable then pkgs.syslinux else null; - squashfsContents = config.isoImage.storeContents; - squashfsCompression = config.isoImage.squashfsCompression; - } // lib.optionalAttrs (config.isoImage.makeUsbBootable && config.isoImage.makeBiosBootable) { - usbBootable = true; - isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin"; - } // lib.optionalAttrs config.isoImage.makeEfiBootable { - efiBootable = true; - efiBootImage = "boot/efi.img"; - }); + system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ( + { + inherit (config.isoImage) compressImage volumeID contents; + isoName = "${config.image.baseName}.iso"; + bootable = config.isoImage.makeBiosBootable; + bootImage = "/isolinux/isolinux.bin"; + syslinux = if config.isoImage.makeBiosBootable then pkgs.syslinux else null; + squashfsContents = config.isoImage.storeContents; + squashfsCompression = config.isoImage.squashfsCompression; + } + // lib.optionalAttrs (config.isoImage.makeUsbBootable && config.isoImage.makeBiosBootable) { + usbBootable = true; + isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin"; + } + // lib.optionalAttrs config.isoImage.makeEfiBootable { + efiBootable = true; + efiBootImage = "boot/efi.img"; + } + ); - boot.postBootCommands = - '' - # After booting, register the contents of the Nix store on the - # CD in the Nix database in the tmpfs. - ${config.nix.package.out}/bin/nix-store --load-db < /nix/store/nix-path-registration + boot.postBootCommands = '' + # After booting, register the contents of the Nix store on the + # CD in the Nix database in the tmpfs. + ${config.nix.package.out}/bin/nix-store --load-db < /nix/store/nix-path-registration - # nixos-rebuild also requires a "system" profile and an - # /etc/NIXOS tag. - touch /etc/NIXOS - ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system - ''; + # nixos-rebuild also requires a "system" profile and an + # /etc/NIXOS tag. + touch /etc/NIXOS + ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system + ''; # Add vfat support to the initrd to enable people to copy the # contents of the CD to a bootable USB stick. diff --git a/nixos/modules/installer/cd-dvd/latest-kernel.nix b/nixos/modules/installer/cd-dvd/latest-kernel.nix new file mode 100644 index 000000000000..53b9af38ba0b --- /dev/null +++ b/nixos/modules/installer/cd-dvd/latest-kernel.nix @@ -0,0 +1,9 @@ +{ lib, pkgs, ... }: +{ + boot.kernelPackages = pkgs.linuxPackages_latest; + boot.supportedFilesystems.zfs = false; + environment.etc."nixos-generate-config.conf".text = '' + [Defaults] + Kernel=latest + ''; +} diff --git a/nixos/modules/installer/tools/manpages/nixos-generate-config.8 b/nixos/modules/installer/tools/manpages/nixos-generate-config.8 index 33afcc2d3b02..622a4a2c1180 100644 --- a/nixos/modules/installer/tools/manpages/nixos-generate-config.8 +++ b/nixos/modules/installer/tools/manpages/nixos-generate-config.8 @@ -13,6 +13,7 @@ .Op Fl -root Ar root .Op Fl -dir Ar dir .Op Fl -flake +.Op Fl -kernel Ar . . . @@ -66,6 +67,9 @@ instead of .Pa /etc/nixos Ns \&. . +.It Fl -kernel Ar +Set the kernel in the generated configuration file. +. .It Fl -force Overwrite .Pa /etc/nixos/configuration.nix diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index 10ff1aeafd05..6f1e98a585bc 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -7,6 +7,7 @@ use File::Path; use File::Basename; use File::Slurp; use File::stat; +use Config::IniFiles; umask(0022); @@ -37,6 +38,14 @@ my $force = 0; my $noFilesystems = 0; my $flake = 0; my $showHardwareConfig = 0; +my $kernel = "lts"; + +if (-e "/etc/nixos-generate-config.conf") { + my $cfg = new Config::IniFiles -file => "/etc/nixos-generate-config.conf"; + $outDir = $cfg->val("Defaults", "Directory") // $outDir; + $rootDir = $cfg->val("Defaults", "RootDirectory") // $rootDir; + $kernel = $cfg->val("Defaults", "Kernel") // $kernel; +} for (my $n = 0; $n < scalar @ARGV; $n++) { my $arg = $ARGV[$n]; @@ -53,8 +62,6 @@ for (my $n = 0; $n < scalar @ARGV; $n++) { $rootDir = $ARGV[$n]; die "$0: ‘--root’ requires an argument\n" unless defined $rootDir; die "$0: no need to specify `/` with `--root`, it is the default\n" if $rootDir eq "/"; - $rootDir =~ s/\/*$//; # remove trailing slashes - $rootDir = File::Spec->rel2abs($rootDir); # resolve absolute path } elsif ($arg eq "--force") { $force = 1; @@ -68,11 +75,19 @@ for (my $n = 0; $n < scalar @ARGV; $n++) { elsif ($arg eq "--flake") { $flake = 1; } + elsif ($arg eq "--kernel") { + $n++; + $kernel = $ARGV[$n]; + die "$0: ‘--kernel’ requires an argument\n" unless defined $kernel; + } else { die "$0: unrecognized argument ‘$arg’\n"; } } +$rootDir =~ s/\/*$//; # remove trailing slashes +$rootDir = File::Spec->rel2abs($rootDir); # resolve absolute path +die "$0: invalid kernel: '$kernel'" unless $kernel eq "lts" || $kernel eq "latest"; my @attrs = (); my @kernelModules = (); @@ -709,6 +724,14 @@ EOF EOF } + if ($kernel eq "latest") { + $bootLoaderConfig .= < 2025/03/17 13:30:44 internal error: package "bufio" without types was imported from "github.com/gruntwork-io/terragrunt/tf/getproviders" + # > tf/getproviders/lock.go:1: running "mockery": exit status 1 + # > make: *** [Makefile:54: generate-mocks] Error 1 + buildGo123Module, fetchFromGitHub, go-mockery, }: -buildGoModule rec { +buildGo123Module rec { pname = "terragrunt"; - version = "0.73.15"; + version = "0.75.10"; src = fetchFromGitHub { owner = "gruntwork-io"; repo = pname; tag = "v${version}"; - hash = "sha256-ISo6r+mMuXiGTIALXA5+xCKNOzNTNFz8cdGtbWyQRNI="; + hash = "sha256-lnp1prffufVOG+XV7UAo9Rh3ALE//b87ioPgimgZ5S0="; }; nativeBuildInputs = [ go-mockery ]; @@ -22,7 +26,7 @@ buildGoModule rec { make generate-mocks ''; - vendorHash = "sha256-EO3zgqVqf994xB55twRmcGBQdffrNr2BejNq2jlkMSA="; + vendorHash = "sha256-UhOb1Djup9Cwrv9vYeD/DZe20dwSKYRpJa4V3ZCsPwQ="; doCheck = false; diff --git a/pkgs/by-name/tw/twilio-cli/package.nix b/pkgs/by-name/tw/twilio-cli/package.nix index 16bacec316d2..a3d89e551d8b 100644 --- a/pkgs/by-name/tw/twilio-cli/package.nix +++ b/pkgs/by-name/tw/twilio-cli/package.nix @@ -8,11 +8,11 @@ stdenvNoCC.mkDerivation (finalAttrs: { pname = "twilio-cli"; - version = "5.22.11"; + version = "5.23.0"; src = fetchzip { url = "https://twilio-cli-prod.s3.amazonaws.com/twilio-v${finalAttrs.version}/twilio-v${finalAttrs.version}.tar.gz"; - hash = "sha256-SeSv16lZ2Dmfngkq1TtvzlM3oIJkVPsdnkc1hRuSZU4="; + hash = "sha256-LTaQFRoXRBLPLWvyqwMbQc0OOC+wT+taLm78GL2mWBQ="; }; buildInputs = [ nodejs-slim ]; diff --git a/pkgs/by-name/ty/typos-lsp/package.nix b/pkgs/by-name/ty/typos-lsp/package.nix index ef55209fb3b3..1bfd22c09a78 100644 --- a/pkgs/by-name/ty/typos-lsp/package.nix +++ b/pkgs/by-name/ty/typos-lsp/package.nix @@ -6,17 +6,17 @@ rustPlatform.buildRustPackage rec { pname = "typos-lsp"; # Please update the corresponding VSCode extension too. # See pkgs/applications/editors/vscode/extensions/tekumara.typos-vscode/default.nix - version = "0.1.34"; + version = "0.1.35"; src = fetchFromGitHub { owner = "tekumara"; repo = "typos-lsp"; tag = "v${version}"; - hash = "sha256-WqICNpheCJJAmmbj5QIejFeUIW/7ghrhQRP73PLLMJ4="; + hash = "sha256-5B4xWYJJ2KQLxzRQf0EKakGuB0LLOg023AIt8G3uAew="; }; useFetchCargoVendor = true; - cargoHash = "sha256-tmBRUoBsNQlJY0JYtDknD5xeeFnokTE9cnHzktMIiBU="; + cargoHash = "sha256-Es/CdtyRtBghAeRoi5WrS0sdkm5flRlp3KXLs/nJ6UU="; # fix for compilation on aarch64 # see https://github.com/NixOS/nixpkgs/issues/145726 diff --git a/pkgs/by-name/yn/ynetd/hardened.nix b/pkgs/by-name/yn/ynetd/hardened.nix new file mode 100644 index 000000000000..f5188810d593 --- /dev/null +++ b/pkgs/by-name/yn/ynetd/hardened.nix @@ -0,0 +1,29 @@ +{ + lib, + stdenv, + fetchurl, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "ctf-ynetd"; + version = "2024.12.31"; + + src = fetchurl { + url = "https://hxp.io/assets/data/code/ctf-ynetd-2024.12.31.tar.xz"; + hash = "sha256-hUEZZEulmaV3KfKOqE1wl7y4SRUn2/HoOjVDabk5+YA="; + }; + + installPhase = '' + runHook preInstall + install -Dm755 ynetd $out/bin/ynetd + runHook postInstall + ''; + + meta = { + description = "Fork of ynetd hardened for CTFs with isolation using PID namespaces, minimal overhead proof-of-work checking, and strict resource limits via cgroups"; + homepage = "https://hxp.io/code/"; + license = lib.licenses.mit; + platforms = lib.platforms.linux; + maintainers = [ lib.maintainers.haylin ]; + mainProgram = "ynetd"; + }; +}) diff --git a/pkgs/by-name/yn/ynetd/package.nix b/pkgs/by-name/yn/ynetd/package.nix index ce4cc7fa2c30..80228791058f 100644 --- a/pkgs/by-name/yn/ynetd/package.nix +++ b/pkgs/by-name/yn/ynetd/package.nix @@ -2,6 +2,7 @@ lib, stdenv, fetchurl, + callPackage, }: stdenv.mkDerivation (finalAttrs: { pname = "ynetd"; @@ -22,6 +23,10 @@ stdenv.mkDerivation (finalAttrs: { runHook postInstall ''; + # ctf-ynetd releases are based on the last stable ynetd version + # these should be kept in sync when possible + passthru.hardened = callPackage ./hardened.nix { }; + meta = { description = "Small server for binding programs to TCP ports"; homepage = "https://yx7.cc/code/"; diff --git a/pkgs/development/python-modules/firecrawl-py/default.nix b/pkgs/development/python-modules/firecrawl-py/default.nix index e1c9f7aec936..cbff62958ad1 100644 --- a/pkgs/development/python-modules/firecrawl-py/default.nix +++ b/pkgs/development/python-modules/firecrawl-py/default.nix @@ -12,14 +12,14 @@ buildPythonPackage rec { pname = "firecrawl-py"; - version = "1.5.0"; + version = "1.6.0"; pyproject = true; src = fetchFromGitHub { owner = "mendableai"; repo = "firecrawl"; tag = "v${version}"; - hash = "sha256-6reo89L/f50pNdMEm1nknEotoCyZFO/RBu3ldNUQkhk="; + hash = "sha256-xr2curv7Inzav0wGOEfWwKn1XhBg8EIotJbwhXc+aBQ="; }; sourceRoot = "${src.name}/apps/python-sdk"; @@ -42,7 +42,7 @@ buildPythonPackage rec { meta = { description = "Turn entire websites into LLM-ready markdown or structured data. Scrape, crawl and extract with a single API"; homepage = "https://firecrawl.dev"; - changelog = "https://github.com/mendableai/firecrawl/releases/tag/v${version}"; + changelog = "https://github.com/mendableai/firecrawl/releases/tag/${src.tag}"; license = lib.licenses.mit; maintainers = with lib.maintainers; [ drupol ]; }; diff --git a/pkgs/development/python-modules/rcssmin/default.nix b/pkgs/development/python-modules/rcssmin/default.nix index 17db349ccc67..11c5a1bb651f 100644 --- a/pkgs/development/python-modules/rcssmin/default.nix +++ b/pkgs/development/python-modules/rcssmin/default.nix @@ -7,14 +7,14 @@ buildPythonPackage rec { pname = "rcssmin"; - version = "1.2.0"; + version = "1.2.1"; format = "setuptools"; disabled = pythonOlder "3.7"; src = fetchPypi { inherit pname version; - hash = "sha256-9DaHJBLPpvBP/5kMYyIkaxOqOJ9gMjuWNYPtYQLXyEw="; + hash = "sha256-s1wMic2sj8NWwrCYXz5TToXMGNGXHZAtHqx/5rT/Vmw="; }; # The package does not ship tests, and the setup machinery confuses diff --git a/pkgs/servers/jackett/default.nix b/pkgs/servers/jackett/default.nix index 30106423949b..66427fc8b852 100644 --- a/pkgs/servers/jackett/default.nix +++ b/pkgs/servers/jackett/default.nix @@ -11,13 +11,13 @@ buildDotnetModule rec { pname = "jackett"; - version = "0.22.1447"; + version = "0.22.1512"; src = fetchFromGitHub { owner = pname; repo = pname; rev = "v${version}"; - hash = "sha512-spmMAfyNZ0/RR1GExMnQCUL+ocr1Oj/NtEFc6lYmHoVkh/xMRn1QUh5ranKdsUGP5a7H3jq749MnA7w3ZrE2jA=="; + hash = "sha512-gNsEDFBZPByRt2/twSCBvYZtZjXmqBMJPmBKSO4j/irxlhvWpq8SgeDgICpQ9Kf4S5eROPxcKH5V50doWBJndg=="; }; projectFile = "src/Jackett.Server/Jackett.Server.csproj"; diff --git a/pkgs/servers/radarr/default.nix b/pkgs/servers/radarr/default.nix index 8862a3fc43a9..b1763f9c27fe 100644 --- a/pkgs/servers/radarr/default.nix +++ b/pkgs/servers/radarr/default.nix @@ -10,15 +10,15 @@ let }."${stdenv.hostPlatform.system}" or (throw "Unsupported system: ${stdenv.hostPlatform.system}"); hash = { - x64-linux_hash = "sha256-D0Np9Jz7E4/1dnWkFdHQIGthklCVc6yav2AAE9pFcu0="; - arm64-linux_hash = "sha256-cWQOddtAQqMvvWR8uFOs/w0iVnCSg8/nNtYuoUcEqAc="; - x64-osx_hash = "sha256-8ReX8PrP6ZL1orhx8sMDMQ4WHx1WH9cyyrx2yQKFnmc="; - arm64-osx_hash = "sha256-kH6gZ7PWIqrFnlRkqCO2KUvHX0L+xYIcR+NFuflBkFk="; + x64-linux_hash = "sha256-/NVosPx55kmbiUrEwqlCTFR9fyB5cbKaFZApafPDQL4="; + arm64-linux_hash = "sha256-4JgtHmNoJv9zURdFzRQaO0og07HpbVVOkBf+jViuM7E="; + x64-osx_hash = "sha256-wfTGi8227Ggf0h2JyrdvM3yHG8lp5EktuHO37MprgZ4="; + arm64-osx_hash = "sha256-VQ6o1XwT5MMS95e0AW6bgba+8iWvt1jKkxfIfkKiMlM="; }."${arch}-${os}_hash"; in stdenv.mkDerivation rec { pname = "radarr"; - version = "5.18.4.9674"; + version = "5.19.3.9730"; src = fetchurl { url = "https://github.com/Radarr/Radarr/releases/download/v${version}/Radarr.master.${version}.${os}-core-${arch}.tar.gz"; diff --git a/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/default.nix b/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/default.nix index 2572a0a4ff70..1c94f999ded8 100644 --- a/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/default.nix +++ b/pkgs/tools/inputmethods/ibus-engines/ibus-typing-booster/default.nix @@ -25,13 +25,13 @@ in stdenv.mkDerivation rec { pname = "ibus-typing-booster"; - version = "2.27.27"; + version = "2.27.29"; src = fetchFromGitHub { owner = "mike-fabian"; repo = "ibus-typing-booster"; rev = version; - hash = "sha256-nh/dn71RFLuEHhkKWT5sZPUQxiG4pIJ8a3SXnW+A+Ts="; + hash = "sha256-0dyp7kNnmuw9YcYTH/5Eln+EzIbM2HTojXXC9NCA8vE="; }; nativeBuildInputs = [ diff --git a/pkgs/tools/misc/steampipe-packages/steampipe-plugin-aws/default.nix b/pkgs/tools/misc/steampipe-packages/steampipe-plugin-aws/default.nix index 5680e3732a2b..fbe232c8a964 100644 --- a/pkgs/tools/misc/steampipe-packages/steampipe-plugin-aws/default.nix +++ b/pkgs/tools/misc/steampipe-packages/steampipe-plugin-aws/default.nix @@ -8,16 +8,16 @@ buildGoModule rec { pname = "steampipe-plugin-aws"; - version = "1.6.0"; + version = "1.9.0"; src = fetchFromGitHub { owner = "turbot"; repo = "steampipe-plugin-aws"; tag = "v${version}"; - hash = "sha256-kKJoEzudqNdVCmZpyB2Jaqjn01ZOnqqQ516DYnC0Qng="; + hash = "sha256-OpfusJAU2VzsvUjzwvd9xoUAsD4Pl/90mv3ADrVSY1A="; }; - vendorHash = "sha256-76mIpOWpW4NgyKDzeVd7LkmiRhcikMvFaqt8qvh16+U="; + vendorHash = "sha256-eWoeC5MyU7Hs96DK53F0HOaqdT9TjfN2f8BW+oJ2pYY="; ldflags = [ "-s" diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 9eb326ca2c34..e6137495b1d4 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -939,6 +939,7 @@ mapAliases { mariadb-client = hiPrio mariadb.client; #added 2019.07.28 maligned = throw "maligned was deprecated upstream in favor of x/tools/go/analysis/passes/fieldalignment"; # Added 20204-08-24 manicode = throw "manicode has been renamed to codebuff"; # Added 2024-12-10 + manta = throw "manta does not support python3, and development has been abandoned upstream"; # Added 2025-03-17 marwaita-manjaro = lib.warnOnInstantiate "marwaita-manjaro has been renamed to marwaita-teal" marwaita-teal; # Added 2024-07-08 marwaita-peppermint = lib.warnOnInstantiate "marwaita-peppermint has been renamed to marwaita-red" marwaita-red; # Added 2024-07-01 marwaita-ubuntu = lib.warnOnInstantiate "marwaita-ubuntu has been renamed to marwaita-orange" marwaita-orange; # Added 2024-07-08