Difference between revisions of "Netboot"
From NixOS Wiki
Erikarvstedt (talk | contribs) (update installer system. sshd has been enabled by default since nixpkgs a5872edf2f61d97a4ada2734d543eaaefe25c916) |
m (fix link to search.nixos.com by drop channel param) |
||
(14 intermediate revisions by 7 users not shown) | |||
Line 2: | Line 2: | ||
=== Example === | === Example === | ||
− | This example uses [https://github.com/danderson/netboot/tree/ | + | 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. |
+ | Create file <code>system.nix</code>: | ||
+ | <syntaxHighlight lang=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 | ||
+ | </syntaxHighlight> | ||
+ | |||
+ | Run pixiecore: | ||
<syntaxHighlight lang=bash> | <syntaxHighlight lang=bash> | ||
− | # | + | # Build pixiecore runner |
+ | nix build -f system.nix -o /tmp/run-pixiecore | ||
+ | |||
+ | # 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 | |
− | + | ||
+ | </syntaxHighlight> | ||
+ | |||
+ | === Another example === | ||
+ | File <code>netboot.nix</code>: | ||
+ | <syntaxHighlight lang=nix copy> | ||
+ | { 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.terminfo | ||
]; | ]; | ||
− | + | # users.users.nixos.openssh.authorizedKeys.keys = [ … ]; | |
− | + | # services.openssh = { ports = [2]; settings.PasswordAuthentication = false; }; | |
− | # users.users. | + | # 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> | |
− | + | version-module | |
− | + | example-configuration | |
− | + | configuration | |
]; | ]; | ||
− | + | }; | |
− | } | + | |
− | + | version-module = { config, ... }: { | |
+ | system.stateVersion = config.system.nixos.version; # be quiet | ||
+ | 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 | ||
+ | </syntaxHighlight> | ||
+ | |||
+ | Usage example: | ||
+ | <syntaxHighlight lang=bash> | ||
+ | # Build pixiecore runner | ||
+ | nix build -f netboot.nix -o /tmp/run-pixiecore | ||
− | nix build -o /tmp/ | + | # Build dnsmasq + pxelinux runner |
+ | nix build -f netboot.nix --arg legacy true -o /tmp/run-dnsmasq | ||
− | # | + | # Build for some ancient system with a serial console |
− | + | nix build -f 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 | |
− | |||
− | -- | ||
− | -- | ||
</syntaxHighlight> | </syntaxHighlight> | ||
=== See also === | === See also === | ||
− | NixOS: [https://search.nixos.org/options? | + | NixOS: [https://search.nixos.org/options?from=0&size=30&sort=relevance&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 08:13, 19 May 2025
Building and serving a netboot image
Example
This example uses Pixiecore for hosting, which works in an ordinary network environment with an existing DHCP server.
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
Run pixiecore:
# Build pixiecore runner
nix build -f system.nix -o /tmp/run-pixiecore
# 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
File 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.terminfo
];
# 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>
version-module
example-configuration
configuration
];
};
version-module = { config, ... }: {
system.stateVersion = config.system.nixos.version; # be quiet
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
Usage example:
# Build pixiecore runner
nix build -f netboot.nix -o /tmp/run-pixiecore
# Build dnsmasq + pxelinux runner
nix build -f netboot.nix --arg legacy true -o /tmp/run-dnsmasq
# Build for some ancient system with a serial console
nix build -f 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
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