Netboot: Difference between revisions
Appearance
m Updated link from 23.11 to 24.11, as the old link is dead. |
Link issue |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
== Building and serving a netboot image == | == Building and serving a netboot image == | ||
This provides an easy way to serve the NixOS installer over netboot, such as when you already have a working NixOS machine and want to install NixOS on a second machine connected to the same network. | |||
=== Example === | === Example === | ||
This example uses [https://github.com/danderson/netboot/tree/main/pixiecore Pixiecore] for hosting, which works in an ordinary network environment with an existing DHCP server. | This example uses [https://github.com/danderson/netboot/tree/main/pixiecore Pixiecore] for hosting, which works in an ordinary network environment with an existing DHCP server. | ||
Pixiecore will notice when the booted machine talks to the network's existing DHCP server, and send netboot information to it at that time. | |||
Create file <code>system.nix</code>: | Create file <code>system.nix</code>: | ||
Line 44: | Line 47: | ||
in | in | ||
run-pixiecore | run-pixiecore | ||
</syntaxHighlight> | </syntaxHighlight>Building:<syntaxhighlight lang="bash"> | ||
< | |||
# Build pixiecore runner | # Build pixiecore runner | ||
nix build | nix-build system.nix -o /tmp/run-pixiecore | ||
</syntaxhighlight>Running:<syntaxhighlight lang="bash"> | |||
# Open required firewall ports | # Open required firewall ports | ||
sudo iptables -w -I nixos-fw -p udp -m multiport --dports 67,69,4011 -j ACCEPT | sudo iptables -w -I nixos-fw -p udp -m multiport --dports 67,69,4011 -j ACCEPT | ||
Line 62: | Line 62: | ||
sudo iptables -w -D nixos-fw -p tcp -m tcp --dport 64172 -j ACCEPT | sudo iptables -w -D nixos-fw -p tcp -m tcp --dport 64172 -j ACCEPT | ||
</ | </syntaxhighlight> | ||
=== Another example === | === Another example === | ||
Line 114: | Line 114: | ||
mutt | mutt | ||
borgbackup | borgbackup | ||
rxvt-unicode | |||
]; | ]; | ||
# users.users.nixos.openssh.authorizedKeys.keys = [ … ]; | # users.users.nixos.openssh.authorizedKeys.keys = [ … ]; | ||
Line 127: | Line 127: | ||
modules = [ | modules = [ | ||
<nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix> | <nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix> | ||
# Reduce build time by ~7x (~1 minute instead of many minutes) by not using the highest compression (image is 5% larger). | |||
({ ... }: { netboot.squashfsCompression = "zstd -Xcompression-level 6"; }) | |||
version-module | version-module | ||
example-configuration | example-configuration | ||
Line 136: | Line 138: | ||
{ config, ... }: | { config, ... }: | ||
{ | { | ||
system.stateVersion = config.system.nixos.version; | system.stateVersion = builtins.substring 0 (builtins.stringLength "XX.XX") config.system.nixos.version; | ||
system.nixos.tags = [ name ]; | system.nixos.tags = [ name ]; | ||
}; | }; | ||
Line 205: | Line 207: | ||
in | in | ||
if legacy then run-dnsmasq else run-pixiecore}} | if legacy then run-dnsmasq else run-pixiecore|name=netboot.nix|lang=nix}} | ||
Building: | |||
< | <syntaxhighlight lang="bash"># Build pixiecore runner | ||
# Build pixiecore runner | nix-build netboot.nix -o /tmp/run-pixiecore | ||
nix build | |||
# Build dnsmasq + pxelinux runner | # Build dnsmasq + pxelinux runner | ||
nix build | nix-build netboot.nix --arg legacy true -o /tmp/run-dnsmasq | ||
# Build for some ancient system with a serial console | # Build for some ancient system with a serial console | ||
nix build | nix-build netboot.nix --arg name '"ancient-netboot"' -o /tmp/run-netboot \ | ||
--arg configuration 'import ./ancient-config.nix' \ | --arg configuration 'import ./ancient-config.nix' \ | ||
--arg legacy true --arg proxynets '["10.2.1.0"]' \ | --arg legacy true --arg proxynets '["10.2.1.0"]' \ | ||
--arg serialconsole true --arg serialport 3 --arg serialspeed 115200 | --arg serialconsole true --arg serialport 3 --arg serialspeed 115200</syntaxhighlight>Running: | ||
* Run the example exactly like the other example further up on the page. | |||
=== Troubleshooting === | |||
* Error "'''autoexec.ipxe... Operation not supported'''": See [https://github.com/NixOS/nixpkgs/pull/378513#pullrequestreview-3081586117 this issue]. | |||
=== See also === | === See also === | ||
NixOS: [https://search.nixos.org/options? | NixOS: [https://search.nixos.org/options?type=packages&query=services.pixiecore Pixiecore module]. | ||
NixOS manual: [https://nixos.org/nixos/manual/index.html#sec-booting-from-pxe PXE booting]. | NixOS manual: [https://nixos.org/nixos/manual/index.html#sec-booting-from-pxe PXE booting]. |
Latest revision as of 00:00, 3 August 2025
Building and serving a netboot image
This provides an easy way to serve the NixOS installer over netboot, such as when you already have a working NixOS machine and want to install NixOS on a second machine connected to the same network.
Example
This example uses Pixiecore for hosting, which works in an ordinary network environment with an existing DHCP server.
Pixiecore will notice when the booted machine talks to the network's existing DHCP server, and send netboot information to it at that time.
Create file system.nix
:
let
# NixOS 22.11 as of 2023-01-12
nixpkgs = builtins.getFlake "github:nixos/nixpkgs/54644f409ab471e87014bb305eac8c50190bcf48";
sys = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
({ config, pkgs, lib, modulesPath, ... }: {
imports = [
(modulesPath + "/installer/netboot/netboot-minimal.nix")
];
config = {
## Some useful options for setting up a new system
# services.getty.autologinUser = lib.mkForce "root";
# users.users.root.openssh.authorizedKeys.keys = [ ... ];
# console.keyMap = "de";
# hardware.video.hidpi.enable = true;
system.stateVersion = config.system.nixos.release;
};
})
];
};
run-pixiecore = let
hostPkgs = if sys.pkgs.system == builtins.currentSystem
then sys.pkgs
else nixpkgs.legacyPackages.${builtins.currentSystem};
build = sys.config.system.build;
in hostPkgs.writers.writeBash "run-pixiecore" ''
exec ${hostPkgs.pixiecore}/bin/pixiecore \
boot ${build.kernel}/bzImage ${build.netbootRamdisk}/initrd \
--cmdline "init=${build.toplevel}/init loglevel=4" \
--debug --dhcp-no-bind \
--port 64172 --status-port 64172 "$@"
'';
in
run-pixiecore
Building:
# Build pixiecore runner
nix-build system.nix -o /tmp/run-pixiecore
Running:
# Open required firewall ports
sudo iptables -w -I nixos-fw -p udp -m multiport --dports 67,69,4011 -j ACCEPT
sudo iptables -w -I nixos-fw -p tcp -m tcp --dport 64172 -j ACCEPT
# Run pixiecore
sudo $(realpath /tmp/run-pixiecore)
# Close ports
sudo iptables -w -D nixos-fw -p udp -m multiport --dports 67,69,4011 -j ACCEPT
sudo iptables -w -D nixos-fw -p tcp -m tcp --dport 64172 -j ACCEPT
Another example
❄︎ netboot.nix
{
name ? "netboot",
arch ? "x86_64-linux",
configuration ? _: { }, # --arg configuration 'import ./netboot-config.nix'
legacy ? false, # variation with pxelinux and dnsmasq for older systems
cmdline ? [ ],
loglevel ? 4,
pixiecoreport ? 64172,
proxynets ? [ "192.168.0.0" ],
serialconsole ? false,
serialport ? 0,
serialspeed ? 9600,
nixpkgs ? import <nixpkgs> { },
...
}:
with nixpkgs;
with lib;
let
example-configuration =
{ pkgs, config, ... }:
with pkgs;
{
config = {
environment.systemPackages = [
mtr
bridge-utils
vlan
ethtool
jwhois
sipcalc
netcat-openbsd
tsocks
psmisc
pciutils
usbutils
lm_sensors
dmidecode
microcom
unar
mkpasswd
ripgrep
wget
rsync
sshfs-fuse
iperf3
mc
mutt
borgbackup
rxvt-unicode
];
# users.users.nixos.openssh.authorizedKeys.keys = [ … ];
# services.openssh = { ports = [2]; settings.PasswordAuthentication = false; };
# virtualisation.lxc.enable = true;
};
};
config = import <nixpkgs/nixos/lib/eval-config.nix> {
# see <nixpkgs/nixos/release.nix>
system = arch;
modules = [
<nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix>
# Reduce build time by ~7x (~1 minute instead of many minutes) by not using the highest compression (image is 5% larger).
({ ... }: { netboot.squashfsCompression = "zstd -Xcompression-level 6"; })
version-module
example-configuration
configuration
];
};
version-module =
{ config, ... }:
{
system.stateVersion = builtins.substring 0 (builtins.stringLength "XX.XX") config.system.nixos.version;
system.nixos.tags = [ name ];
};
run-pixiecore = writeShellScript "${name}-run-pixiecore" ''
exec ${pixiecore}/bin/pixiecore \
boot ${kernel} ${initrd} \
--cmdline "${cmd-line}" \
--debug --dhcp-no-bind --log-timestamps \
--port ${toString pixiecoreport} \
--status-port ${toString pixiecoreport} "$@"
'';
run-dnsmasq = writeShellScript "${name}-run-dnsmasq" ''
exec ${dnsmasq}/bin/dnsmasq \
-d -k --no-daemon -C "${dnsmasq-conf}" "$@"
'';
tftp-root = linkFarm "${name}-tftp-root" (
mapAttrsToList (name: path: { inherit name path; }) {
"pxelinux.cfg/default" = pxelinux-cfg;
"pxelinux.0" = "syslinux/pxelinux.0";
"syslinux" = "${syslinux}/share/syslinux";
"bzImage" = kernel;
"initrd" = initrd;
}
);
dnsmasq-conf = writeText "${name}-dnsmasq-conf" ''
pxe-prompt="Booting NixOS..",1
local-service=net
dhcp-boot=pxelinux.0
${flip concatMapStrings proxynets (net: ''
dhcp-range=${net},proxy
'')}
dhcp-no-override
dhcp-leasefile=/dev/null
log-dhcp
enable-tftp
tftp-port-range=6900,6999
tftp-root=${tftp-root}
'';
cmd-line = concatStringsSep " " (
[
"init=${build.toplevel}/init"
"loglevel=${toString loglevel}"
]
++ optional serialconsole "console=ttyS${toString serialport},${toString serialspeed}"
++ cmdline
);
pxelinux-cfg = writeText "${name}-pxelinux.cfg" ''
${optionalString serialconsole "serial ${toString serialport} ${toString serialspeed}"}
console 1
prompt 1
timeout 37
default NixOS
label NixOS
kernel bzImage
append initrd=initrd ${cmd-line}
'';
build = config.config.system.build;
kernel = "${build.kernel}/${kernel-target}";
kernel-target = config.pkgs.stdenv.hostPlatform.linux-kernel.target;
initrd = "${build.netbootRamdisk}/initrd";
in
if legacy then run-dnsmasq else run-pixiecore
Building:
# Build pixiecore runner
nix-build netboot.nix -o /tmp/run-pixiecore
# Build dnsmasq + pxelinux runner
nix-build netboot.nix --arg legacy true -o /tmp/run-dnsmasq
# Build for some ancient system with a serial console
nix-build netboot.nix --arg name '"ancient-netboot"' -o /tmp/run-netboot \
--arg configuration 'import ./ancient-config.nix' \
--arg legacy true --arg proxynets '["10.2.1.0"]' \
--arg serialconsole true --arg serialport 3 --arg serialspeed 115200
Running:
- Run the example exactly like the other example further up on the page.
Troubleshooting
- Error "autoexec.ipxe... Operation not supported": See this issue.
See also
NixOS: Pixiecore module.
NixOS manual: PXE booting.
netboot.xyz
There is now official netboot.xyz support. Just select NixOS from Linux installs and you should be ready to go.
Note: Your iPXE must be recent enough to support https:// links