lol

Merge pull request #177010 from flokli/make-kexec

nixos/modules/installer/kexec/kexec-boot.nix: move into nixos/lib, expose `kexec` nixos/release.nix

authored by

Florian Klink and committed by
GitHub
2b9be311 2de7c6f1

+201 -55
+94
nixos/doc/manual/from_md/installation/installing-kexec.section.xml
··· 1 + <section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-booting-via-kexec"> 2 + <title><quote>Booting</quote> into NixOS via kexec</title> 3 + <para> 4 + In some cases, your system might already be booted into/preinstalled 5 + with another Linux distribution, and booting NixOS by attaching an 6 + installation image is quite a manual process. 7 + </para> 8 + <para> 9 + This is particularly useful for (cloud) providers where you can’t 10 + boot a custom image, but get some Debian or Ubuntu installation. 11 + </para> 12 + <para> 13 + In these cases, it might be easier to use <literal>kexec</literal> 14 + to <quote>jump into NixOS</quote> from the running system, which 15 + only assumes <literal>bash</literal> and <literal>kexec</literal> to 16 + be installed on the machine. 17 + </para> 18 + <para> 19 + Note that kexec may not work correctly on some hardware, as devices 20 + are not fully re-initialized in the process. In practice, this 21 + however is rarely the case. 22 + </para> 23 + <para> 24 + To build the necessary files from your current version of nixpkgs, 25 + you can run: 26 + </para> 27 + <programlisting> 28 + nix-build -A kexec.x86_64-linux '&lt;nixpkgs/nixos/release.nix&gt;' 29 + </programlisting> 30 + <para> 31 + This will create a <literal>result</literal> directory containing 32 + the following: 33 + </para> 34 + <itemizedlist spacing="compact"> 35 + <listitem> 36 + <para> 37 + <literal>bzImage</literal> (the Linux kernel) 38 + </para> 39 + </listitem> 40 + <listitem> 41 + <para> 42 + <literal>initrd</literal> (the initrd file) 43 + </para> 44 + </listitem> 45 + <listitem> 46 + <para> 47 + <literal>kexec-boot</literal> (a shellscript invoking 48 + <literal>kexec</literal>) 49 + </para> 50 + </listitem> 51 + </itemizedlist> 52 + <para> 53 + These three files are meant to be copied over to the other already 54 + running Linux Distribution. 55 + </para> 56 + <para> 57 + Note it’s symlinks pointing elsewhere, so <literal>cd</literal> in, 58 + and use <literal>scp * root@$destination</literal> to copy it over, 59 + rather than rsync. 60 + </para> 61 + <para> 62 + Once you finished copying, execute <literal>kexec-boot</literal> 63 + <emphasis>on the destination</emphasis>, and after some seconds, the 64 + machine should be booting into an (ephemeral) NixOS installation 65 + medium. 66 + </para> 67 + <para> 68 + In case you want to describe your own system closure to kexec into, 69 + instead of the default installer image, you can build your own 70 + <literal>configuration.nix</literal>: 71 + </para> 72 + <programlisting language="bash"> 73 + { modulesPath, ... }: { 74 + imports = [ 75 + (modulesPath + &quot;/installer/netboot/netboot-minimal.nix&quot;) 76 + ]; 77 + 78 + services.openssh.enable = true; 79 + users.users.root.openssh.authorizedKeys.keys = [ 80 + &quot;my-ssh-pubkey&quot; 81 + ]; 82 + } 83 + </programlisting> 84 + <programlisting> 85 + nix-build '&lt;nixpkgs/nixos&gt;' \ 86 + --arg configuration ./configuration.nix 87 + --attr config.system.build.kexecTree 88 + </programlisting> 89 + <para> 90 + Make sure your <literal>configuration.nix</literal> does still 91 + import <literal>netboot-minimal.nix</literal> (or 92 + <literal>netboot-base.nix</literal>). 93 + </para> 94 + </section>
+1
nixos/doc/manual/from_md/installation/installing.chapter.xml
··· 638 638 <title>Additional installation notes</title> 639 639 <xi:include href="installing-usb.section.xml" /> 640 640 <xi:include href="installing-pxe.section.xml" /> 641 + <xi:include href="installing-kexec.section.xml" /> 641 642 <xi:include href="installing-virtualbox-guest.section.xml" /> 642 643 <xi:include href="installing-from-other-distro.section.xml" /> 643 644 <xi:include href="installing-behind-a-proxy.section.xml" />
+64
nixos/doc/manual/installation/installing-kexec.section.md
··· 1 + # "Booting" into NixOS via kexec {#sec-booting-via-kexec} 2 + 3 + In some cases, your system might already be booted into/preinstalled with 4 + another Linux distribution, and booting NixOS by attaching an installation 5 + image is quite a manual process. 6 + 7 + This is particularly useful for (cloud) providers where you can't boot a custom 8 + image, but get some Debian or Ubuntu installation. 9 + 10 + In these cases, it might be easier to use `kexec` to "jump into NixOS" from the 11 + running system, which only assumes `bash` and `kexec` to be installed on the 12 + machine. 13 + 14 + Note that kexec may not work correctly on some hardware, as devices are not 15 + fully re-initialized in the process. In practice, this however is rarely the 16 + case. 17 + 18 + To build the necessary files from your current version of nixpkgs, 19 + you can run: 20 + 21 + ```ShellSession 22 + nix-build -A kexec.x86_64-linux '<nixpkgs/nixos/release.nix>' 23 + ``` 24 + 25 + This will create a `result` directory containing the following: 26 + - `bzImage` (the Linux kernel) 27 + - `initrd` (the initrd file) 28 + - `kexec-boot` (a shellscript invoking `kexec`) 29 + 30 + These three files are meant to be copied over to the other already running 31 + Linux Distribution. 32 + 33 + Note it's symlinks pointing elsewhere, so `cd` in, and use 34 + `scp * root@$destination` to copy it over, rather than rsync. 35 + 36 + Once you finished copying, execute `kexec-boot` *on the destination*, and after 37 + some seconds, the machine should be booting into an (ephemeral) NixOS 38 + installation medium. 39 + 40 + In case you want to describe your own system closure to kexec into, instead of 41 + the default installer image, you can build your own `configuration.nix`: 42 + 43 + ```nix 44 + { modulesPath, ... }: { 45 + imports = [ 46 + (modulesPath + "/installer/netboot/netboot-minimal.nix") 47 + ]; 48 + 49 + services.openssh.enable = true; 50 + users.users.root.openssh.authorizedKeys.keys = [ 51 + "my-ssh-pubkey" 52 + ]; 53 + } 54 + ``` 55 + 56 + 57 + ```ShellSession 58 + nix-build '<nixpkgs/nixos>' \ 59 + --arg configuration ./configuration.nix 60 + --attr config.system.build.kexecTree 61 + ``` 62 + 63 + Make sure your `configuration.nix` does still import `netboot-minimal.nix` (or 64 + `netboot-base.nix`).
+1
nixos/doc/manual/installation/installing.chapter.md
··· 476 476 ```{=docbook} 477 477 <xi:include href="installing-usb.section.xml" /> 478 478 <xi:include href="installing-pxe.section.xml" /> 479 + <xi:include href="installing-kexec.section.xml" /> 479 480 <xi:include href="installing-virtualbox-guest.section.xml" /> 480 481 <xi:include href="installing-from-other-distro.section.xml" /> 481 482 <xi:include href="installing-behind-a-proxy.section.xml" />
-51
nixos/modules/installer/kexec/kexec-boot.nix
··· 1 - # This module exposes a config.system.build.kexecBoot attribute, 2 - # which returns a directory with kernel, initrd and a shell script 3 - # running the necessary kexec commands. 4 - 5 - # It's meant to be scp'ed to a machine with working ssh and kexec binary 6 - # installed. 7 - 8 - # This is useful for (cloud) providers where you can't boot a custom image, but 9 - # get some Debian or Ubuntu installation. 10 - 11 - { pkgs 12 - , modulesPath 13 - , config 14 - , ... 15 - }: 16 - { 17 - imports = [ 18 - (modulesPath + "/installer/netboot/netboot-minimal.nix") 19 - ]; 20 - 21 - config = { 22 - system.build.kexecBoot = 23 - let 24 - kexecScript = pkgs.writeScript "kexec-boot" '' 25 - #!/usr/bin/env bash 26 - if ! kexec -v >/dev/null 2>&1; then 27 - echo "kexec not found: please install kexec-tools" 2>&1 28 - exit 1 29 - fi 30 - SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 31 - kexec --load ''${SCRIPT_DIR}/bzImage \ 32 - --initrd=''${SCRIPT_DIR}/initrd.gz \ 33 - --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}" 34 - kexec -e 35 - ''; in 36 - pkgs.linkFarm "kexec-tree" [ 37 - { 38 - name = "initrd.gz"; 39 - path = "${config.system.build.netbootRamdisk}/initrd"; 40 - } 41 - { 42 - name = "bzImage"; 43 - path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}"; 44 - } 45 - { 46 - name = "kexec-boot"; 47 - path = kexecScript; 48 - } 49 - ]; 50 - }; 51 - }
+31
nixos/modules/installer/netboot/netboot.nix
··· 101 101 boot 102 102 ''; 103 103 104 + # A script invoking kexec on ./bzImage and ./initrd.gz. 105 + # Usually used through system.build.kexecTree, but exposed here for composability. 106 + system.build.kexecScript = pkgs.writeScript "kexec-boot" '' 107 + #!/usr/bin/env bash 108 + if ! kexec -v >/dev/null 2>&1; then 109 + echo "kexec not found: please install kexec-tools" 2>&1 110 + exit 1 111 + fi 112 + SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 113 + kexec --load ''${SCRIPT_DIR}/bzImage \ 114 + --initrd=''${SCRIPT_DIR}/initrd.gz \ 115 + --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}" 116 + kexec -e 117 + ''; 118 + 119 + # A tree containing initrd.gz, bzImage and a kexec-boot script. 120 + system.build.kexecTree = pkgs.linkFarm "kexec-tree" [ 121 + { 122 + name = "initrd.gz"; 123 + path = "${config.system.build.netbootRamdisk}/initrd"; 124 + } 125 + { 126 + name = "bzImage"; 127 + path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}"; 128 + } 129 + { 130 + name = "kexec-boot"; 131 + path = config.system.build.kexecScript; 132 + } 133 + ]; 134 + 104 135 boot.loader.timeout = 10; 105 136 106 137 boot.postBootCommands =
+7
nixos/release.nix
··· 151 151 # Build the initial ramdisk so Hydra can keep track of its size over time. 152 152 initialRamdisk = buildFromConfig ({ ... }: { }) (config: config.system.build.initialRamdisk); 153 153 154 + kexec = forMatchingSystems supportedSystems (system: (import lib/eval-config.nix { 155 + inherit system; 156 + modules = [ 157 + ./modules/installer/netboot/netboot-minimal.nix 158 + ]; 159 + }).config.system.build.kexecTree); 160 + 154 161 netboot = forMatchingSystems supportedSystems (system: makeNetboot { 155 162 module = ./modules/installer/netboot/netboot-minimal.nix; 156 163 inherit system;
+3 -4
nixos/tests/kexec.nix
··· 18 18 virtualisation.vlans = [ ]; 19 19 environment.systemPackages = [ pkgs.hello ]; 20 20 imports = [ 21 - "${modulesPath}/installer/kexec/kexec-boot.nix" 22 - "${modulesPath}/profiles/minimal.nix" 21 + "${modulesPath}/installer/netboot/netboot-minimal.nix" 23 22 ]; 24 23 }; 25 24 }; ··· 33 32 node1.connect() 34 33 node1.wait_for_unit("multi-user.target") 35 34 36 - # Check if the machine with kexec-boot.nix profile boots up 35 + # Check if the machine with netboot-minimal.nix profile boots up 37 36 node2.wait_for_unit("multi-user.target") 38 37 node2.shutdown() 39 38 40 39 # Kexec node1 to the toplevel of node2 via the kexec-boot script 41 40 node1.succeed('touch /run/foo') 42 41 node1.fail('hello') 43 - node1.execute('${nodes.node2.config.system.build.kexecBoot}/kexec-boot', check_return=False) 42 + node1.execute('${nodes.node2.config.system.build.kexecTree}/kexec-boot', check_return=False) 44 43 node1.succeed('! test -e /run/foo') 45 44 node1.succeed('hello') 46 45 node1.succeed('[ "$(hostname)" = "node2" ]')