every.channel/docs/NUC_UNIFI_NETBOOT.md

5.2 KiB

NUC Fleet Netboot (Unifi)

This runbook provisions x86_64 NUCs from runner netboot artifacts without USB image flashing.

Supported modes:

  • ProxyDHCP mode: recommended when you want automatic stage-1/2 iPXE handling.
  • UniFi-only mode: DHCP options 66/67 in UniFi, no ProxyDHCP.

Prerequisites

  • Linux boot server on the same VLAN/L2 domain as the NUCs.
  • Unifi network with DHCP enabled.
  • Local DNS record on that VLAN: boot.every.channel -> <boot-server-ip>.
  • curl, tar, python3, dnsmasq installed on the boot server.
  • For UniFi-only mode with reliable chainloading: git and make to build embedded iPXE.
  • openssl (or equivalent) if you want generated chain tokens.
  • Runner netboot artifact published to Forgejo Releases (or available as local tarball).

Instead of running scripts manually, use the exported NixOS module and keep netboot staging/serving declarative:

{
  imports = [ every-channel.nixosModules.ec-netboot ];

  services.every-channel.netboot = {
    enable = true;
    listenIP = "10.20.30.2";
    interface = "enp195s0";
    hostname = "boot.every.channel";
    tftpBootFilename = "ec-ipxe.efi";
    httpAllowedCIDRs = [ "10.20.30.0/24" ];
    chainTokenFile = "/run/agenix/every-channel-netboot-chain-token";

    # UniFi-only mode by default (no ProxyDHCP):
    proxyDhcp.enable = false;

    release.host = "https://git.every.channel";
    release.repo = "every-channel/every.channel";
    # release.tag = "boot-v2026.03.02"; # optional pin
    # release.tokenFile = "/run/agenix/forgejo-api-token"; # optional private repo token
  };
}

Operational commands:

sudo systemctl start every-channel-netboot-stage.service
sudo systemctl restart every-channel-netboot.service
sudo systemctl status every-channel-netboot.service

If you prefer ProxyDHCP mode:

services.every-channel.netboot.proxyDhcp.enable = true;
services.every-channel.netboot.proxyDhcp.subnet = "10.20.30.0/24";

1) Build embedded iPXE (UniFi-only mode)

This removes iPXE boot loops without requiring ProxyDHCP.

EVERY_CHANNEL_NETBOOT_HOSTNAME=boot.every.channel \
EVERY_CHANNEL_NETBOOT_HTTP_PORT=8080 \
EVERY_CHANNEL_NETBOOT_CHAIN_TOKEN="$(openssl rand -hex 16)" \
./scripts/netboot-build-ipxe.sh

Output:

  • tmp/netboot/tftp/ec-ipxe.efi (use this as DHCP option 67 filename)

2) Stage runner netboot artifacts

EVERY_CHANNEL_NETBOOT_HOSTNAME=boot.every.channel \
EVERY_CHANNEL_NETBOOT_CHAIN_TOKEN="<same-token-as-step-1>" \
EVERY_CHANNEL_NETBOOT_IPXE_EFI_PATH=tmp/netboot/tftp/ec-ipxe.efi \
EVERY_CHANNEL_NETBOOT_IPXE_EFI_FILENAME=ec-ipxe.efi \
./scripts/netboot-stage.sh

Optional inputs:

  • EVERY_CHANNEL_NETBOOT_RELEASE_TAG=boot-v2026.02.28
  • EVERY_CHANNEL_NETBOOT_TARBALL=/path/to/ec-runner-x86_64-netboot-....tar.gz
  • EVERY_CHANNEL_FORGE_TOKEN=<token> for private releases
  • EVERY_CHANNEL_NETBOOT_ALLOW_REMOTE_IPXE=true only if you intentionally want to download iPXE from URL
  • EVERY_CHANNEL_IPXE_EFI_SHA256=<sha256> to pin iPXE binary integrity

This stages:

  • tmp/netboot/http/{kernel,initrd,netboot.ipxe}
  • tmp/netboot/tftp/ec-ipxe.efi

3) Serve HTTP + TFTP

UniFi-only mode (no ProxyDHCP):

sudo \
  EVERY_CHANNEL_NETBOOT_LISTEN_IP=10.20.30.2 \
  EVERY_CHANNEL_NETBOOT_INTERFACE=eth0 \
  EVERY_CHANNEL_NETBOOT_HOSTNAME=boot.every.channel \
  EVERY_CHANNEL_NETBOOT_CHAIN_TOKEN="<same-token-as-step-1>" \
  EVERY_CHANNEL_NETBOOT_HTTP_ALLOWED_CIDRS=10.20.30.0/24 \
  EVERY_CHANNEL_NETBOOT_PROXY_DHCP=false \
  EVERY_CHANNEL_NETBOOT_TFTP_BOOT_FILENAME=ec-ipxe.efi \
  ./scripts/netboot-serve.sh

ProxyDHCP mode:

sudo \
  EVERY_CHANNEL_NETBOOT_LISTEN_IP=10.20.30.2 \
  EVERY_CHANNEL_NETBOOT_INTERFACE=eth0 \
  EVERY_CHANNEL_NETBOOT_PROXY_SUBNET=10.20.30.0/24 \
  EVERY_CHANNEL_NETBOOT_HOSTNAME=boot.every.channel \
  EVERY_CHANNEL_NETBOOT_CHAIN_TOKEN="<same-token-as-step-1>" \
  EVERY_CHANNEL_NETBOOT_HTTP_ALLOWED_CIDRS=10.20.30.0/24 \
  EVERY_CHANNEL_NETBOOT_PROXY_DHCP=true \
  EVERY_CHANNEL_NETBOOT_TFTP_BOOT_FILENAME=ec-ipxe.efi \
  ./scripts/netboot-serve.sh

4) UniFi settings (you do this)

UniFi-only mode:

  • Network Boot: enabled
  • Server: boot.every.channel (or boot server IP)
  • Filename: ec-ipxe.efi
  • TFTP Server: boot.every.channel

ProxyDHCP mode:

  • leave UniFi boot/TFTP options unset.

NUC BIOS:

  • Enable UEFI PXE boot.
  • Disable Legacy/CSM where possible.
  • Put network boot first for initial install.

Security hardening

  • Keep provisioning on an isolated VLAN.
  • Allow only required ports from NUC VLAN to boot server: UDP 69, TCP 8080 (and DHCP if ProxyDHCP mode).
  • Keep provisioning services up only during rollout, then stop them.
  • Use EVERY_CHANNEL_NETBOOT_HTTP_ALLOWED_CIDRS to limit HTTP artifact access to NUC subnet(s).
  • Use EVERY_CHANNEL_NETBOOT_CHAIN_TOKEN so only tokened iPXE chain requests receive netboot.ipxe.
  • Use checksum verification in netboot-stage.sh (enabled by default when release has SHA256SUMS.txt).
  • netboot-stage.sh now defaults to local iPXE binaries; remote URL download requires explicit opt-in.
  • Prefer embedded ec-ipxe.efi with fixed chain target over generic unsigned internet binaries.
  • If Secure Boot is required, use signed boot chain and keys for your environment (outside this basic runbook).