diff --git a/nixos/doc/manual/from_md/installation/installing-kexec.section.xml b/nixos/doc/manual/from_md/installation/installing-kexec.section.xml
new file mode 100644
index 000000000000..46ea0d59b6c3
--- /dev/null
+++ b/nixos/doc/manual/from_md/installation/installing-kexec.section.xml
@@ -0,0 +1,94 @@
+
+ Booting
into NixOS via kexec
+
+ In some cases, your system might already be booted into/preinstalled
+ with another Linux distribution, and booting NixOS by attaching an
+ installation image is quite a manual process.
+
+
+ This is particularly useful for (cloud) providers where you can’t
+ boot a custom image, but get some Debian or Ubuntu installation.
+
+
+ In these cases, it might be easier to use kexec
+ to jump into NixOS
from the running system, which
+ only assumes bash and kexec to
+ be installed on the machine.
+
+
+ Note that kexec may not work correctly on some hardware, as devices
+ are not fully re-initialized in the process. In practice, this
+ however is rarely the case.
+
+
+ To build the necessary files from your current version of nixpkgs,
+ you can run:
+
+
+nix-build -A kexec.x86_64-linux '<nixpkgs/nixos/release.nix>'
+
+
+ This will create a result directory containing
+ the following:
+
+
+
+
+ bzImage (the Linux kernel)
+
+
+
+
+ initrd (the initrd file)
+
+
+
+
+ kexec-boot (a shellscript invoking
+ kexec)
+
+
+
+
+ These three files are meant to be copied over to the other already
+ running Linux Distribution.
+
+
+ Note it’s symlinks pointing elsewhere, so cd in,
+ and use scp * root@$destination to copy it over,
+ rather than rsync.
+
+
+ Once you finished copying, execute kexec-boot
+ on the destination, and after some seconds, the
+ machine should be booting into an (ephemeral) NixOS installation
+ medium.
+
+
+ In case you want to describe your own system closure to kexec into,
+ instead of the default installer image, you can build your own
+ configuration.nix:
+
+
+{ modulesPath, ... }: {
+ imports = [
+ (modulesPath + "/installer/netboot/netboot-minimal.nix")
+ ];
+
+ services.openssh.enable = true;
+ users.users.root.openssh.authorizedKeys.keys = [
+ "my-ssh-pubkey"
+ ];
+}
+
+
+nix-build '<nixpkgs/nixos>' \
+ --arg configuration ./configuration.nix
+ --attr config.system.build.kexecTree
+
+
+ Make sure your configuration.nix does still
+ import netboot-minimal.nix (or
+ netboot-base.nix).
+
+
diff --git a/nixos/doc/manual/from_md/installation/installing.chapter.xml b/nixos/doc/manual/from_md/installation/installing.chapter.xml
index aee0b30a7076..19ff841f5a67 100644
--- a/nixos/doc/manual/from_md/installation/installing.chapter.xml
+++ b/nixos/doc/manual/from_md/installation/installing.chapter.xml
@@ -638,6 +638,7 @@ $ passwd eelco
Additional installation notes
+
diff --git a/nixos/doc/manual/installation/installing-kexec.section.md b/nixos/doc/manual/installation/installing-kexec.section.md
new file mode 100644
index 000000000000..286cbbda6a69
--- /dev/null
+++ b/nixos/doc/manual/installation/installing-kexec.section.md
@@ -0,0 +1,64 @@
+# "Booting" into NixOS via kexec {#sec-booting-via-kexec}
+
+In some cases, your system might already be booted into/preinstalled with
+another Linux distribution, and booting NixOS by attaching an installation
+image is quite a manual process.
+
+This is particularly useful for (cloud) providers where you can't boot a custom
+image, but get some Debian or Ubuntu installation.
+
+In these cases, it might be easier to use `kexec` to "jump into NixOS" from the
+running system, which only assumes `bash` and `kexec` to be installed on the
+machine.
+
+Note that kexec may not work correctly on some hardware, as devices are not
+fully re-initialized in the process. In practice, this however is rarely the
+case.
+
+To build the necessary files from your current version of nixpkgs,
+you can run:
+
+```ShellSession
+nix-build -A kexec.x86_64-linux ''
+```
+
+This will create a `result` directory containing the following:
+ - `bzImage` (the Linux kernel)
+ - `initrd` (the initrd file)
+ - `kexec-boot` (a shellscript invoking `kexec`)
+
+These three files are meant to be copied over to the other already running
+Linux Distribution.
+
+Note it's symlinks pointing elsewhere, so `cd` in, and use
+`scp * root@$destination` to copy it over, rather than rsync.
+
+Once you finished copying, execute `kexec-boot` *on the destination*, and after
+some seconds, the machine should be booting into an (ephemeral) NixOS
+installation medium.
+
+In case you want to describe your own system closure to kexec into, instead of
+the default installer image, you can build your own `configuration.nix`:
+
+```nix
+{ modulesPath, ... }: {
+ imports = [
+ (modulesPath + "/installer/netboot/netboot-minimal.nix")
+ ];
+
+ services.openssh.enable = true;
+ users.users.root.openssh.authorizedKeys.keys = [
+ "my-ssh-pubkey"
+ ];
+}
+```
+
+
+```ShellSession
+nix-build '' \
+ --arg configuration ./configuration.nix
+ --attr config.system.build.kexecTree
+```
+
+Make sure your `configuration.nix` does still import `netboot-minimal.nix` (or
+`netboot-base.nix`).
diff --git a/nixos/doc/manual/installation/installing.chapter.md b/nixos/doc/manual/installation/installing.chapter.md
index 8a46d68ae3ba..7e830f8e4583 100644
--- a/nixos/doc/manual/installation/installing.chapter.md
+++ b/nixos/doc/manual/installation/installing.chapter.md
@@ -476,6 +476,7 @@ With a partitioned disk.
```{=docbook}
+
diff --git a/nixos/modules/installer/kexec/kexec-boot.nix b/nixos/modules/installer/kexec/kexec-boot.nix
deleted file mode 100644
index 2d062214efc2..000000000000
--- a/nixos/modules/installer/kexec/kexec-boot.nix
+++ /dev/null
@@ -1,51 +0,0 @@
-# This module exposes a config.system.build.kexecBoot attribute,
-# which returns a directory with kernel, initrd and a shell script
-# running the necessary kexec commands.
-
-# It's meant to be scp'ed to a machine with working ssh and kexec binary
-# installed.
-
-# This is useful for (cloud) providers where you can't boot a custom image, but
-# get some Debian or Ubuntu installation.
-
-{ pkgs
-, modulesPath
-, config
-, ...
-}:
-{
- imports = [
- (modulesPath + "/installer/netboot/netboot-minimal.nix")
- ];
-
- config = {
- system.build.kexecBoot =
- let
- kexecScript = pkgs.writeScript "kexec-boot" ''
- #!/usr/bin/env bash
- if ! kexec -v >/dev/null 2>&1; then
- echo "kexec not found: please install kexec-tools" 2>&1
- exit 1
- fi
- SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
- kexec --load ''${SCRIPT_DIR}/bzImage \
- --initrd=''${SCRIPT_DIR}/initrd.gz \
- --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
- kexec -e
- ''; in
- pkgs.linkFarm "kexec-tree" [
- {
- name = "initrd.gz";
- path = "${config.system.build.netbootRamdisk}/initrd";
- }
- {
- name = "bzImage";
- path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
- }
- {
- name = "kexec-boot";
- path = kexecScript;
- }
- ];
- };
-}
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
index a459e7304cd4..3127bdc436f9 100644
--- a/nixos/modules/installer/netboot/netboot.nix
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -101,6 +101,37 @@ with lib;
boot
'';
+ # A script invoking kexec on ./bzImage and ./initrd.gz.
+ # Usually used through system.build.kexecTree, but exposed here for composability.
+ system.build.kexecScript = pkgs.writeScript "kexec-boot" ''
+ #!/usr/bin/env bash
+ if ! kexec -v >/dev/null 2>&1; then
+ echo "kexec not found: please install kexec-tools" 2>&1
+ exit 1
+ fi
+ SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+ kexec --load ''${SCRIPT_DIR}/bzImage \
+ --initrd=''${SCRIPT_DIR}/initrd.gz \
+ --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
+ kexec -e
+ '';
+
+ # A tree containing initrd.gz, bzImage and a kexec-boot script.
+ system.build.kexecTree = pkgs.linkFarm "kexec-tree" [
+ {
+ name = "initrd.gz";
+ path = "${config.system.build.netbootRamdisk}/initrd";
+ }
+ {
+ name = "bzImage";
+ path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
+ }
+ {
+ name = "kexec-boot";
+ path = config.system.build.kexecScript;
+ }
+ ];
+
boot.loader.timeout = 10;
boot.postBootCommands =
diff --git a/nixos/release.nix b/nixos/release.nix
index e0d782bcaec3..beafdf9ff5bc 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -151,6 +151,13 @@ in rec {
# Build the initial ramdisk so Hydra can keep track of its size over time.
initialRamdisk = buildFromConfig ({ ... }: { }) (config: config.system.build.initialRamdisk);
+ kexec = forMatchingSystems supportedSystems (system: (import lib/eval-config.nix {
+ inherit system;
+ modules = [
+ ./modules/installer/netboot/netboot-minimal.nix
+ ];
+ }).config.system.build.kexecTree);
+
netboot = forMatchingSystems supportedSystems (system: makeNetboot {
module = ./modules/installer/netboot/netboot-minimal.nix;
inherit system;
diff --git a/nixos/tests/kexec.nix b/nixos/tests/kexec.nix
index 7238a9f58e09..3f5a6f521af0 100644
--- a/nixos/tests/kexec.nix
+++ b/nixos/tests/kexec.nix
@@ -18,8 +18,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
virtualisation.vlans = [ ];
environment.systemPackages = [ pkgs.hello ];
imports = [
- "${modulesPath}/installer/kexec/kexec-boot.nix"
- "${modulesPath}/profiles/minimal.nix"
+ "${modulesPath}/installer/netboot/netboot-minimal.nix"
];
};
};
@@ -33,14 +32,14 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
node1.connect()
node1.wait_for_unit("multi-user.target")
- # Check if the machine with kexec-boot.nix profile boots up
+ # Check if the machine with netboot-minimal.nix profile boots up
node2.wait_for_unit("multi-user.target")
node2.shutdown()
# Kexec node1 to the toplevel of node2 via the kexec-boot script
node1.succeed('touch /run/foo')
node1.fail('hello')
- node1.execute('${nodes.node2.config.system.build.kexecBoot}/kexec-boot', check_return=False)
+ node1.execute('${nodes.node2.config.system.build.kexecTree}/kexec-boot', check_return=False)
node1.succeed('! test -e /run/foo')
node1.succeed('hello')
node1.succeed('[ "$(hostname)" = "node2" ]')