diff options
author | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:36 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:47 +0000 |
commit | 36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2 (patch) | |
tree | b3faaf573407b32aa645237a4d16b82778a39a92 /nixpkgs/nixos/modules/installer | |
parent | 4e31070265257dc67d120c27e0f75c2344fdfa9a (diff) | |
parent | abf060725d7614bd3b9f96764262dfbc2f9c2199 (diff) | |
download | nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.gz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.bz2 nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.lz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.xz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.zst nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.zip |
Add 'nixpkgs/' from commit 'abf060725d7614bd3b9f96764262dfbc2f9c2199'
git-subtree-dir: nixpkgs git-subtree-mainline: 4e31070265257dc67d120c27e0f75c2344fdfa9a git-subtree-split: abf060725d7614bd3b9f96764262dfbc2f9c2199
Diffstat (limited to 'nixpkgs/nixos/modules/installer')
36 files changed, 3893 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix b/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix new file mode 100644 index 000000000000..01cfe8a02e10 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix @@ -0,0 +1,47 @@ +# Provide an initial copy of the NixOS channel so that the user +# doesn't need to run "nix-channel --update" first. + +{ config, lib, pkgs, ... }: + +with lib; + +let + nixpkgs = lib.cleanSource pkgs.path; + + # We need a copy of the Nix expressions for Nixpkgs and NixOS on the + # CD. These are installed into the "nixos" channel of the root + # user, as expected by nixos-rebuild/nixos-install. FIXME: merge + # with make-channel.nix. + channelSources = pkgs.runCommand "nixos-${config.system.nixos.version}" + { } + '' + mkdir -p $out + cp -prd ${nixpkgs} $out/nixos + chmod -R u+w $out/nixos + if [ ! -e $out/nixos/nixpkgs ]; then + ln -s . $out/nixos/nixpkgs + fi + echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision + echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix + echo ${config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision + ''; + +in + +{ + # Provide the NixOS/Nixpkgs sources in /etc/nixos. This is required + # for nixos-install. + boot.postBootCommands = mkAfter + '' + if ! [ -e /var/lib/nixos/did-channel-init ]; then + echo "unpacking the NixOS/Nixpkgs sources..." + mkdir -p /nix/var/nix/profiles/per-user/root + ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/per-user/root/channels \ + -i ${channelSources} --quiet --option build-use-substitutes false + mkdir -m 0700 -p /root/.nix-defexpr + ln -s /nix/var/nix/profiles/per-user/root/channels /root/.nix-defexpr/channels + mkdir -m 0755 -p /var/lib/nixos + touch /var/lib/nixos/did-channel-init + fi + ''; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-base.nix new file mode 100644 index 000000000000..24070a786945 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-base.nix @@ -0,0 +1,33 @@ +# This module contains the basic configuration for building a NixOS +# installation CD. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = + [ ./iso-image.nix + + # Profiles of this basic installation CD. + ../../profiles/all-hardware.nix + ../../profiles/base.nix + ../../profiles/installation-device.nix + ]; + + # ISO naming. + isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.iso"; + + isoImage.volumeID = substring 0 11 "NIXOS_ISO"; + + # EFI booting + isoImage.makeEfiBootable = true; + + # USB booting + isoImage.makeUsbBootable = true; + + # Add Memtest86+ to the CD. + boot.loader.grub.memtest86.enable = true; + + system.stateVersion = mkDefault "18.03"; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix new file mode 100644 index 000000000000..228ef371d252 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix @@ -0,0 +1,49 @@ +# This module contains the basic configuration for building a graphical NixOS +# installation CD. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./installation-cd-base.nix ]; + + services.xserver = { + enable = true; + + # Don't start the X server by default. + autorun = mkForce false; + + # Automatically login as root. + displayManager.slim = { + enable = true; + defaultUser = "root"; + autoLogin = true; + }; + + }; + + # Provide networkmanager for easy wireless configuration. + networking.networkmanager.enable = true; + networking.wireless.enable = mkForce false; + + # KDE complains if power management is disabled (to be precise, if + # there is no power management backend such as upower). + powerManagement.enable = true; + + environment.systemPackages = [ + # Include gparted for partitioning disks. + pkgs.gparted + + # Include some editors. + pkgs.vim + pkgs.bvi # binary editor + pkgs.joe + + # Firefox for reading the manual. + pkgs.firefox + + pkgs.glxinfo + ]; + +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix new file mode 100644 index 000000000000..42b5ec882272 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix @@ -0,0 +1,21 @@ +# This module defines a NixOS installation CD that contains X11 and +# GNOME 3. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./installation-cd-graphical-base.nix ]; + + services.xserver.desktopManager.gnome3.enable = true; + + services.xserver.displayManager.slim.enable = mkForce false; + + # Auto-login as root. + services.xserver.displayManager.gdm.autoLogin = { + enable = true; + user = "root"; + }; + +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde-new-kernel.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde-new-kernel.nix new file mode 100644 index 000000000000..3336d512cfd8 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde-new-kernel.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: + +{ + imports = [ ./installation-cd-graphical-kde.nix ]; + + boot.kernelPackages = pkgs.linuxPackages_latest; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix new file mode 100644 index 000000000000..1c3c9cb30b41 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-kde.nix @@ -0,0 +1,44 @@ +# This module defines a NixOS installation CD that contains X11 and +# Plasma5. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + imports = [ ./installation-cd-graphical-base.nix ]; + + services.xserver = { + desktopManager.plasma5 = { + enable = true; + enableQt4Support = false; + }; + + # Enable touchpad support for many laptops. + synaptics.enable = true; + }; + + environment.systemPackages = with pkgs; [ + # Graphical text editor + kate + ]; + + system.activationScripts.installerDesktop = let + + manualDesktopFile = pkgs.writeScript "nixos-manual.desktop" '' + [Desktop Entry] + Version=1.0 + Type=Application + Name=NixOS Manual + Exec=firefox ${config.system.build.manual.manualHTMLIndex} + Icon=text-html + ''; + + in '' + mkdir -p /root/Desktop + ln -sfT ${manualDesktopFile} /root/Desktop/nixos-manual.desktop + ln -sfT ${pkgs.konsole}/share/applications/org.kde.konsole.desktop /root/Desktop/org.kde.konsole.desktop + ln -sfT ${pkgs.gparted}/share/applications/gparted.desktop /root/Desktop/gparted.desktop + ''; + +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix new file mode 100644 index 000000000000..3911a2b01b1e --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: + +{ + imports = [ ./installation-cd-minimal.nix ]; + + boot.kernelPackages = pkgs.linuxPackages_latest; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix new file mode 100644 index 000000000000..bcdbffdc20b7 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix @@ -0,0 +1,12 @@ +# This module defines a small NixOS installation CD. It does not +# contain any graphical stuff. + +{ ... }: + +{ + imports = + [ ./installation-cd-base.nix + ]; + + fonts.fontconfig.enable = false; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix new file mode 100644 index 000000000000..9475da23b1ff --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix @@ -0,0 +1,663 @@ +# 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, ... }: + +with lib; + +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} + */ + 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 (if option ? params then "(${option.params})" else "") + }' ${if option ? class then " --class ${option.class}" else ""} { + linux ${defaults.image} ${defaults.params} ${ + option.params or "" + } + initrd ${defaults.initrd} + } + '') + options + ) + ; + + /** + * Given a `config`, builds the default options. + */ + buildMenuGrub2 = config: + buildMenuAdditionalParamsGrub2 config "" + ; + + /** + * Given a `config` and params to add to `params`, build a set of default options. + * Use this one when creating a variant (e.g. hidpi) + */ + buildMenuAdditionalParamsGrub2 = config: additional: + let + finalCfg = { + name = "NixOS ${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"; } + ] + ; + + # Timeout in syslinux is in units of 1/10 of a second. + # 0 is used to disable timeouts. + syslinuxTimeout = if config.boot.loader.timeout == null then + 0 + else + max (config.boot.loader.timeout * 10) 1; + + + max = x: y: if x > y then x else y; + + # The configuration file for syslinux. + + # Notes on syslinux configuration and UNetbootin compatiblity: + # * Do not use '/syslinux/syslinux.cfg' as the path for this + # configuration. UNetbootin will not parse the file and use it as-is. + # This results in a broken configuration if the partition label does + # not match the specified config.isoImage.volumeID. For this reason + # we're using '/isolinux/isolinux.cfg'. + # * Use APPEND instead of adding command-line arguments directly after + # the LINUX entries. + # * COM32 entries (chainload, reboot, poweroff) are not recognized. They + # result in incorrect boot entries. + + baseIsolinuxCfg = '' + SERIAL 0 38400 + TIMEOUT ${builtins.toString syslinuxTimeout} + UI vesamenu.c32 + MENU TITLE NixOS + MENU BACKGROUND /isolinux/background.png + MENU RESOLUTION 800 600 + MENU CLEAR + MENU ROWS 6 + MENU CMDLINEROW -4 + MENU TIMEOUTROW -3 + MENU TABMSGROW -2 + MENU HELPMSGROW -1 + MENU HELPMSGENDROW -1 + MENU MARGIN 0 + + # FG:AARRGGBB BG:AARRGGBB shadow + MENU COLOR BORDER 30;44 #00000000 #00000000 none + MENU COLOR SCREEN 37;40 #FF000000 #00E2E8FF none + MENU COLOR TABMSG 31;40 #80000000 #00000000 none + MENU COLOR TIMEOUT 1;37;40 #FF000000 #00000000 none + MENU COLOR TIMEOUT_MSG 37;40 #FF000000 #00000000 none + MENU COLOR CMDMARK 1;36;40 #FF000000 #00000000 none + MENU COLOR CMDLINE 37;40 #FF000000 #00000000 none + MENU COLOR TITLE 1;36;44 #00000000 #00000000 none + MENU COLOR UNSEL 37;44 #FF000000 #00000000 none + MENU COLOR SEL 7;37;40 #FFFFFFFF #FF5277C3 std + + DEFAULT boot + + LABEL boot + MENU LABEL NixOS ${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} + + # A variant to boot with 'nomodeset' + LABEL boot-nomodeset + MENU LABEL NixOS ${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} + + # A variant to boot with 'copytoram' + LABEL boot-copytoram + MENU LABEL NixOS ${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} + + # A variant to boot with verbose logging to the console + LABEL boot-debug + MENU LABEL NixOS ${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} + ''; + + isolinuxMemtest86Entry = '' + LABEL memtest + MENU LABEL Memtest86+ + LINUX /boot/memtest.bin + APPEND ${toString config.boot.loader.grub.memtest86.params} + ''; + + isolinuxCfg = concatStringsSep "\n" + ([ baseIsolinuxCfg ] ++ optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry); + + # Setup instructions for rEFInd. + refind = + if targetArch == "x64" then + '' + # Adds rEFInd to the ISO. + cp -v ${pkgs.refind}/share/refind/refind_x64.efi $out/EFI/boot/ + '' + else + "# No refind for ${targetArch}" + ; + + grubMenuCfg = '' + # + # Menu configuration + # + + insmod gfxterm + insmod png + set gfxpayload=keep + + # Fonts can be loaded? + # (This font is assumed to always be provided as a fallback by NixOS) + if loadfont (hd0)/EFI/boot/unicode.pf2; then + # Use graphical term, it can be either with background image or a theme. + # input is "console", while output is "gfxterm". + # This enables "serial" input and output only when possible. + # Otherwise the failure mode is to not even enable gfxterm. + if test "\$with_serial" == "yes"; then + terminal_output gfxterm serial + terminal_input console serial + else + terminal_output gfxterm + terminal_input console + fi + else + # Sets colors for the non-graphical term. + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi + + ${ # When there is a theme configured, use it, otherwise use the background image. + if (!isNull config.isoImage.grubTheme) then '' + # Sets theme. + set theme=(hd0)/EFI/boot/grub-theme/theme.txt + # Load theme fonts + $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (hd0)/EFI/boot/grub-theme/%P\n") + '' else '' + if background_image (hd0)/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 + ''} + ''; + + # 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" {} '' + mkdir -p $out/EFI/boot/ + + # ALWAYS required modules. + MODULES="fat iso9660 part_gpt part_msdos \ + normal boot linux configfile loopback chain halt \ + efifwsetup efi_gop \ + ls search search_label search_fs_uuid search_fs_file \ + gfxmenu gfxterm gfxterm_background gfxterm_menu test all_video loadenv \ + exfat ext2 ntfs btrfs hfsplus udf \ + videoinfo png \ + echo serial \ + " + + 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 ${pkgs.grub2_efi}/lib/grub/${pkgs.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. + ${pkgs.grub2_efi}/bin/grub-mkimage -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${pkgs.grub2_efi.grubTarget} \ + $MODULES + cp ${pkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/ + + cat <<EOF > $out/EFI/boot/grub.cfg + + # If you want to use serial for "terminal_*" commands, you need to set one up: + # Example manual configuration: + # → serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 + # This uses the defaults, and makes the serial terminal available. + set with_serial=no + if serial; then set with_serial=yes ;fi + export with_serial + clear + set timeout=10 + ${grubMenuCfg} + + # + # Menu entries + # + + ${buildMenuGrub2 config} + submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu { + ${grubMenuCfg} + submenu "Suggests resolution @720p" --class hidpi-720p { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "video=1280x720@60"} + } + submenu "Suggests resolution @1080p" --class hidpi-1080p { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "video=1920x1080@60"} + } + + # 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 config "fbcon=rotate:1"} + } + submenu "Rotate framebuffer Upside-Down" --class rotate-180 { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:2"} + } + submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw { + ${grubMenuCfg} + ${buildMenuAdditionalParamsGrub2 config "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 config "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 config "console=ttyS0,115200n8"} + } + } + + menuentry 'rEFInd' --class refind { + # UUID is hard-coded in the derivation. + search --set=root --no-floppy --fs-uuid 1234-5678 + chainloader (\$root)/EFI/boot/refind_x64.efi + } + 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 + + ${refind} + ''; + + efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools pkgs.libfaketime ]; } + # Be careful about determinism: du --apparent-size, + # dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i) + '' + mkdir ./contents && cd ./contents + cp -rp "${efiDir}"/* . + mkdir ./boot + cp -p "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}" \ + "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}" ./boot/ + touch --date=@0 ./* + + usage_size=$(du -sb --apparent-size . | tr -cd '[:digit:]') + # 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" + ${pkgs.libfaketime}/bin/faketime "2000-01-01 00:00:00" ${pkgs.dosfstools}/sbin/mkfs.vfat -i 12345678 -n EFIBOOT "$out" + mcopy -psvm -i "$out" ./* :: + # Verify the FAT partition. + ${pkgs.dosfstools}/sbin/fsck.vfat -vn "$out" + ''; # */ + + # Name used by UEFI for architectures. + targetArch = + if pkgs.stdenv.isi686 then + "ia32" + else if pkgs.stdenv.isx86_64 then + "x64" + else if pkgs.stdenv.isAarch64 then + "aa64" + else + throw "Unsupported architecture"; + + # Syslinux (and isolinux) only supports x86-based architectures. + canx86BiosBoot = pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64; + +in + +{ + options = { + + isoImage.isoName = mkOption { + default = "${config.isoImage.isoBaseName}.iso"; + description = '' + Name of the generated ISO image file. + ''; + }; + + isoImage.isoBaseName = mkOption { + default = "nixos"; + description = '' + Prefix of the name of the generated ISO image file. + ''; + }; + + isoImage.compressImage = mkOption { + default = false; + description = '' + Whether the ISO image should be compressed using + <command>bzip2</command>. + ''; + }; + + isoImage.volumeID = mkOption { + default = "NIXOS_BOOT_CD"; + description = '' + Specifies the label or volume ID of the generated ISO image. + Note that the label is used by stage 1 of the boot process to + mount the CD, so it should be reasonably distinctive. + ''; + }; + + isoImage.contents = mkOption { + example = literalExample '' + [ { source = pkgs.memtest86 + "/memtest.bin"; + target = "boot/memtest.bin"; + } + ] + ''; + description = '' + This option lists files to be copied to fixed locations in the + generated ISO image. + ''; + }; + + isoImage.storeContents = mkOption { + example = literalExample "[ pkgs.stdenv ]"; + description = '' + This option lists additional derivations to be included in the + Nix store in the generated ISO image. + ''; + }; + + isoImage.includeSystemBuildDependencies = mkOption { + default = false; + description = '' + Set this option to include all the needed sources etc in the + image. It significantly increases image size. Use that when + you want to be able to keep all the sources needed to build your + system or when you are going to install the system on a computer + with slow or non-existent network connection. + ''; + }; + + isoImage.makeEfiBootable = mkOption { + default = false; + description = '' + Whether the ISO image should be an efi-bootable volume. + ''; + }; + + isoImage.makeUsbBootable = mkOption { + default = false; + description = '' + Whether the ISO image should be bootable from CD as well as USB. + ''; + }; + + isoImage.efiSplashImage = mkOption { + default = pkgs.fetchurl { + 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. + ''; + }; + + isoImage.splashImage = mkOption { + default = pkgs.fetchurl { + 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. + ''; + }; + + isoImage.grubTheme = mkOption { + default = pkgs.nixos-grub2-theme; + type = types.nullOr (types.either types.path types.package); + description = '' + The grub2 theme used for UEFI boot. + ''; + }; + + isoImage.appendToMenuLabel = mkOption { + default = " Installer"; + example = " Live System"; + description = '' + The string to append after the menu label for the NixOS system. + This will be directly appended (without whitespace) to the NixOS version + string, like for example if it is set to <literal>XXX</literal>: + + <para><literal>NixOS 99.99-pre666XXX</literal></para> + ''; + }; + + }; + + config = { + + boot.loader.grub.version = 2; + + # 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 = [ pkgs.grub2 pkgs.grub2_efi ] + ++ optional canx86BiosBoot pkgs.syslinux + ; + + # In stage 1 of the boot, mount the CD as the root FS by label so + # that we don't need to know its device. We pass the label of the + # root filesystem on the kernel command line, rather than in + # `fileSystems' below. This allows CD-to-USB converters such as + # UNetbootin to rewrite the kernel command line to pass the label or + # 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" + ]; + + fileSystems."/" = + { 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. + fileSystems."/iso" = + { 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. + fileSystems."/nix/.ro-store" = + { fsType = "squashfs"; + device = "/iso/nix-store.squashfs"; + options = [ "loop" ]; + neededForBoot = true; + }; + + fileSystems."/nix/.rw-store" = + { fsType = "tmpfs"; + options = [ "mode=0755" ]; + neededForBoot = true; + }; + + fileSystems."/nix/store" = + { fsType = "unionfs-fuse"; + device = "unionfs"; + options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ]; + }; + + boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" ]; + + boot.blacklistedKernelModules = [ "nouveau" ]; + + boot.initrd.kernelModules = [ "loop" ]; + + # 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 ] ++ + optional config.isoImage.includeSystemBuildDependencies + config.system.build.toplevel.drvPath; + + # Create the squashfs image that contains the Nix store. + system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix { + storeContents = config.isoImage.storeContents; + }; + + # Individual files to be included on the CD, outside of the Nix + # store on the CD. + isoImage.contents = + [ + { 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 = config.system.build.squashfsStore; + target = "/nix-store.squashfs"; + } + { source = config.isoImage.efiSplashImage; + target = "/EFI/boot/efi-background.png"; + } + { source = config.isoImage.splashImage; + target = "/isolinux/background.png"; + } + { source = pkgs.writeText "version" config.system.nixos.label; + target = "/version.txt"; + } + ] ++ optionals canx86BiosBoot [ + { source = pkgs.substituteAll { + name = "isolinux.cfg"; + src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg; + bootRoot = "/boot"; + }; + target = "/isolinux/isolinux.cfg"; + } + { source = "${pkgs.syslinux}/share/syslinux"; + target = "/isolinux"; + } + ] ++ optionals config.isoImage.makeEfiBootable [ + { source = efiImg; + target = "/boot/efi.img"; + } + { source = "${efiDir}/EFI"; + target = "/EFI"; + } + ] ++ optionals (config.boot.loader.grub.memtest86.enable && canx86BiosBoot) [ + { source = "${pkgs.memtest86plus}/memtest.bin"; + target = "/boot/memtest.bin"; + } + ] ++ optionals (!isNull config.isoImage.grubTheme) [ + { source = config.isoImage.grubTheme; + target = "/EFI/boot/grub-theme"; + } + ]; + + boot.loader.timeout = 10; + + # Create the ISO image. + system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({ + inherit (config.isoImage) isoName compressImage volumeID contents; + bootable = canx86BiosBoot; + bootImage = "/isolinux/isolinux.bin"; + syslinux = if canx86BiosBoot then pkgs.syslinux else null; + } // optionalAttrs (config.isoImage.makeUsbBootable && canx86BiosBoot) { + usbBootable = true; + isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin"; + } // 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 + + # 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. + boot.initrd.supportedFilesystems = [ "vfat" ]; + + }; + +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64-new-kernel.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64-new-kernel.nix new file mode 100644 index 000000000000..2882fbcc7305 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64-new-kernel.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: + +{ + imports = [ ./sd-image-aarch64.nix ]; + + boot.kernelPackages = pkgs.linuxPackages_latest; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix new file mode 100644 index 000000000000..2db71eb20c5d --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix @@ -0,0 +1,59 @@ +# To build, use: +# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-aarch64.nix -A config.system.build.sdImage +{ config, lib, pkgs, ... }: + +let + extlinux-conf-builder = + import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix { + inherit pkgs; + }; +in +{ + imports = [ + ../../profiles/base.nix + ../../profiles/installation-device.nix + ./sd-image.nix + ]; + + assertions = lib.singleton { + assertion = pkgs.stdenv.hostPlatform.system == "aarch64-linux" + && pkgs.stdenv.hostPlatform.system == pkgs.stdenv.buildPlatform.system; + message = "sd-image-aarch64.nix can be only built natively on Aarch64 / ARM64; " + + "it cannot be cross compiled"; + }; + + boot.loader.grub.enable = false; + boot.loader.generic-extlinux-compatible.enable = true; + + boot.consoleLogLevel = lib.mkDefault 7; + + # The serial ports listed here are: + # - ttyS0: for Tegra (Jetson TX1) + # - ttyAMA0: for QEMU's -machine virt + # Also increase the amount of CMA to ensure the virtual console on the RPi3 works. + boot.kernelParams = ["cma=32M" "console=ttyS0,115200n8" "console=ttyAMA0,115200n8" "console=tty0"]; + + sdImage = { + populateBootCommands = let + configTxt = pkgs.writeText "config.txt" '' + kernel=u-boot-rpi3.bin + + # Boot in 64-bit mode. + arm_control=0x200 + + # U-Boot used to need this to work, regardless of whether UART is actually used or not. + # TODO: check when/if this can be removed. + enable_uart=1 + + # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel + # when attempting to show low-voltage or overtemperature warnings. + avoid_warnings=1 + ''; + in '' + (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/) + cp ${pkgs.ubootRaspberryPi3_64bit}/u-boot.bin boot/u-boot-rpi3.bin + cp ${configTxt} boot/config.txt + ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot + ''; + }; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix new file mode 100644 index 000000000000..695c79ca1707 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix @@ -0,0 +1,63 @@ +# To build, use: +# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix -A config.system.build.sdImage +{ config, lib, pkgs, ... }: + +let + extlinux-conf-builder = + import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix { + inherit pkgs; + }; +in +{ + imports = [ + ../../profiles/base.nix + ../../profiles/installation-device.nix + ./sd-image.nix + ]; + + assertions = lib.singleton { + assertion = pkgs.stdenv.hostPlatform.system == "armv7l-linux" + && pkgs.stdenv.hostPlatform.system == pkgs.stdenv.buildPlatform.system; + message = "sd-image-armv7l-multiplatform.nix can be only built natively on ARMv7; " + + "it cannot be cross compiled"; + }; + + boot.loader.grub.enable = false; + boot.loader.generic-extlinux-compatible.enable = true; + + boot.consoleLogLevel = lib.mkDefault 7; + boot.kernelPackages = pkgs.linuxPackages_latest; + # The serial ports listed here are: + # - ttyS0: for Tegra (Jetson TK1) + # - ttymxc0: for i.MX6 (Wandboard) + # - ttyAMA0: for Allwinner (pcDuino3 Nano) and QEMU's -machine virt + # - ttyO0: for OMAP (BeagleBone Black) + # - ttySAC2: for Exynos (ODROID-XU3) + boot.kernelParams = ["console=ttyS0,115200n8" "console=ttymxc0,115200n8" "console=ttyAMA0,115200n8" "console=ttyO0,115200n8" "console=ttySAC2,115200n8" "console=tty0"]; + + sdImage = { + populateBootCommands = let + configTxt = pkgs.writeText "config.txt" '' + # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel + # when attempting to show low-voltage or overtemperature warnings. + avoid_warnings=1 + + [pi2] + kernel=u-boot-rpi2.bin + + [pi3] + kernel=u-boot-rpi3.bin + + # U-Boot used to need this to work, regardless of whether UART is actually used or not. + # TODO: check when/if this can be removed. + enable_uart=1 + ''; + in '' + (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/) + cp ${pkgs.ubootRaspberryPi2}/u-boot.bin boot/u-boot-rpi2.bin + cp ${pkgs.ubootRaspberryPi3_32bit}/u-boot.bin boot/u-boot-rpi3.bin + cp ${configTxt} boot/config.txt + ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot + ''; + }; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix new file mode 100644 index 000000000000..e395b265d15e --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix @@ -0,0 +1,52 @@ +# To build, use: +# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix -A config.system.build.sdImage +{ config, lib, pkgs, ... }: + +let + extlinux-conf-builder = + import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix { + inherit pkgs; + }; +in +{ + imports = [ + ../../profiles/base.nix + ../../profiles/installation-device.nix + ./sd-image.nix + ]; + + assertions = lib.singleton { + assertion = pkgs.stdenv.hostPlatform.system == "armv6l-linux" + && pkgs.stdenv.hostPlatform.system == pkgs.stdenv.buildPlatform.system; + message = "sd-image-raspberrypi.nix can be only built natively on ARMv6; " + + "it cannot be cross compiled"; + }; + + boot.loader.grub.enable = false; + boot.loader.generic-extlinux-compatible.enable = true; + + boot.consoleLogLevel = lib.mkDefault 7; + boot.kernelPackages = pkgs.linuxPackages_rpi; + + sdImage = { + populateBootCommands = let + configTxt = pkgs.writeText "config.txt" '' + # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel + # when attempting to show low-voltage or overtemperature warnings. + avoid_warnings=1 + + [pi0] + kernel=u-boot-rpi0.bin + + [pi1] + kernel=u-boot-rpi1.bin + ''; + in '' + (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/) + cp ${pkgs.ubootRaspberryPiZero}/u-boot.bin boot/u-boot-rpi0.bin + cp ${pkgs.ubootRaspberryPi}/u-boot.bin boot/u-boot-rpi1.bin + cp ${configTxt} boot/config.txt + ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot + ''; + }; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix new file mode 100644 index 000000000000..69746a8e9799 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix @@ -0,0 +1,168 @@ +# This module creates a bootable SD card image containing the given NixOS +# configuration. The generated image is MBR partitioned, with a FAT /boot +# partition, and ext4 root partition. The generated image is sized to fit +# its contents, and a boot script automatically resizes the root partition +# to fit the device on the first boot. +# +# The derivation for the SD image will be placed in +# config.system.build.sdImage + +{ config, lib, pkgs, ... }: + +with lib; + +let + rootfsImage = pkgs.callPackage ../../../lib/make-ext4-fs.nix ({ + inherit (config.sdImage) storePaths; + volumeLabel = "NIXOS_SD"; + } // optionalAttrs (config.sdImage.rootPartitionUUID != null) { + uuid = config.sdImage.rootPartitionUUID; + }); +in +{ + options.sdImage = { + imageName = mkOption { + default = "${config.sdImage.imageBaseName}-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.img"; + description = '' + Name of the generated image file. + ''; + }; + + imageBaseName = mkOption { + default = "nixos-sd-image"; + description = '' + Prefix of the name of the generated image file. + ''; + }; + + storePaths = mkOption { + type = with types; listOf package; + example = literalExample "[ pkgs.stdenv ]"; + description = '' + Derivations to be included in the Nix store in the generated SD image. + ''; + }; + + bootPartitionID = mkOption { + type = types.string; + default = "0x2178694e"; + description = '' + Volume ID for the /boot partition on the SD card. This value must be a + 32-bit hexadecimal number. + ''; + }; + + rootPartitionUUID = mkOption { + type = types.nullOr types.string; + default = null; + example = "14e19a7b-0ae0-484d-9d54-43bd6fdc20c7"; + description = '' + UUID for the main NixOS partition on the SD card. + ''; + }; + + bootSize = mkOption { + type = types.int; + default = 120; + description = '' + Size of the /boot partition, in megabytes. + ''; + }; + + populateBootCommands = mkOption { + example = literalExample "'' cp \${pkgs.myBootLoader}/u-boot.bin boot/ ''"; + description = '' + Shell commands to populate the ./boot directory. + All files in that directory are copied to the + /boot partition on the SD image. + ''; + }; + }; + + config = { + fileSystems = { + "/boot" = { + device = "/dev/disk/by-label/NIXOS_BOOT"; + fsType = "vfat"; + }; + "/" = { + device = "/dev/disk/by-label/NIXOS_SD"; + fsType = "ext4"; + }; + }; + + sdImage.storePaths = [ config.system.build.toplevel ]; + + system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs, mtools, libfaketime, utillinux }: stdenv.mkDerivation { + name = config.sdImage.imageName; + + nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux ]; + + buildCommand = '' + mkdir -p $out/nix-support $out/sd-image + export img=$out/sd-image/${config.sdImage.imageName} + + echo "${pkgs.stdenv.buildPlatform.system}" > $out/nix-support/system + echo "file sd-image $img" >> $out/nix-support/hydra-build-products + + # Create the image file sized to fit /boot and /, plus 20M of slack + rootSizeBlocks=$(du -B 512 --apparent-size ${rootfsImage} | awk '{ print $1 }') + bootSizeBlocks=$((${toString config.sdImage.bootSize} * 1024 * 1024 / 512)) + imageSize=$((rootSizeBlocks * 512 + bootSizeBlocks * 512 + 20 * 1024 * 1024)) + truncate -s $imageSize $img + + # type=b is 'W95 FAT32', type=83 is 'Linux'. + sfdisk $img <<EOF + label: dos + label-id: ${config.sdImage.bootPartitionID} + + start=8M, size=$bootSizeBlocks, type=b, bootable + start=${toString (8 + config.sdImage.bootSize)}M, type=83 + EOF + + # Copy the rootfs into the SD image + eval $(partx $img -o START,SECTORS --nr 2 --pairs) + dd conv=notrunc if=${rootfsImage} of=$img seek=$START count=$SECTORS + + # Create a FAT32 /boot partition of suitable size into bootpart.img + eval $(partx $img -o START,SECTORS --nr 1 --pairs) + truncate -s $((SECTORS * 512)) bootpart.img + faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.bootPartitionID} -n NIXOS_BOOT bootpart.img + + # Populate the files intended for /boot + mkdir boot + ${config.sdImage.populateBootCommands} + + # Copy the populated /boot into the SD image + (cd boot; mcopy -psvm -i ../bootpart.img ./* ::) + # Verify the FAT partition before copying it. + fsck.vfat -vn bootpart.img + dd conv=notrunc if=bootpart.img of=$img seek=$START count=$SECTORS + ''; + }) {}; + + boot.postBootCommands = '' + # On the first boot do some maintenance tasks + if [ -f /nix-path-registration ]; then + # Figure out device names for the boot device and root filesystem. + rootPart=$(readlink -f /dev/disk/by-label/NIXOS_SD) + bootDevice=$(lsblk -npo PKNAME $rootPart) + + # Resize the root partition and the filesystem to fit the disk + echo ",+," | sfdisk -N2 --no-reread $bootDevice + ${pkgs.parted}/bin/partprobe + ${pkgs.e2fsprogs}/bin/resize2fs $rootPart + + # Register the contents of the initial Nix store + ${config.nix.package.out}/bin/nix-store --load-db < /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 + + # Prevents this from running on later boots. + rm -f /nix-path-registration + fi + ''; + }; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix new file mode 100644 index 000000000000..6d4ba96dba0c --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix @@ -0,0 +1,160 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + # A dummy /etc/nixos/configuration.nix in the booted CD that + # rebuilds the CD's configuration (and allows the configuration to + # be modified, of course, providing a true live CD). Problem is + # that we don't really know how the CD was built - the Nix + # expression language doesn't allow us to query the expression being + # evaluated. So we'll just hope for the best. + dummyConfiguration = pkgs.writeText "configuration.nix" + '' + { config, pkgs, ... }: + + { # Add your own options below, e.g.: + # services.openssh.enable = true; + nixpkgs.config.platform = pkgs.platforms.fuloong2f_n32; + } + ''; + + + pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l; + + # A clue for the kernel loading + kernelParams = pkgs.writeText "kernel-params.txt" '' + Kernel Parameters: + init=/boot/init systemConfig=/boot/init ${toString config.boot.kernelParams} + ''; + + # System wide nixpkgs config + nixpkgsUserConfig = pkgs.writeText "config.nix" '' + pkgs: + { + platform = pkgs.platforms.fuloong2f_n32; + } + ''; + +in + +{ + imports = [ ./system-tarball.nix ]; + + # Disable some other stuff we don't need. + security.sudo.enable = false; + + # Include only the en_US locale. This saves 75 MiB or so compared to + # the full glibcLocales package. + i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"]; + + # Include some utilities that are useful for installing or repairing + # the system. + environment.systemPackages = + [ pkgs.w3m # needed for the manual anyway + pkgs.testdisk # useful for repairing boot problems + pkgs.ms-sys # for writing Microsoft boot sectors / MBRs + pkgs.parted + pkgs.ddrescue + pkgs.ccrypt + pkgs.cryptsetup # needed for dm-crypt volumes + + # Some networking tools. + pkgs.sshfs-fuse + pkgs.socat + pkgs.screen + pkgs.wpa_supplicant # !!! should use the wpa module + + # Hardware-related tools. + pkgs.sdparm + pkgs.hdparm + pkgs.dmraid + + # Tools to create / manipulate filesystems. + pkgs.ntfsprogs # for resizing NTFS partitions + pkgs.btrfs-progs + pkgs.jfsutils + + # Some compression/archiver tools. + pkgs.unzip + pkgs.zip + pkgs.xz + pkgs.dar # disk archiver + + # Some editors. + pkgs.nvi + pkgs.bvi # binary editor + pkgs.joe + ]; + + # The initrd has to contain any module that might be necessary for + # mounting the CD/DVD. + boot.initrd.availableKernelModules = + [ "vfat" "reiserfs" ]; + + boot.kernelPackages = pkgs.linuxPackages_3_10; + boot.kernelParams = [ "console=tty1" ]; + + boot.postBootCommands = + '' + mkdir -p /mnt + + cp ${dummyConfiguration} /etc/nixos/configuration.nix + ''; + + # Some more help text. + services.mingetty.helpLine = + '' + + Log in as "root" with an empty password. ${ + if config.services.xserver.enable then + "Type `start xserver' to start\nthe graphical user interface." + else "" + } + ''; + + # Include the firmware for various wireless cards. + networking.enableRalinkFirmware = true; + networking.enableIntel2200BGFirmware = true; + + # To speed up further installation of packages, include the complete stdenv + # in the Nix store of the tarball. + tarball.storeContents = pkgs2storeContents [ pkgs.stdenv ] + ++ [ + { + object = config.system.build.bootStage2; + symlink = "/boot/init"; + } + { + object = config.system.build.toplevel; + symlink = "/boot/system"; + } + ]; + + tarball.contents = [ + { source = kernelParams; + target = "/kernelparams.txt"; + } + { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile; + target = "/boot/" + config.system.boot.loader.kernelFile; + } + { source = nixpkgsUserConfig; + target = "/root/.nixpkgs/config.nix"; + } + ]; + + # Allow sshd to be started manually through "start sshd". It should + # not be started by default on the installation CD because the + # default root password is empty. + services.openssh.enable = true; + systemd.services.openssh.wantedBy = lib.mkOverride 50 []; + + boot.loader.grub.enable = false; + boot.loader.generationsDir.enable = false; + system.boot.loader.kernelFile = "vmlinux"; + + nixpkgs.config = { + platform = pkgs.platforms.fuloong2f_n32; + }; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt new file mode 100644 index 000000000000..84252f292c54 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt @@ -0,0 +1,89 @@ +Let all the files in the system tarball sit in a directory served by NFS (the +NFS root) like this in exportfs: + /home/pcroot 192.168.1.0/24(rw,no_root_squash,no_all_squash) + +Run "exportfs -a" after editing /etc/exportfs, for the nfs server to be aware +of the changes. + +Use a tftp server serving the root of boot/ (from the system tarball). + +In order to have PXE boot, use the boot/dhcpd.conf-example file for your dhcpd +server, as it will point your PXE clients to pxelinux.0 from the tftp server. +Adapt the configuration to your network. + +Adapt the pxelinux configuration (boot/pxelinux.cfg/default) to set the path to +your nfrroot. If you use ip=dhcp in the kernel, the nfs server ip will be taken +from dhcp and so you don't have to specify it. + +The linux in bzImage includes network drivers for some usual cards. + + +QEMU Testing +--------------- + +You can test qemu pxe boot without having a DHCP server adapted, but having +nfsroot, like this: + qemu-system-x86_64 -tftp /home/pcroot/boot -net nic -net user,bootfile=pxelinux.0 -boot n + +I don't know how to use NFS through the qemu '-net user' though. + + +QEMU Testing with NFS root and bridged network +------------------------------------------------- + +This allows testing with qemu as any other host in your LAN. + +Testing with the real dhcpd server requires setting up a bridge and having a +tap device. + tunctl -t tap0 + brctl addbr br0 + brctl addif br0 eth0 + brctl addif tap0 eth0 + ifconfig eth0 0.0.0.0 up + ifconfig tap0 0.0.0.0 up + ifconfig br0 up # With your ip configuration + +Then you can run qemu: + qemu-system-x86_64 -boot n -net tap,ifname=tap0,script=no -net nic,model=e1000 + + +Using the system-tarball-pc in a chroot +-------------------------------------------------- + +Installation: + mkdir nixos-chroot && cd nixos-chroot + tar xf your-system-tarball.tar.xz + mkdir sys dev proc tmp root var run + mount --bind /sys sys + mount --bind /dev dev + mount --bind /proc proc + +Activate the system: look for a directory in nix/store similar to: + "/nix/store/y0d1lcj9fppli0hl3x0m0ba5g1ndjv2j-nixos-feb97bx-53f008" +Having found it, activate that nixos system *twice*: + chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate + chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate + +This runs a 'hostname' command. Restore your old hostname with: + hostname OLDHOSTNAME + +Copy your system resolv.conf to the /etc/resolv.conf inside the chroot: + cp /etc/resolv.conf etc + +Then you can get an interactive shell in the nixos chroot. '*' means +to run inside the chroot interactive shell + chroot . /bin/sh +* source /etc/profile + +Populate the nix database: that should be done in the init script if you +had booted this nixos. Run: +* `grep local-cmds run/current-system/init` + +Then you can proceed normally subscribing to a nixos channel: + nix-channel --add https://nixos.org/channels/nixos-unstable + nix-channel --update + +Testing: + nix-env -i hello + which hello + hello diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-pc.nix b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-pc.nix new file mode 100644 index 000000000000..5da5df81ede1 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-pc.nix @@ -0,0 +1,164 @@ +# This module contains the basic configuration for building a NixOS +# tarball, that can directly boot, maybe using PXE or unpacking on a fs. + +{ config, lib, pkgs, ... }: + +with lib; + +let + + pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l; + + # For PXE kernel loading + pxeconfig = pkgs.writeText "pxeconfig-default" '' + default menu.c32 + prompt 0 + + label bootlocal + menu default + localboot 0 + timeout 80 + TOTALTIMEOUT 9000 + + label nixos + MENU LABEL ^NixOS using nfsroot + KERNEL bzImage + append ip=dhcp nfsroot=/home/pcroot systemConfig=${config.system.build.toplevel} init=${config.system.build.toplevel}/init rw + + # I don't know how to make this boot with nfsroot (using the initrd) + label nixos_initrd + MENU LABEL NixOS booting the poor ^initrd. + KERNEL bzImage + append initrd=initrd ip=dhcp nfsroot=/home/pcroot systemConfig=${config.system.build.toplevel} init=${config.system.build.toplevel}/init rw + + label memtest + MENU LABEL ^${pkgs.memtest86.name} + KERNEL memtest + ''; + + dhcpdExampleConfig = pkgs.writeText "dhcpd.conf-example" '' + # Example configuration for booting PXE. + allow booting; + allow bootp; + + # Adapt this to your network configuration. + option domain-name "local"; + option subnet-mask 255.255.255.0; + option broadcast-address 192.168.1.255; + option domain-name-servers 192.168.1.1; + option routers 192.168.1.1; + + # PXE-specific configuration directives... + # Some BIOS don't accept slashes for paths inside the tftp servers, + # and will report Access Violation if they see slashes. + filename "pxelinux.0"; + # For the TFTP and NFS root server. Set the IP of your server. + next-server 192.168.1.34; + + subnet 192.168.1.0 netmask 255.255.255.0 { + range 192.168.1.50 192.168.1.55; + } + ''; + + readme = ./system-tarball-pc-readme.txt; + +in + +{ + imports = + [ ./system-tarball.nix + + # Profiles of this basic installation. + ../../profiles/all-hardware.nix + ../../profiles/base.nix + ../../profiles/installation-device.nix + ]; + + # To speed up further installation of packages, include the complete stdenv + # in the Nix store of the tarball. + tarball.storeContents = pkgs2storeContents [ pkgs.stdenv ]; + + tarball.contents = + [ { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile; + target = "/boot/" + config.system.boot.loader.kernelFile; + } + { source = "${pkgs.syslinux}/share/syslinux/pxelinux.0"; + target = "/boot/pxelinux.0"; + } + { source = "${pkgs.syslinux}/share/syslinux/menu.c32"; + target = "/boot/menu.c32"; + } + { source = pxeconfig; + target = "/boot/pxelinux.cfg/default"; + } + { source = readme; + target = "/readme.txt"; + } + { source = dhcpdExampleConfig; + target = "/boot/dhcpd.conf-example"; + } + { source = "${pkgs.memtest86}/memtest.bin"; + # We can't leave '.bin', because pxelinux interprets this specially, + # and it would not load the image fine. + # http://forum.canardpc.com/threads/46464-0104-when-launched-via-pxe + target = "/boot/memtest"; + } + ]; + + # Allow sshd to be started manually through "start sshd". It should + # not be started by default on the installation CD because the + # default root password is empty. + services.openssh.enable = true; + systemd.services.openssh.wantedBy = lib.mkOverride 50 []; + + # To be able to use the systemTarball to catch troubles. + boot.crashDump = { + enable = true; + kernelPackages = pkgs.linuxPackages_3_4; + }; + + # No grub for the tarball. + boot.loader.grub.enable = false; + + /* fake entry, just to have a happy stage-1. Users + may boot without having stage-1 though */ + fileSystems = [ + { mountPoint = "/"; + device = "/dev/something"; + } + ]; + + nixpkgs.config = { + packageOverrides = p: rec { + linux_3_4 = p.linux_3_4.override { + extraConfig = '' + # Enable drivers in kernel for most NICs. + E1000 y + # E1000E y + # ATH5K y + 8139TOO y + NE2K_PCI y + ATL1 y + ATL1E y + ATL1C y + VORTEX y + VIA_RHINE y + R8169 y + + # Enable nfs root boot + UNIX y # http://www.linux-mips.org/archives/linux-mips/2006-11/msg00113.html + IP_PNP y + IP_PNP_DHCP y + FSCACHE y + NFS_FS y + NFS_FSCACHE y + ROOT_NFS y + + # Enable devtmpfs + DEVTMPFS y + DEVTMPFS_MOUNT y + ''; + }; + }; + }; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix new file mode 100644 index 000000000000..90a5128c02a5 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix @@ -0,0 +1,173 @@ +# This module contains the basic configuration for building a NixOS +# tarball for the sheevaplug. + +{ config, lib, pkgs, ... }: + +with lib; + +let + + # A dummy /etc/nixos/configuration.nix in the booted CD that + # rebuilds the CD's configuration (and allows the configuration to + # be modified, of course, providing a true live CD). Problem is + # that we don't really know how the CD was built - the Nix + # expression language doesn't allow us to query the expression being + # evaluated. So we'll just hope for the best. + dummyConfiguration = pkgs.writeText "configuration.nix" + '' + { config, pkgs, ... }: + + { + # Add your own options below and run "nixos-rebuild switch". + # E.g., + # services.openssh.enable = true; + } + ''; + + + pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l; + + # A clue for the kernel loading + kernelParams = pkgs.writeText "kernel-params.txt" '' + Kernel Parameters: + init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} + ''; + + +in + +{ + imports = [ ./system-tarball.nix ]; + + # Disable some other stuff we don't need. + security.sudo.enable = false; + + # Include only the en_US locale. This saves 75 MiB or so compared to + # the full glibcLocales package. + i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"]; + + # Include some utilities that are useful for installing or repairing + # the system. + environment.systemPackages = + [ pkgs.w3m # needed for the manual anyway + pkgs.ddrescue + pkgs.ccrypt + pkgs.cryptsetup # needed for dm-crypt volumes + + # Some networking tools. + pkgs.sshfs-fuse + pkgs.socat + pkgs.screen + pkgs.wpa_supplicant # !!! should use the wpa module + + # Hardware-related tools. + pkgs.sdparm + pkgs.hdparm + pkgs.dmraid + + # Tools to create / manipulate filesystems. + pkgs.btrfs-progs + + # Some compression/archiver tools. + pkgs.unzip + pkgs.zip + pkgs.xz + pkgs.dar # disk archiver + + # Some editors. + pkgs.nvi + pkgs.bvi # binary editor + pkgs.joe + ]; + + boot.loader.grub.enable = false; + boot.loader.generationsDir.enable = false; + system.boot.loader.kernelFile = "uImage"; + + boot.initrd.availableKernelModules = + [ "mvsdio" "reiserfs" "ext3" "ums-cypress" "rtc_mv" "ext4" ]; + + boot.postBootCommands = + '' + mkdir -p /mnt + + cp ${dummyConfiguration} /etc/nixos/configuration.nix + ''; + + boot.initrd.extraUtilsCommands = + '' + copy_bin_and_libs ${pkgs.utillinux}/sbin/hwclock + ''; + + boot.initrd.postDeviceCommands = + '' + hwclock -s + ''; + + boot.kernelParams = + [ + "selinux=0" + "console=tty1" + # "console=ttyS0,115200n8" # serial console + ]; + + boot.kernelPackages = pkgs.linuxPackages_3_4; + + boot.supportedFilesystems = [ "reiserfs" ]; + + /* fake entry, just to have a happy stage-1. Users + may boot without having stage-1 though */ + fileSystems = [ + { mountPoint = "/"; + device = "/dev/something"; + } + ]; + + services.mingetty = { + # Some more help text. + helpLine = '' + Log in as "root" with an empty password. ${ + if config.services.xserver.enable then + "Type `start xserver' to start\nthe graphical user interface." + else "" + } + ''; + }; + + # Setting vesa, we don't get the nvidia driver, which can't work in arm. + services.xserver.videoDrivers = [ "vesa" ]; + + documentation.nixos.enable = false; + + # Include the firmware for various wireless cards. + networking.enableRalinkFirmware = true; + networking.enableIntel2200BGFirmware = true; + + # To speed up further installation of packages, include the complete stdenv + # in the Nix store of the tarball. + tarball.storeContents = pkgs2storeContents [ pkgs.stdenv ]; + tarball.contents = [ + { source = kernelParams; + target = "/kernelparams.txt"; + } + { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile; + target = "/boot/" + config.system.boot.loader.kernelFile; + } + { source = pkgs.ubootSheevaplug; + target = "/boot/uboot"; + } + ]; + + # Allow sshd to be started manually through "start sshd". It should + # not be started by default on the installation CD because the + # default root password is empty. + services.openssh.enable = true; + systemd.services.openssh.wantedBy = lib.mkOverride 50 []; + + # cpufrequtils fails to build on non-pc + powerManagement.enable = false; + + nixpkgs.config = { + platform = pkgs.platforms.sheevaplug; + }; +} diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball.nix b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball.nix new file mode 100644 index 000000000000..e72d4a5b4910 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/cd-dvd/system-tarball.nix @@ -0,0 +1,93 @@ +# 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.tarball. + +{ config, lib, pkgs, ... }: + +with lib; + +let + + versionFile = pkgs.writeText "nixos-label" config.system.nixos.label; + +in + +{ + options = { + tarball.contents = mkOption { + example = literalExample '' + [ { source = pkgs.memtest86 + "/memtest.bin"; + target = "boot/memtest.bin"; + } + ] + ''; + description = '' + This option lists files to be copied to fixed locations in the + generated ISO image. + ''; + }; + + tarball.storeContents = mkOption { + example = literalExample "[ pkgs.stdenv ]"; + description = '' + This option lists additional derivations to be included in the + Nix store in the generated ISO image. + ''; + }; + + }; + + config = { + + # In stage 1 of the boot, mount the CD/DVD as the root FS by label + # so that we don't need to know its device. + fileSystems = [ ]; + + # boot.initrd.availableKernelModules = [ "mvsdio" "reiserfs" "ext3" "ext4" ]; + + # boot.initrd.kernelModules = [ "rtc_mv" ]; + + # Closures to be copied to the Nix store on the CD, namely the init + # script and the top-level system configuration directory. + tarball.storeContents = + [ { object = config.system.build.toplevel; + symlink = "/run/current-system"; + } + ]; + + # Individual files to be included on the CD, outside of the Nix + # store on the CD. + tarball.contents = + [ { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile; + target = "/boot/" + config.system.boot.loader.initrdFile; + } + { source = versionFile; + target = "/nixos-version.txt"; + } + ]; + + # Create the tarball + system.build.tarball = import ../../../lib/make-system-tarball.nix { + inherit (pkgs) stdenv perl xz pathsFromGraph; + + inherit (config.tarball) contents storeContents; + }; + + boot.postBootCommands = + '' + # After booting, register the contents of the Nix store on the + # CD in the Nix database in the tmpfs. + if [ -f /nix-path-registration ]; then + ${config.nix.package.out}/bin/nix-store --load-db < /nix-path-registration && + rm /nix-path-registration + fi + + # 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 + ''; + + }; + +} diff --git a/nixpkgs/nixos/modules/installer/netboot/netboot-base.nix b/nixpkgs/nixos/modules/installer/netboot/netboot-base.nix new file mode 100644 index 000000000000..7e66a49c7391 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/netboot/netboot-base.nix @@ -0,0 +1,17 @@ +# This module contains the basic configuration for building netboot +# images + +{ lib, ... }: + +with lib; + +{ + imports = + [ ./netboot.nix + + # Profiles of this basic netboot media + ../../profiles/all-hardware.nix + ../../profiles/base.nix + ../../profiles/installation-device.nix + ]; +} diff --git a/nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix b/nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix new file mode 100644 index 000000000000..1563501a7e01 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix @@ -0,0 +1,10 @@ +# This module defines a small netboot environment. + +{ ... }: + +{ + imports = + [ ./netboot-base.nix + ../../profiles/minimal.nix + ]; +} diff --git a/nixpkgs/nixos/modules/installer/netboot/netboot.nix b/nixpkgs/nixos/modules/installer/netboot/netboot.nix new file mode 100644 index 000000000000..303d9fce3f9a --- /dev/null +++ b/nixpkgs/nixos/modules/installer/netboot/netboot.nix @@ -0,0 +1,109 @@ +# This module creates netboot media containing the given NixOS +# configuration. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + options = { + + netboot.storeContents = mkOption { + example = literalExample "[ pkgs.stdenv ]"; + description = '' + This option lists additional derivations to be included in the + Nix store in the generated netboot image. + ''; + }; + + }; + + config = rec { + # 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; + + # !!! Hack - attributes expected by other modules. + environment.systemPackages = [ pkgs.grub2_efi ] + ++ (if pkgs.stdenv.hostPlatform.system == "aarch64-linux" + then [] + else [ pkgs.grub2 pkgs.syslinux ]); + + fileSystems."/" = + { fsType = "tmpfs"; + options = [ "mode=0755" ]; + }; + + # In stage 1, mount a tmpfs on top of /nix/store (the squashfs + # image) to make this a live CD. + fileSystems."/nix/.ro-store" = + { fsType = "squashfs"; + device = "../nix-store.squashfs"; + options = [ "loop" ]; + neededForBoot = true; + }; + + fileSystems."/nix/.rw-store" = + { fsType = "tmpfs"; + options = [ "mode=0755" ]; + neededForBoot = true; + }; + + fileSystems."/nix/store" = + { fsType = "unionfs-fuse"; + device = "unionfs"; + options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ]; + }; + + boot.initrd.availableKernelModules = [ "squashfs" ]; + + boot.initrd.kernelModules = [ "loop" ]; + + # Closures to be copied to the Nix store, namely the init + # script and the top-level system configuration directory. + netboot.storeContents = + [ config.system.build.toplevel ]; + + # Create the squashfs image that contains the Nix store. + system.build.squashfsStore = import ../../../lib/make-squashfs.nix { + inherit (pkgs) stdenv squashfsTools closureInfo; + storeContents = config.netboot.storeContents; + }; + + + # Create the initrd + system.build.netbootRamdisk = pkgs.makeInitrd { + inherit (config.boot.initrd) compressor; + prepend = [ "${config.system.build.initialRamdisk}/initrd" ]; + + contents = + [ { object = config.system.build.squashfsStore; + symlink = "/nix-store.squashfs"; + } + ]; + }; + + system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" '' + #!ipxe + kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} + initrd initrd + boot + ''; + + boot.loader.timeout = 10; + + boot.postBootCommands = + '' + # After booting, register the contents of the Nix store + # in the Nix database in the tmpfs. + ${config.nix.package}/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}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system + ''; + + }; + +} diff --git a/nixpkgs/nixos/modules/installer/scan/detected.nix b/nixpkgs/nixos/modules/installer/scan/detected.nix new file mode 100644 index 000000000000..5c5fba56f517 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/scan/detected.nix @@ -0,0 +1,12 @@ +# List all devices which are detected by nixos-generate-config. +# Common devices are enabled by default. +{ lib, ... }: + +with lib; + +{ + config = mkDefault { + # Common firmware, i.e. for wifi cards + hardware.enableRedistributableFirmware = true; + }; +} diff --git a/nixpkgs/nixos/modules/installer/scan/not-detected.nix b/nixpkgs/nixos/modules/installer/scan/not-detected.nix new file mode 100644 index 000000000000..baa068c08dbf --- /dev/null +++ b/nixpkgs/nixos/modules/installer/scan/not-detected.nix @@ -0,0 +1,6 @@ +# Enables non-free firmware on devices not recognized by `nixos-generate-config`. +{ lib, ... }: + +{ + hardware.enableRedistributableFirmware = lib.mkDefault true; +} diff --git a/nixpkgs/nixos/modules/installer/tools/get-version-suffix b/nixpkgs/nixos/modules/installer/tools/get-version-suffix new file mode 100644 index 000000000000..b8972cd57d22 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/get-version-suffix @@ -0,0 +1,22 @@ +getVersion() { + local dir="$1" + rev= + if [ -e "$dir/.git" ]; then + if [ -z "$(type -P git)" ]; then + echo "warning: Git not found; cannot figure out revision of $dir" >&2 + return + fi + cd "$dir" + rev=$(git rev-parse --short HEAD) + if git describe --always --dirty | grep -q dirty; then + rev+=M + fi + fi +} + +if nixpkgs=$(nix-instantiate --find-file nixpkgs "$@"); then + getVersion $nixpkgs + if [ -n "$rev" ]; then + echo ".git.$rev" + fi +fi diff --git a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix new file mode 100644 index 000000000000..1cfc8ff8612e --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix @@ -0,0 +1,6 @@ +{ + x86_64-linux = "/nix/store/cdcia67siabmj6li7vyffgv2cry86fq8-nix-2.1.3"; + i686-linux = "/nix/store/6q3xi6y5qnsv7d62b8n00hqfxi8rs2xs-nix-2.1.3"; + aarch64-linux = "/nix/store/2v93d0vimlm28jg0ms6v1i6lc0fq13pn-nix-2.1.3"; + x86_64-darwin = "/nix/store/dkjlfkrknmxbjmpfk3dg4q3nmb7m3zvk-nix-2.1.3"; +} diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix new file mode 100644 index 000000000000..c1028a0ad7e9 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix @@ -0,0 +1,13 @@ +{ system ? builtins.currentSystem +, config ? {} +, networkExpr +}: + +let nodes = import networkExpr; in + +with import ../../../../lib/testing.nix { + inherit system; + pkgs = import ../../../../.. { inherit system config; }; +}; + +(makeTest { inherit nodes; testScript = ""; }).driver diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh new file mode 100644 index 000000000000..4e981c074a57 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh @@ -0,0 +1,57 @@ +#! @shell@ -e + +# Shows the usage of this command to the user + +showUsage() { + exec man nixos-build-vms + exit 1 +} + +# Parse valid argument options + +PARAMS=`getopt -n $0 -o h -l no-out-link,show-trace,help -- "$@"` + +if [ $? != 0 ] +then + showUsage + exit 1 +fi + +eval set -- "$PARAMS" + +# Evaluate valid options + +while [ "$1" != "--" ] +do + case "$1" in + --no-out-link) + noOutLinkArg="--no-out-link" + ;; + --show-trace) + showTraceArg="--show-trace" + ;; + -h|--help) + showUsage + exit 0 + ;; + esac + + shift +done + +shift + +# Validate the given options + +if [ "$1" = "" ] +then + echo "ERROR: A network expression must be specified!" >&2 + exit 1 +else + networkExpr=$(readlink -f $1) +fi + +# Build a network of VMs + +nix-build '<nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix>' \ + --argstr networkExpr $networkExpr $noOutLinkArg $showTraceArg diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh new file mode 100644 index 000000000000..518dbbbf21e3 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh @@ -0,0 +1,61 @@ +#! @shell@ + +set -e + +# Re-exec ourselves in a private mount namespace so that our bind +# mounts get cleaned up automatically. +if [ -z "$NIXOS_ENTER_REEXEC" ]; then + export NIXOS_ENTER_REEXEC=1 + if [ "$(id -u)" != 0 ]; then + extraFlags="-r" + fi + exec unshare --fork --mount --uts --mount-proc --pid $extraFlags -- "$0" "$@" +else + mount --make-rprivate / +fi + +mountPoint=/mnt +system=/nix/var/nix/profiles/system +command=($system/sw/bin/bash "--login") + +while [ "$#" -gt 0 ]; do + i="$1"; shift 1 + case "$i" in + --root) + mountPoint="$1"; shift 1 + ;; + --system) + system="$1"; shift 1 + ;; + --help) + exec man nixos-enter + exit 1 + ;; + --command|-c) + command=($system/sw/bin/bash "-c" "$1") + shift 1 + ;; + --) + command=("$@") + break + ;; + *) + echo "$0: unknown option \`$i'" + exit 1 + ;; + esac +done + +if [[ ! -e $mountPoint/etc/NIXOS ]]; then + echo "$0: '$mountPoint' is not a NixOS installation" >&2 + exit 126 +fi + +mkdir -m 0755 -p "$mountPoint/dev" "$mountPoint/sys" +mount --rbind /dev "$mountPoint/dev" +mount --rbind /sys "$mountPoint/sys" + +# Run the activation script. Set $LOCALE_ARCHIVE to supress some Perl locale warnings. +LOCALE_ARCHIVE=$system/sw/lib/locale/locale-archive chroot "$mountPoint" "$system/activate" >&2 || true + +exec chroot "$mountPoint" "${command[@]}" diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl new file mode 100644 index 000000000000..52a129b39bcd --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl @@ -0,0 +1,652 @@ +#! @perl@ + +use strict; +use Cwd 'abs_path'; +use File::Spec; +use File::Path; +use File::Basename; +use File::Slurp; +use File::stat; + +umask(0022); + +sub uniq { + my %seen; + my @res = (); + foreach my $s (@_) { + if (!defined $seen{$s}) { + $seen{$s} = 1; + push @res, $s; + } + } + return @res; +} + +sub runCommand { + my ($cmd) = @_; + open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n"; + my @ret = <FILE>; + close FILE; + return ($?, @ret); +} + +# Process the command line. +my $outDir = "/etc/nixos"; +my $rootDir = ""; # = / +my $force = 0; +my $noFilesystems = 0; +my $showHardwareConfig = 0; + +for (my $n = 0; $n < scalar @ARGV; $n++) { + my $arg = $ARGV[$n]; + if ($arg eq "--help") { + exec "man nixos-generate-config" or die; + } + elsif ($arg eq "--dir") { + $n++; + $outDir = $ARGV[$n]; + die "$0: ‘--dir’ requires an argument\n" unless defined $outDir; + } + elsif ($arg eq "--root") { + $n++; + $rootDir = $ARGV[$n]; + die "$0: ‘--root’ requires an argument\n" unless defined $rootDir; + $rootDir =~ s/\/*$//; # remove trailing slashes + } + elsif ($arg eq "--force") { + $force = 1; + } + elsif ($arg eq "--no-filesystems") { + $noFilesystems = 1; + } + elsif ($arg eq "--show-hardware-config") { + $showHardwareConfig = 1; + } + else { + die "$0: unrecognized argument ‘$arg’\n"; + } +} + + +my @attrs = (); +my @kernelModules = (); +my @initrdKernelModules = (); +my @initrdAvailableKernelModules = (); +my @modulePackages = (); +my @imports; + + +sub debug { + return unless defined $ENV{"DEBUG"}; + print STDERR @_; +} + + +my $cpuinfo = read_file "/proc/cpuinfo"; + + +sub hasCPUFeature { + my $feature = shift; + return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m; +} + + +# Detect the number of CPU cores. +my $cpus = scalar (grep {/^processor\s*:/} (split '\n', $cpuinfo)); + + +# Determine CPU governor to use +if (-e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors") { + my $governors = read_file("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors"); + # ondemand governor is not available on sandy bridge or later Intel CPUs + my @desired_governors = ("ondemand", "powersave"); + my $e; + + foreach $e (@desired_governors) { + if (index($governors, $e) != -1) { + last if (push @attrs, "powerManagement.cpuFreqGovernor = lib.mkDefault \"$e\";"); + } + } +} + + +# Virtualization support? +push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; +push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; + + +# Look at the PCI devices and add necessary modules. Note that most +# modules are auto-detected so we don't need to list them here. +# However, some are needed in the initrd to boot the system. + +my $videoDriver; + +sub pciCheck { + my $path = shift; + my $vendor = read_file "$path/vendor"; chomp $vendor; + my $device = read_file "$path/device"; chomp $device; + my $class = read_file "$path/class"; chomp $class; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + debug "$path: $vendor $device $class"; + debug " $module" if defined $module; + debug "\n"; + + if (defined $module) { + # See the bottom of http://pciids.sourceforge.net/pci.ids for + # device classes. + if (# Mass-storage controller. Definitely important. + $class =~ /^0x01/ || + + # Firewire controller. A disk might be attached. + $class =~ /^0x0c00/ || + + # USB controller. Needed if we want to use the + # keyboard when things go wrong in the initrd. + $class =~ /^0x0c03/ + ) + { + push @initrdAvailableKernelModules, $module; + } + } + + # broadcom STA driver (wl.ko) + # list taken from http://www.broadcom.com/docs/linux_sta/README.txt + if ($vendor eq "0x14e4" && + ($device eq "0x4311" || $device eq "0x4312" || $device eq "0x4313" || + $device eq "0x4315" || $device eq "0x4327" || $device eq "0x4328" || + $device eq "0x4329" || $device eq "0x432a" || $device eq "0x432b" || + $device eq "0x432c" || $device eq "0x432d" || $device eq "0x4353" || + $device eq "0x4357" || $device eq "0x4358" || $device eq "0x4359" || + $device eq "0x4331" || $device eq "0x43a0" || $device eq "0x43b1" + ) ) + { + push @modulePackages, "config.boot.kernelPackages.broadcom_sta"; + push @kernelModules, "wl"; + } + + # broadcom FullMac driver + # list taken from + # https://wireless.wiki.kernel.org/en/users/Drivers/brcm80211#brcmfmac + if ($vendor eq "0x14e4" && + ($device eq "0x43a3" || $device eq "0x43df" || $device eq "0x43ec" || + $device eq "0x43d3" || $device eq "0x43d9" || $device eq "0x43e9" || + $device eq "0x43ba" || $device eq "0x43bb" || $device eq "0x43bc" || + $device eq "0xaa52" || $device eq "0x43ca" || $device eq "0x43cb" || + $device eq "0x43cc" || $device eq "0x43c3" || $device eq "0x43c4" || + $device eq "0x43c5" + ) ) + { + # we need e.g. brcmfmac43602-pcie.bin + push @imports, "<nixpkgs/nixos/modules/hardware/network/broadcom-43xx.nix>"; + } + + # Can't rely on $module here, since the module may not be loaded + # due to missing firmware. Ideally we would check modules.pcimap + # here. + push @attrs, "networking.enableIntel2200BGFirmware = true;" if + $vendor eq "0x8086" && + ($device eq "0x1043" || $device eq "0x104f" || $device eq "0x4220" || + $device eq "0x4221" || $device eq "0x4223" || $device eq "0x4224"); + + push @attrs, "networking.enableIntel3945ABGFirmware = true;" if + $vendor eq "0x8086" && + ($device eq "0x4229" || $device eq "0x4230" || + $device eq "0x4222" || $device eq "0x4227"); + + # Assume that all NVIDIA cards are supported by the NVIDIA driver. + # There may be exceptions (e.g. old cards). + # FIXME: do we want to enable an unfree driver here? + #$videoDriver = "nvidia" if $vendor eq "0x10de" && $class =~ /^0x03/; +} + +foreach my $path (glob "/sys/bus/pci/devices/*") { + pciCheck $path; +} + +# Idem for USB devices. + +sub usbCheck { + my $path = shift; + my $class = read_file "$path/bInterfaceClass"; chomp $class; + my $subclass = read_file "$path/bInterfaceSubClass"; chomp $subclass; + my $protocol = read_file "$path/bInterfaceProtocol"; chomp $protocol; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + debug "$path: $class $subclass $protocol"; + debug " $module" if defined $module; + debug "\n"; + + if (defined $module) { + if (# Mass-storage controller. Definitely important. + $class eq "08" || + + # Keyboard. Needed if we want to use the + # keyboard when things go wrong in the initrd. + ($class eq "03" && $protocol eq "01") + ) + { + push @initrdAvailableKernelModules, $module; + } + } +} + +foreach my $path (glob "/sys/bus/usb/devices/*") { + if (-e "$path/bInterfaceClass") { + usbCheck $path; + } +} + + +# Add the modules for all block and MMC devices. +foreach my $path (glob "/sys/class/{block,mmc_host}/*") { + my $module; + if (-e "$path/device/driver/module") { + $module = basename `readlink -f $path/device/driver/module`; + chomp $module; + push @initrdAvailableKernelModules, $module; + } +} + + +my $virt = `systemd-detect-virt`; +chomp $virt; + + +# Check if we're a VirtualBox guest. If so, enable the guest +# additions. +if ($virt eq "oracle") { + push @attrs, "virtualisation.virtualbox.guest.enable = true;" +} + + +# Likewise for QEMU. +if ($virt eq "qemu" || $virt eq "kvm" || $virt eq "bochs") { + push @imports, "<nixpkgs/nixos/modules/profiles/qemu-guest.nix>"; +} + +# Also for Hyper-V. +if ($virt eq "microsoft") { + push @attrs, "virtualisation.hypervGuest.enable = true;" +} + + +# Pull in NixOS configuration for containers. +if ($virt eq "systemd-nspawn") { + push @attrs, "boot.isContainer = true;"; +} + + +# Provide firmware for devices that are not detected by this script, +# unless we're in a VM/container. +push @imports, "<nixpkgs/nixos/modules/installer/scan/not-detected.nix>" + if $virt eq "none"; + + +# For a device name like /dev/sda1, find a more stable path like +# /dev/disk/by-uuid/X or /dev/disk/by-label/Y. +sub findStableDevPath { + my ($dev) = @_; + return $dev if substr($dev, 0, 1) ne "/"; + return $dev unless -e $dev; + + my $st = stat($dev) or return $dev; + + foreach my $dev2 (glob("/dev/disk/by-uuid/*"), glob("/dev/mapper/*"), glob("/dev/disk/by-label/*")) { + my $st2 = stat($dev2) or next; + return $dev2 if $st->rdev == $st2->rdev; + } + + return $dev; +} + +push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];" if $videoDriver; + +# Generate the swapDevices option from the currently activated swap +# devices. +my @swaps = read_file("/proc/swaps", err_mode => 'carp'); +my @swapDevices; +if (@swaps) { + shift @swaps; + foreach my $swap (@swaps) { + $swap =~ /^(\S+)\s/; + next unless -e $1; + my $dev = findStableDevPath $1; + push @swapDevices, "{ device = \"$dev\"; }"; + } +} + + +# Generate the fileSystems option from the currently mounted +# filesystems. +sub in { + my ($d1, $d2) = @_; + return $d1 eq $d2 || substr($d1, 0, length($d2) + 1) eq "$d2/"; +} + +my $fileSystems; +my %fsByDev; +foreach my $fs (read_file("/proc/self/mountinfo")) { + chomp $fs; + my @fields = split / /, $fs; + my $mountPoint = $fields[4]; + next unless -d $mountPoint; + my @mountOptions = split /,/, $fields[5]; + + next if !in($mountPoint, $rootDir); + $mountPoint = substr($mountPoint, length($rootDir)); # strip the root directory (e.g. /mnt) + $mountPoint = "/" if $mountPoint eq ""; + + # Skip special filesystems. + next if in($mountPoint, "/proc") || in($mountPoint, "/dev") || in($mountPoint, "/sys") || in($mountPoint, "/run") || $mountPoint eq "/var/lib/nfs/rpc_pipefs"; + + # Skip the optional fields. + my $n = 6; $n++ while $fields[$n] ne "-"; $n++; + my $fsType = $fields[$n]; + my $device = $fields[$n + 1]; + my @superOptions = split /,/, $fields[$n + 2]; + + # Skip the read-only bind-mount on /nix/store. + next if $mountPoint eq "/nix/store" && (grep { $_ eq "rw" } @superOptions) && (grep { $_ eq "ro" } @mountOptions); + + # Maybe this is a bind-mount of a filesystem we saw earlier? + if (defined $fsByDev{$fields[2]}) { + # Make sure this isn't a btrfs subvolume. + my $msg = `btrfs subvol show $rootDir$mountPoint`; + if ($? != 0 || $msg =~ /ERROR:/s) { + my $path = $fields[3]; $path = "" if $path eq "/"; + my $base = $fsByDev{$fields[2]}; + $base = "" if $base eq "/"; + $fileSystems .= <<EOF; + fileSystems.\"$mountPoint\" = + { device = \"$base$path\"; + fsType = \"none\"; + options = \[ \"bind\" \]; + }; + +EOF + next; + } + } + $fsByDev{$fields[2]} = $mountPoint; + + # We don't know how to handle FUSE filesystems. + if ($fsType eq "fuseblk" || $fsType eq "fuse") { + print STDERR "warning: don't know how to emit ‘fileSystem’ option for FUSE filesystem ‘$mountPoint’\n"; + next; + } + + # Is this a mount of a loopback device? + my @extraOptions; + if ($device =~ /\/dev\/loop(\d+)/) { + my $loopnr = $1; + my $backer = read_file "/sys/block/loop$loopnr/loop/backing_file"; + if (defined $backer) { + chomp $backer; + $device = $backer; + push @extraOptions, "loop"; + } + } + + # Is this a btrfs filesystem? + if ($fsType eq "btrfs") { + my ($status, @info) = runCommand("btrfs subvol show $rootDir$mountPoint"); + if ($status != 0 || join("", @info) =~ /ERROR:/) { + die "Failed to retrieve subvolume info for $mountPoint\n"; + } + my @ids = join("\n", @info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s; + if ($#ids > 0) { + die "Btrfs subvol name for $mountPoint listed multiple times in mount\n" + } elsif ($#ids == 0) { + my @paths = join("", @info) =~ m/^([^\n]*)/; + if ($#paths > 0) { + die "Btrfs returned multiple paths for a single subvolume id, mountpoint $mountPoint\n"; + } elsif ($#paths != 0) { + die "Btrfs did not return a path for the subvolume at $mountPoint\n"; + } + push @extraOptions, "subvol=$paths[0]"; + } + } + + # Emit the filesystem. + $fileSystems .= <<EOF; + fileSystems.\"$mountPoint\" = + { device = \"${\(findStableDevPath $device)}\"; + fsType = \"$fsType\"; +EOF + + if (scalar @extraOptions > 0) { + $fileSystems .= <<EOF; + options = \[ ${\join " ", map { "\"" . $_ . "\"" } uniq(@extraOptions)} \]; +EOF + } + + $fileSystems .= <<EOF; + }; + +EOF + + # If this filesystem is on a LUKS device, then add a + # boot.initrd.luks.devices entry. + if (-e $device) { + my $deviceName = basename(abs_path($device)); + if (-e "/sys/class/block/$deviceName" + && read_file("/sys/class/block/$deviceName/dm/uuid", err_mode => 'quiet') =~ /^CRYPT-LUKS/) + { + my @slaves = glob("/sys/class/block/$deviceName/slaves/*"); + if (scalar @slaves == 1) { + my $slave = "/dev/" . basename($slaves[0]); + if (-e $slave) { + my $dmName = read_file("/sys/class/block/$deviceName/dm/name"); + chomp $dmName; + $fileSystems .= " boot.initrd.luks.devices.\"$dmName\".device = \"${\(findStableDevPath $slave)}\";\n\n"; + } + } + } + } +} + + +# Generate the hardware configuration file. + +sub toNixStringList { + my $res = ""; + foreach my $s (@_) { + $res .= " \"$s\""; + } + return $res; +} +sub toNixList { + my $res = ""; + foreach my $s (@_) { + $res .= " $s"; + } + return $res; +} + +sub multiLineList { + my $indent = shift; + return " [ ]" if !@_; + my $res = "\n${indent}[ "; + my $first = 1; + foreach my $s (@_) { + $res .= "$indent " if !$first; + $first = 0; + $res .= "$s\n"; + } + $res .= "$indent]"; + return $res; +} + +my $initrdAvailableKernelModules = toNixStringList(uniq @initrdAvailableKernelModules); +my $kernelModules = toNixStringList(uniq @kernelModules); +my $modulePackages = toNixList(uniq @modulePackages); + +my $fsAndSwap = ""; +if (!$noFilesystems) { + $fsAndSwap = "\n$fileSystems "; + $fsAndSwap .= "swapDevices =" . multiLineList(" ", @swapDevices) . ";\n"; +} + +my $hwConfig = <<EOF; +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, ... }: + +{ + imports =${\multiLineList(" ", @imports)}; + + boot.initrd.availableKernelModules = [$initrdAvailableKernelModules ]; + boot.kernelModules = [$kernelModules ]; + boot.extraModulePackages = [$modulePackages ]; +$fsAndSwap + nix.maxJobs = lib.mkDefault $cpus; +${\join "", (map { " $_\n" } (uniq @attrs))}} +EOF + + +if ($showHardwareConfig) { + print STDOUT $hwConfig; +} else { + $outDir = "$rootDir$outDir"; + + my $fn = "$outDir/hardware-configuration.nix"; + print STDERR "writing $fn...\n"; + mkpath($outDir, 0, 0755); + write_file($fn, $hwConfig); + + # Generate a basic configuration.nix, unless one already exists. + $fn = "$outDir/configuration.nix"; + if ($force || ! -e $fn) { + print STDERR "writing $fn...\n"; + + my $bootLoaderConfig = ""; + if (-e "/sys/firmware/efi/efivars") { + $bootLoaderConfig = <<EOF; + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; +EOF + } elsif (-e "/boot/extlinux") { + $bootLoaderConfig = <<EOF; + # Use the extlinux boot loader. (NixOS wants to enable GRUB by default) + boot.loader.grub.enable = false; + # Enables the generation of /boot/extlinux/extlinux.conf + boot.loader.generic-extlinux-compatible.enable = true; +EOF + } elsif ($virt ne "systemd-nspawn") { + $bootLoaderConfig = <<EOF; + # Use the GRUB 2 boot loader. + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + # boot.loader.grub.efiSupport = true; + # boot.loader.grub.efiInstallAsRemovable = true; + # boot.loader.efi.efiSysMountPoint = "/boot/efi"; + # Define on which hard drive you want to install Grub. + # boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only +EOF + } + + write_file($fn, <<EOF); +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + +$bootLoaderConfig + # networking.hostName = "nixos"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password\@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + # i18n = { + # consoleFont = "Lat2-Terminus16"; + # consoleKeyMap = "us"; + # defaultLocale = "en_US.UTF-8"; + # }; + + # Set your time zone. + # time.timeZone = "Europe/Amsterdam"; + + # List packages installed in system profile. To search, run: + # \$ nix search wget + # environment.systemPackages = with pkgs; [ + # wget vim + # ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { enable = true; enableSSHSupport = true; }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # sound.enable = true; + # hardware.pulseaudio.enable = true; + + # Enable the X11 windowing system. + # services.xserver.enable = true; + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e"; + + # Enable touchpad support. + # services.xserver.libinput.enable = true; + + # Enable the KDE Desktop Environment. + # services.xserver.displayManager.sddm.enable = true; + # services.xserver.desktopManager.plasma5.enable = true; + + # Define a user account. Don't forget to set a password with ‘passwd’. + # users.users.guest = { + # isNormalUser = true; + # uid = 1000; + # }; + + # This value determines the NixOS release with which your system is to be + # compatible, in order to avoid breaking some software such as database + # servers. You should change this only after NixOS release notes say you + # should. + system.stateVersion = "${\(qw(@release@))}"; # Did you read the comment? + +} +EOF + } else { + print STDERR "warning: not overwriting existing $fn\n"; + } +} + +# workaround for a bug in substituteAll diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-install.sh b/nixpkgs/nixos/modules/installer/tools/nixos-install.sh new file mode 100644 index 000000000000..defc46ad2a72 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-install.sh @@ -0,0 +1,144 @@ +#! @shell@ + +set -e +shopt -s nullglob + +export PATH=@path@:$PATH + +# Ensure a consistent umask. +umask 0022 + +# Parse the command line for the -I flag +extraBuildFlags=() + +mountPoint=/mnt +channelPath= +system= + +while [ "$#" -gt 0 ]; do + i="$1"; shift 1 + case "$i" in + --max-jobs|-j|--cores|-I|--substituters) + j="$1"; shift 1 + extraBuildFlags+=("$i" "$j") + ;; + --option) + j="$1"; shift 1 + k="$1"; shift 1 + extraBuildFlags+=("$i" "$j" "$k") + ;; + --root) + mountPoint="$1"; shift 1 + ;; + --system|--closure) + system="$1"; shift 1 + ;; + --channel) + channelPath="$1"; shift 1 + ;; + --no-channel-copy) + noChannelCopy=1 + ;; + --no-root-passwd) + noRootPasswd=1 + ;; + --no-bootloader) + noBootLoader=1 + ;; + --show-trace) + extraBuildFlags+=("$i") + ;; + --help) + exec man nixos-install + exit 1 + ;; + --debug) + set -x + ;; + *) + echo "$0: unknown option \`$i'" + exit 1 + ;; + esac +done + +if ! test -e "$mountPoint"; then + echo "mount point $mountPoint doesn't exist" + exit 1 +fi + +# Get the path of the NixOS configuration file. +if [[ -z $NIXOS_CONFIG ]]; then + NIXOS_CONFIG=$mountPoint/etc/nixos/configuration.nix +fi + +if [[ ${NIXOS_CONFIG:0:1} != / ]]; then + echo "$0: \$NIXOS_CONFIG is not an absolute path" + exit 1 +fi + +if [[ ! -e $NIXOS_CONFIG && -z $system ]]; then + echo "configuration file $NIXOS_CONFIG doesn't exist" + exit 1 +fi + +# A place to drop temporary stuff. +trap "rm -rf $tmpdir" EXIT +tmpdir="$(mktemp -d)" + +sub="auto?trusted=1" + +# Build the system configuration in the target filesystem. +if [[ -z $system ]]; then + echo "building the configuration in $NIXOS_CONFIG..." + outLink="$tmpdir/system" + nix build --out-link "$outLink" --store "$mountPoint" "${extraBuildFlags[@]}" \ + --extra-substituters "$sub" \ + -f '<nixpkgs/nixos>' system -I "nixos-config=$NIXOS_CONFIG" + system=$(readlink -f $outLink) +fi + +# Set the system profile to point to the configuration. TODO: combine +# this with the previous step once we have a nix-env replacement with +# a progress bar. +nix-env --store "$mountPoint" "${extraBuildFlags[@]}" \ + --extra-substituters "$sub" \ + -p $mountPoint/nix/var/nix/profiles/system --set "$system" + +# Copy the NixOS/Nixpkgs sources to the target as the initial contents +# of the NixOS channel. +if [[ -z $noChannelCopy ]]; then + if [[ -z $channelPath ]]; then + channelPath="$(nix-env -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")" + fi + if [[ -n $channelPath ]]; then + echo "copying channel..." + mkdir -p $mountPoint/nix/var/nix/profiles/per-user/root + nix-env --store "$mountPoint" "${extraBuildFlags[@]}" --extra-substituters "$sub" \ + -p $mountPoint/nix/var/nix/profiles/per-user/root/channels --set "$channelPath" --quiet + install -m 0700 -d $mountPoint/root/.nix-defexpr + ln -sfn /nix/var/nix/profiles/per-user/root/channels $mountPoint/root/.nix-defexpr/channels + fi +fi + +# Mark the target as a NixOS installation, otherwise switch-to-configuration will chicken out. +mkdir -m 0755 -p "$mountPoint/etc" +touch "$mountPoint/etc/NIXOS" + +# Switch to the new system configuration. This will install Grub with +# a menu default pointing at the kernel/initrd/etc of the new +# configuration. +if [[ -z $noBootLoader ]]; then + echo "installing the boot loader..." + # Grub needs an mtab. + ln -sfn /proc/mounts $mountPoint/etc/mtab + NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root "$mountPoint" -- /run/current-system/bin/switch-to-configuration boot +fi + +# Ask the user to set a root password, but only if the passwd command +# exists (i.e. when mutable user accounts are enabled). +if [[ -z $noRootPasswd ]] && [ -t 0 ]; then + nixos-enter --root "$mountPoint" -c '[[ -e /nix/var/nix/profiles/system/sw/bin/passwd ]] && echo "setting root password..." && /nix/var/nix/profiles/system/sw/bin/passwd' +fi + +echo "installation finished!" diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-option.sh b/nixpkgs/nixos/modules/installer/tools/nixos-option.sh new file mode 100644 index 000000000000..327e3e6989f7 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-option.sh @@ -0,0 +1,327 @@ +#! @shell@ -e + +# FIXME: rewrite this in a more suitable language. + +usage () { + exec man nixos-option + exit 1 +} + +##################### +# Process Arguments # +##################### + +xml=false +verbose=false +nixPath="" + +option="" +exit_code=0 + +argfun="" +for arg; do + if test -z "$argfun"; then + case $arg in + -*) + sarg="$arg" + longarg="" + while test "$sarg" != "-"; do + case $sarg in + --*) longarg=$arg; sarg="--";; + -I) argfun="include_nixpath";; + -*) usage;; + esac + # remove the first letter option + sarg="-${sarg#??}" + done + ;; + *) longarg=$arg;; + esac + for larg in $longarg; do + case $larg in + --xml) xml=true;; + --verbose) verbose=true;; + --help) usage;; + -*) usage;; + *) if test -z "$option"; then + option="$larg" + else + usage + fi;; + esac + done + else + case $argfun in + set_*) + var=$(echo $argfun | sed 's,^set_,,') + eval $var=$arg + ;; + include_nixpath) + nixPath="-I $arg $nixPath" + ;; + esac + argfun="" + fi +done + +if $verbose; then + set -x +else + set +x +fi + +############################# +# Process the configuration # +############################# + +evalNix(){ + # disable `-e` flag, it's possible that the evaluation of `nix-instantiate` fails (e.g. due to broken pkgs) + set +e + result=$(nix-instantiate ${nixPath:+$nixPath} - --eval-only "$@" 2>&1) + exit_code=$? + set -e + + if test $exit_code -eq 0; then + sed '/^warning: Nix search path/d' <<EOF +$result +EOF + return 0; + else + sed -n ' + /^error/ { s/, at (string):[0-9]*:[0-9]*//; p; }; + /^warning: Nix search path/ { p; }; +' >&2 <<EOF +$result +EOF + exit_code=1 + fi +} + +header="let + nixos = import <nixpkgs/nixos> {}; + nixpkgs = import <nixpkgs> {}; +in with nixpkgs.lib; +" + +# This function is used for converting the option definition path given by +# the user into accessors for reaching the definition and the declaration +# corresponding to this option. +generateAccessors(){ + if result=$(evalNix --strict --show-trace <<EOF +$header + +let + path = "${option:+$option}"; + pathList = splitString "." path; + + walkOptions = attrsNames: result: + if attrsNames == [] then + result + else + let name = head attrsNames; rest = tail attrsNames; in + if isOption result.options then + walkOptions rest { + options = result.options.type.getSubOptions ""; + opt = ''(\${result.opt}.type.getSubOptions "")''; + cfg = ''\${result.cfg}."\${name}"''; + } + else + walkOptions rest { + options = result.options.\${name}; + opt = ''\${result.opt}."\${name}"''; + cfg = ''\${result.cfg}."\${name}"''; + } + ; + + walkResult = (if path == "" then x: x else walkOptions pathList) { + options = nixos.options; + opt = ''nixos.options''; + cfg = ''nixos.config''; + }; + +in + ''let option = \${walkResult.opt}; config = \${walkResult.cfg}; in'' +EOF +) + then + echo $result + else + # In case of error we want to ignore the error message roduced by the + # script above, as it is iterating over each attribute, which does not + # produce a nice error message. The following code is a fallback + # solution which is cause a nicer error message in the next + # evaluation. + echo "\"let option = nixos.options${option:+.$option}; config = nixos.config${option:+.$option}; in\"" + fi +} + +header="$header +$(eval echo $(generateAccessors)) +" + +evalAttr(){ + local prefix="$1" + local strict="$2" + local suffix="$3" + + # If strict is set, then set it to "true". + test -n "$strict" && strict=true + + evalNix ${strict:+--strict} <<EOF +$header + +let + value = $prefix${suffix:+.$suffix}; + strict = ${strict:-false}; + cleanOutput = x: with nixpkgs.lib; + if isDerivation x then x.outPath + else if isFunction x then "<CODE>" + else if strict then + if isAttrs x then mapAttrs (n: cleanOutput) x + else if isList x then map cleanOutput x + else x + else x; +in + cleanOutput value +EOF +} + +evalOpt(){ + evalAttr "option" "" "$@" +} + +evalCfg(){ + local strict="$1" + evalAttr "config" "$strict" +} + +findSources(){ + local suffix=$1 + evalNix --strict <<EOF +$header + +option.$suffix +EOF +} + +# Given a result from nix-instantiate, recover the list of attributes it +# contains. +attrNames() { + local attributeset=$1 + # sed is used to replace un-printable subset by 0s, and to remove most of + # the inner-attribute set, which reduce the likelyhood to encounter badly + # pre-processed input. + echo "builtins.attrNames $attributeset" | \ + sed 's,<[A-Z]*>,0,g; :inner; s/{[^\{\}]*};/0;/g; t inner;' | \ + evalNix --strict +} + +# map a simple list which contains strings or paths. +nixMap() { + local fun="$1" + local list="$2" + local elem + for elem in $list; do + test $elem = '[' -o $elem = ']' && continue; + $fun $elem + done +} + +# This duplicates the work made below, but it is useful for processing +# the output of nixos-option with other tools such as nixos-gui. +if $xml; then + evalNix --xml --no-location <<EOF +$header + +let + sources = builtins.map (f: f.source); + opt = option; + cfg = config; +in + +with nixpkgs.lib; + +let + optStrict = v: + let + traverse = x : + if isAttrs x then + if x ? outPath then true + else all id (mapAttrsFlatten (n: traverseNoAttrs) x) + else traverseNoAttrs x; + traverseNoAttrs = x: + # do not continue in attribute sets + if isAttrs x then true + else if isList x then all id (map traverse x) + else true; + in assert traverse v; v; +in + +if isOption opt then + optStrict ({} + // optionalAttrs (opt ? default) { inherit (opt) default; } + // optionalAttrs (opt ? example) { inherit (opt) example; } + // optionalAttrs (opt ? description) { inherit (opt) description; } + // optionalAttrs (opt ? type) { typename = opt.type.description; } + // optionalAttrs (opt ? options) { inherit (opt) options; } + // { + # to disambiguate the xml output. + _isOption = true; + declarations = sources opt.declarations; + definitions = sources opt.definitions; + value = cfg; + }) +else + opt +EOF + exit $? +fi + +if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then + echo "Value:" + evalCfg 1 + + echo + + echo "Default:" + if default=$(evalOpt "default" - 2> /dev/null); then + echo "$default" + else + echo "<None>" + fi + echo + if example=$(evalOpt "example" - 2> /dev/null); then + echo "Example:" + echo "$example" + echo + fi + echo "Description:" + echo + echo $(evalOpt "description") + + echo $desc; + + printPath () { echo " $1"; } + + echo "Declared by:" + nixMap printPath "$(findSources "declarations")" + echo + echo "Defined by:" + nixMap printPath "$(findSources "files")" + echo + +else + # echo 1>&2 "Warning: This value is not an option." + + result=$(evalCfg "") + if names=$(attrNames "$result" 2> /dev/null); then + echo 1>&2 "This attribute set contains:" + escapeQuotes () { eval echo "$1"; } + nixMap escapeQuotes "$names" + else + echo 1>&2 "An error occurred while looking for attribute names." + echo $result + fi +fi + +exit $exit_code diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh b/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh new file mode 100644 index 000000000000..2af73519bc52 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh @@ -0,0 +1,387 @@ +#! @shell@ + +if [ -x "@shell@" ]; then export SHELL="@shell@"; fi; + +set -e + +showSyntax() { + exec man nixos-rebuild + exit 1 +} + + +# Parse the command line. +origArgs=("$@") +extraBuildFlags=() +action= +buildNix=1 +fast= +rollback= +upgrade= +repair= +profile=/nix/var/nix/profiles/system +buildHost= +targetHost= + +while [ "$#" -gt 0 ]; do + i="$1"; shift 1 + case "$i" in + --help) + showSyntax + ;; + switch|boot|test|build|dry-build|dry-run|dry-activate|build-vm|build-vm-with-bootloader) + if [ "$i" = dry-run ]; then i=dry-build; fi + action="$i" + ;; + --install-grub) + echo "$0: --install-grub deprecated, use --install-bootloader instead" >&2 + export NIXOS_INSTALL_BOOTLOADER=1 + ;; + --install-bootloader) + export NIXOS_INSTALL_BOOTLOADER=1 + ;; + --no-build-nix) + buildNix= + ;; + --rollback) + rollback=1 + ;; + --upgrade) + upgrade=1 + ;; + --repair) + repair=1 + extraBuildFlags+=("$i") + ;; + --max-jobs|-j|--cores|-I) + j="$1"; shift 1 + extraBuildFlags+=("$i" "$j") + ;; + --show-trace|--no-build-hook|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*) + extraBuildFlags+=("$i") + ;; + --option) + j="$1"; shift 1 + k="$1"; shift 1 + extraBuildFlags+=("$i" "$j" "$k") + ;; + --fast) + buildNix= + fast=1 + extraBuildFlags+=(--show-trace) + ;; + --profile-name|-p) + if [ -z "$1" ]; then + echo "$0: ‘--profile-name’ requires an argument" + exit 1 + fi + if [ "$1" != system ]; then + profile="/nix/var/nix/profiles/system-profiles/$1" + mkdir -p -m 0755 "$(dirname "$profile")" + fi + shift 1 + ;; + --build-host|h) + buildHost="$1" + shift 1 + ;; + --target-host|t) + targetHost="$1" + shift 1 + ;; + *) + echo "$0: unknown option \`$i'" + exit 1 + ;; + esac +done + + +if [ -z "$buildHost" -a -n "$targetHost" ]; then + buildHost="$targetHost" +fi +if [ "$targetHost" = localhost ]; then + targetHost= +fi +if [ "$buildHost" = localhost ]; then + buildHost= +fi + +buildHostCmd() { + if [ -z "$buildHost" ]; then + "$@" + elif [ -n "$remoteNix" ]; then + ssh $SSHOPTS "$buildHost" PATH="$remoteNix:$PATH" "$@" + else + ssh $SSHOPTS "$buildHost" "$@" + fi +} + +targetHostCmd() { + if [ -z "$targetHost" ]; then + "$@" + else + ssh $SSHOPTS "$targetHost" "$@" + fi +} + +copyToTarget() { + if ! [ "$targetHost" = "$buildHost" ]; then + if [ -z "$targetHost" ]; then + NIX_SSHOPTS=$SSHOPTS nix-copy-closure --from "$buildHost" "$1" + elif [ -z "$buildHost" ]; then + NIX_SSHOPTS=$SSHOPTS nix-copy-closure --to "$targetHost" "$1" + else + buildHostCmd nix-copy-closure --to "$targetHost" "$1" + fi + fi +} + +nixBuild() { + if [ -z "$buildHost" ]; then + nix-build "$@" + else + local instArgs=() + local buildArgs=() + + while [ "$#" -gt 0 ]; do + local i="$1"; shift 1 + case "$i" in + -o) + local out="$1"; shift 1 + buildArgs+=("--add-root" "$out" "--indirect") + ;; + -A) + local j="$1"; shift 1 + instArgs+=("$i" "$j") + ;; + -I) # We don't want this in buildArgs + shift 1 + ;; + --no-out-link) # We don't want this in buildArgs + ;; + "<"*) # nix paths + instArgs+=("$i") + ;; + *) + buildArgs+=("$i") + ;; + esac + done + + local drv="$(nix-instantiate "${instArgs[@]}" "${extraBuildFlags[@]}")" + if [ -a "$drv" ]; then + NIX_SSHOPTS=$SSHOPTS nix-copy-closure --to "$buildHost" "$drv" + buildHostCmd nix-store -r "$drv" "${buildArgs[@]}" + else + echo "nix-instantiate failed" + exit 1 + fi + fi +} + + +if [ -z "$action" ]; then showSyntax; fi + +# Only run shell scripts from the Nixpkgs tree if the action is +# "switch", "boot", or "test". With other actions (such as "build"), +# the user may reasonably expect that no code from the Nixpkgs tree is +# executed, so it's safe to run nixos-rebuild against a potentially +# untrusted tree. +canRun= +if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then + canRun=1 +fi + + +# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’. +if [ -n "$upgrade" -a -z "$_NIXOS_REBUILD_REEXEC" ]; then + nix-channel --update nixos + + # If there are other channels that contain a file called + # ".update-on-nixos-rebuild", update them as well. + for channelpath in /nix/var/nix/profiles/per-user/root/channels/*; do + if [ -e "$channelpath/.update-on-nixos-rebuild" ]; then + nix-channel --update "$(basename "$channelpath")" + fi + done +fi + +# Make sure that we use the Nix package we depend on, not something +# else from the PATH for nix-{env,instantiate,build}. This is +# important, because NixOS defaults the architecture of the rebuilt +# system to the architecture of the nix-* binaries used. So if on an +# amd64 system the user has an i686 Nix package in her PATH, then we +# would silently downgrade the whole system to be i686 NixOS on the +# next reboot. +if [ -z "$_NIXOS_REBUILD_REEXEC" ]; then + export PATH=@nix@/bin:$PATH +fi + +# Re-execute nixos-rebuild from the Nixpkgs tree. +if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then + if p=$(nix-build --no-out-link --expr 'with import <nixpkgs/nixos> {}; config.system.build.nixos-rebuild' "${extraBuildFlags[@]}"); then + export _NIXOS_REBUILD_REEXEC=1 + exec $p/bin/nixos-rebuild "${origArgs[@]}" + exit 1 + fi +fi + + +tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX) +SSHOPTS="$NIX_SSHOPTS -o ControlMaster=auto -o ControlPath=$tmpDir/ssh-%n -o ControlPersist=60" + +cleanup() { + for ctrl in "$tmpDir"/ssh-*; do + ssh -o ControlPath="$ctrl" -O exit dummyhost 2>/dev/null || true + done + rm -rf "$tmpDir" +} +trap cleanup EXIT + + + +# If the Nix daemon is running, then use it. This allows us to use +# the latest Nix from Nixpkgs (below) for expression evaluation, while +# still using the old Nix (via the daemon) for actual store access. +# This matters if the new Nix in Nixpkgs has a schema change. It +# would upgrade the schema, which should only happen once we actually +# switch to the new configuration. +# If --repair is given, don't try to use the Nix daemon, because the +# flag can only be used directly. +if [ -z "$repair" ] && systemctl show nix-daemon.socket nix-daemon.service | grep -q ActiveState=active; then + export NIX_REMOTE=${NIX_REMOTE-daemon} +fi + + +# First build Nix, since NixOS may require a newer version than the +# current one. +if [ -n "$rollback" -o "$action" = dry-build ]; then + buildNix= +fi + +prebuiltNix() { + machine="$1" + if [ "$machine" = x86_64 ]; then + echo @nix_x86_64_linux@ + elif [[ "$machine" =~ i.86 ]]; then + echo @nix_i686_linux@ + else + echo "$0: unsupported platform" + exit 1 + fi +} + +remotePATH= + +if [ -n "$buildNix" ]; then + echo "building Nix..." >&2 + nixDrv= + if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then + if ! nixDrv="$(nix-instantiate '<nixpkgs>' --add-root $tmpDir/nix.drv --indirect -A nix "${extraBuildFlags[@]}")"; then + nixStorePath="$(prebuiltNix "$(uname -m)")" + if ! nix-store -r $nixStorePath --add-root $tmpDir/nix --indirect \ + --option extra-binary-caches https://cache.nixos.org/; then + echo "warning: don't know how to get latest Nix" >&2 + fi + # Older version of nix-store -r don't support --add-root. + [ -e $tmpDir/nix ] || ln -sf $nixStorePath $tmpDir/nix + if [ -n "$buildHost" ]; then + remoteNixStorePath="$(prebuiltNix "$(buildHostCmd uname -m)")" + remoteNix="$remoteNixStorePath/bin" + if ! buildHostCmd nix-store -r $remoteNixStorePath \ + --option extra-binary-caches https://cache.nixos.org/ >/dev/null; then + remoteNix= + echo "warning: don't know how to get latest Nix" >&2 + fi + fi + fi + fi + if [ -a "$nixDrv" ]; then + nix-store -r "$nixDrv"'!'"out" --add-root $tmpDir/nix --indirect >/dev/null + if [ -n "$buildHost" ]; then + nix-copy-closure --to "$buildHost" "$nixDrv" + # The nix build produces multiple outputs, we add them all to the remote path + for p in $(buildHostCmd nix-store -r "$(readlink "$nixDrv")" "${buildArgs[@]}"); do + remoteNix="$remoteNix${remoteNix:+:}$p/bin" + done + fi + fi + PATH="$tmpDir/nix/bin:$PATH" +fi + + +# Update the version suffix if we're building from Git (so that +# nixos-version shows something useful). +if [ -n "$canRun" ]; then + if nixpkgs=$(nix-instantiate --find-file nixpkgs "${extraBuildFlags[@]}"); then + suffix=$($SHELL $nixpkgs/nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}" || true) + if [ -n "$suffix" ]; then + echo -n "$suffix" > "$nixpkgs/.version-suffix" || true + fi + fi +fi + + +if [ "$action" = dry-build ]; then + extraBuildFlags+=(--dry-run) +fi + + +# Either upgrade the configuration in the system profile (for "switch" +# or "boot"), or just build it and create a symlink "result" in the +# current directory (for "build" and "test"). +if [ -z "$rollback" ]; then + echo "building the system configuration..." >&2 + if [ "$action" = switch -o "$action" = boot ]; then + pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")" + copyToTarget "$pathToConfig" + targetHostCmd nix-env -p "$profile" --set "$pathToConfig" + elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then + pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")" + elif [ "$action" = build-vm ]; then + pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")" + elif [ "$action" = build-vm-with-bootloader ]; then + pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")" + else + showSyntax + fi + # Copy build to target host if we haven't already done it + if ! [ "$action" = switch -o "$action" = boot ]; then + copyToTarget "$pathToConfig" + fi +else # [ -n "$rollback" ] + if [ "$action" = switch -o "$action" = boot ]; then + targetHostCmd nix-env --rollback -p "$profile" + pathToConfig="$profile" + elif [ "$action" = test -o "$action" = build ]; then + systemNumber=$( + targetHostCmd nix-env -p "$profile" --list-generations | + sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h' + ) + pathToConfig="$profile"-${systemNumber}-link + if [ -z "$targetHost" ]; then + ln -sT "$pathToConfig" ./result + fi + else + showSyntax + fi +fi + + +# If we're not just building, then make the new configuration the boot +# default and/or activate it now. +if [ "$action" = switch -o "$action" = boot -o "$action" = test -o "$action" = dry-activate ]; then + if ! targetHostCmd $pathToConfig/bin/switch-to-configuration "$action"; then + echo "warning: error(s) occurred while switching to the new configuration" >&2 + exit 1 + fi +fi + + +if [ "$action" = build-vm ]; then + cat >&2 <<EOF + +Done. The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm) +EOF +fi diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-version.sh b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh new file mode 100644 index 000000000000..190c49a33ec6 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh @@ -0,0 +1,14 @@ +#! @shell@ + +case "$1" in + -h|--help) + exec man nixos-version + exit 1 + ;; + --hash|--revision) + echo "@revision@" + ;; + *) + echo "@version@ (@codeName@)" + ;; +esac diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix new file mode 100644 index 000000000000..af0a3a2fcc88 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/tools/tools.nix @@ -0,0 +1,82 @@ +# This module generates nixos-install, nixos-rebuild, +# nixos-generate-config, etc. + +{ config, lib, pkgs, ... }: + +with lib; + +let + makeProg = args: pkgs.substituteAll (args // { + dir = "bin"; + isExecutable = true; + }); + + nixos-build-vms = makeProg { + name = "nixos-build-vms"; + src = ./nixos-build-vms/nixos-build-vms.sh; + }; + + nixos-install = makeProg { + name = "nixos-install"; + src = ./nixos-install.sh; + nix = config.nix.package.out; + path = makeBinPath [ nixos-enter ]; + }; + + nixos-rebuild = + let fallback = import ./nix-fallback-paths.nix; in + makeProg { + name = "nixos-rebuild"; + src = ./nixos-rebuild.sh; + nix = config.nix.package.out; + nix_x86_64_linux = fallback.x86_64-linux; + nix_i686_linux = fallback.i686-linux; + }; + + nixos-generate-config = makeProg { + name = "nixos-generate-config"; + src = ./nixos-generate-config.pl; + path = [ pkgs.btrfs-progs ]; + perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl"; + inherit (config.system.nixos) release; + }; + + nixos-option = makeProg { + name = "nixos-option"; + src = ./nixos-option.sh; + }; + + nixos-version = makeProg { + name = "nixos-version"; + src = ./nixos-version.sh; + inherit (config.system.nixos) version codeName revision; + }; + + nixos-enter = makeProg { + name = "nixos-enter"; + src = ./nixos-enter.sh; + }; + +in + +{ + + config = { + + environment.systemPackages = + [ nixos-build-vms + nixos-install + nixos-rebuild + nixos-generate-config + nixos-option + nixos-version + nixos-enter + ]; + + system.build = { + inherit nixos-install nixos-generate-config nixos-option nixos-rebuild nixos-enter; + }; + + }; + +} diff --git a/nixpkgs/nixos/modules/installer/virtualbox-demo.nix b/nixpkgs/nixos/modules/installer/virtualbox-demo.nix new file mode 100644 index 000000000000..2e1b4b3998b5 --- /dev/null +++ b/nixpkgs/nixos/modules/installer/virtualbox-demo.nix @@ -0,0 +1,63 @@ +{ lib, ... }: + +with lib; + +{ + imports = + [ ../virtualisation/virtualbox-image.nix + ../installer/cd-dvd/channel.nix + ../profiles/demo.nix + ../profiles/clone-config.nix + ]; + + # FIXME: UUID detection is currently broken + boot.loader.grub.fsIdentifier = "provided"; + + # Allow mounting of shared folders. + users.users.demo.extraGroups = [ "vboxsf" ]; + + # Add some more video drivers to give X11 a shot at working in + # VMware and QEMU. + services.xserver.videoDrivers = mkOverride 40 [ "virtualbox" "vmware" "cirrus" "vesa" "modesetting" ]; + + powerManagement.enable = false; + system.stateVersion = mkDefault "18.03"; + + installer.cloneConfigExtra = '' + # Let demo build as a trusted user. + # nix.trustedUsers = [ "demo" ]; + + # Mount a VirtualBox shared folder. + # This is configurable in the VirtualBox menu at + # Machine / Settings / Shared Folders. + # fileSystems."/mnt" = { + # fsType = "vboxsf"; + # device = "nameofdevicetomount"; + # options = [ "rw" ]; + # }; + + # By default, the NixOS VirtualBox demo image includes SDDM and Plasma. + # If you prefer another desktop manager or display manager, you may want + # to disable the default. + # services.xserver.desktopManager.plasma5.enable = lib.mkForce false; + # services.xserver.displayManager.sddm.enable = lib.mkForce false; + + # Enable GDM/GNOME by uncommenting above two lines and two lines below. + # services.xserver.displayManager.gdm.enable = true; + # services.xserver.desktopManager.gnome3.enable = true; + + # Set your time zone. + # time.timeZone = "Europe/Amsterdam"; + + # List packages installed in system profile. To search, run: + # \$ nix search wget + # environment.systemPackages = with pkgs; [ + # wget vim + # ]; + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + system.stateVersion = mkDefault "18.03"; + ''; +} |