A personal homelab network-boot environment: iPXE menu generation for live-booting Linux distros over the LAN, a custom Arch Linux live image, a Windows 11 iSCSI-boot image builder, declarative workstation provisioning, and Mellanox NIC firmware tooling.
Three roles, three sets of scripts:
| Host | Role | Runs |
|---|---|---|
PXE server (Fedora Linux, 192.168.1.11) |
TFTP (/srv/tftp), HTTP on :81 (/srv/http/pxe), iSCSI target (LIO/targetcli) |
update-pxe-images.sh, build_archiso.sh |
| Windows build machine | Builds the Win11 iSCSI boot image | build_win11pxe.ps1 + the Get-*.ps1 scrapers |
| Clients | UEFI/BIOS PXE boot into the generated menu | — |
Boot flow: DHCP → TFTP (ipxe.efi / undionly.kpxe) → default.ipxe menu →
live boot from public mirrors / netboot.xyz assets / local HTTP artifacts /
Windows 11 via iSCSI sanboot.
Scrapes the Purdue PLUG mirror for the current Debian, Fedora, Rocky, and Ubuntu LTS
live ISOs (x86_64 and ARM64), resolves matching netboot.xyz kernel/initrd release
assets via the GitHub API, and generates /srv/tftp/default.ipxe with per-distro
menu entries plus Clonezilla, netboot.xyz, and an iPXE shell. Finishes with a
HEAD-check pass over the embedded URLs.
Feature toggles (edit the variables at the top of the script):
ENABLE_TFTP_BOOTSTRAP— download iPXE binaries (snponly.efisaved asipxe.efi,undionly.kpxe, ARM64 EFI) into the TFTP dir.ENABLE_LOCAL_ARCH— copy a local Arch kernel/initramfs from/srv/archand add an NBD-root boot entry.ENABLE_CUSTOM_ARCHISO— add menu entries for the custom archiso image (below).ENABLE_WIN11_PXE— add the Windows 11 iSCSIsanbootentry.
If /srv/http/pxe or /srv/tftp is not writable (e.g. run without root), the script
falls back to ./pxe_test/ — useful as a dry run.
Run as Administrator with PowerShell 7 on a Windows machine:
.\build_win11pxe.ps1 -IsoPath .\Win11_25H2_English_x64.iso -OutPath .\win11_netboot.vhdx -ImageIndex 6 [-Drivers] [-Updates]Creates a dynamic VHDX (GPT: ESP / MSR / NTFS), applies the Windows image with DISM,
writes boot files with bcdboot, then edits the offline SYSTEM/SOFTWARE hives:
promotes iSCSI/NIC/storage services to boot-start, sets the SAN policy, disables
BitLocker auto-encryption, injects LabConfig hardware-check bypasses and BypassNRO,
and drops an unattend.xml (local lan admin account with autologon) plus a
SetupComplete.cmd that disables NIC power management.
-Driversruns everyGet-*Drivers.ps1scraper in parallel and injects the results withDISM /Add-Driver.-UpdatesrunsGet-Win11CumulativeUpdates.ps1and injects the latest cumulative update (with checkpoint prerequisites) via folder-basedDISM /Add-Package.
Serving the image: convert the VHDX to a raw image first
(qemu-img convert -f vhdx -O raw win11_netboot.vhdx win11.img) and expose it as an
LIO/targetcli backstore behind iqn.2026-02.lan.pxe:win11. LIO serves file bytes
raw — it does not parse the VHDX container. The targetcli configuration itself is
not versioned in this repo.
Boot NIC (-BootAdapterGuid): a DISM-applied image has never run PnP, so its
boot NIC exists only as a Services key and the kernel cannot bind it at boot —
the classic 0x7B INACCESSIBLE_BOOT_DEVICE over iSCSI. The script fixes this with
the offline DISM /Add-NetAdapter verb (the same one Windows Setup runs when it
detects an iBFT), which needs the boot NIC's adapter GUID:
# on a machine / WinPE where that NIC is live:
wmic nic get GUID,Name,ServiceName
# then:
.\build_win11pxe.ps1 -IsoPath ... -Drivers -Updates -BootAdapterGuid '{GUID}'Without -BootAdapterGuid the script warns and the image will almost certainly
0x7B. Deferred: auto-detecting/validating the correct adapter from hardware
IDs is not yet implemented — the GUID is supplied by hand for now. If
/Add-NetAdapter is unavailable on your DISM build, install Windows by booting
Setup over the sanhook'd LUN instead (see the notes block at the end of
build_win11pxe.ps1).
Driver/update scrapers (Microsoft Update Catalog):
| Script | Covers |
|---|---|
Get-IntelEthernetDrivers.ps1 |
Intel I210/I219/I225/I226, X540/X550, X710, E810, AVF |
Get-RealtekEthernetDrivers.ps1 |
RTL8125/8126/8127/8168 PCIe, RTL8153/8156/8157 USB |
Get-MarvellEthernetDrivers.ps1 |
Aquantia/Marvell AQC107/AQC113 PCIe, AQC111U USB |
Get-IntelWiFiDrivers.ps1 |
Intel Wi-Fi 6/6E/7 (post-boot convenience) |
Get-MediatekWiFiDrivers.ps1 |
MediaTek MT79xx Wi-Fi (post-boot convenience) |
Get-QualcommWiFiDrivers.ps1 |
Qualcomm WCN/FastConnect Wi-Fi (post-boot convenience) |
Get-Win11CumulativeUpdates.ps1 |
Latest monthly CU + checkpoint chain + SSU per Windows version |
Status: the 0x7B INACCESSIBLE_BOOT_DEVICE failure (DISM apply + service-key
edits load the NIC driver but never PnP-install it) is addressed by the
-BootAdapterGuid / DISM /Add-NetAdapter step described above. Supplying the boot
NIC's adapter GUID is currently a manual step (auto-detection deferred); if the
verb is unavailable on your DISM build, fall back to installing via Setup over the
iBFT-attached LUN.
Run as root on an Arch system with archiso installed. Clones the releng profile,
applies customizations (local pacman.conf, zstd squashfs, archlinux-custom ISO
name, a large multi-desktop package set), and injects a systemd generator +
configure-desktop.sh that enable exactly one desktop environment per boot based on
the desktop= kernel argument (gnome, kde, xfce, sway, enlightenment — selected by
the corresponding iPXE menu entry). Outputs the ISO plus extracted
vmlinuz-linux / initramfs-linux.img / airootfs.sfs into /srv/http/pxe/archiso
(or ./archiso when not on the server) for HTTP PXE boot.
Applied with comtrya; run from the repo root (several actions use repo-relative paths):
arch_workstation.yaml— Arch packages (incl. AUR via yay), GNOME config, services, config files fromfiles/.fedora_workstation.yaml— Fedora repos (files/etc/yum.repos.d/), dnf/copr packages, flatpaks, GNOME config.win11_workstation.yaml— winget package set; wires in the Windows helper scripts.
Windows helpers:
enable-openssh-win11.ps1— installs the OpenSSH Server capability, starts/enablessshd, ensures the firewall rule, sets PowerShell as the default SSH shell.enable-hyperv-win11home.ps1— installs Hyper-V on Windows 11 Home from the on-disk servicing packages (re-run after feature updates).
Dotfiles and system config consumed by the manifests: bashrc, vimrc, grub
defaults, etc/pacman.conf, etc/locale.conf, etc/sysctl.d/99-inotify.conf,
etc/cron.daily/pacman-update (unattended Arch updates + reboot scheduling),
etc/dconf/db/gdm.d/10-font-settings, Fedora repo definitions under
etc/yum.repos.d/, and config/Antigravity/User/settings.json.
Interactive detector/cross-flasher for ConnectX-3 through ConnectX-7 NICs. Queries
devices with mstflint, downloads stock NVIDIA firmware, flashes (including
OEM→stock cross-flash with -allow_psid_change after explicit confirmation), and
configures UEFI/legacy boot ROM options via mstconfig. Requires root, mstflint,
and pciutils. Firmware flashing is inherently risky — read every prompt.
- One-time: point DHCP at the TFTP server (
ipxe.efifor UEFI,undionly.kpxefor BIOS); setENABLE_TFTP_BOOTSTRAP=truefor the first run to fetch the binaries. - Periodically (cron or manual):
./update-pxe-images.shon the server to refresh distro versions and regenerate the menu. - Optional:
sudo ./build_archiso.shto rebuild the custom Arch image; enableENABLE_CUSTOM_ARCHISO. - Optional: build the Win11 VHDX on the Windows machine, convert to raw, configure
the iSCSI target, enable
ENABLE_WIN11_PXE. - After installing an OS on a workstation:
comtrya applywith the matching*_workstation.yamlfrom the repo root.
update-pxe-images.shwrites to the live server paths and needs root; pass--test(orDRY_RUN=true) to generate into./pxe_test/instead. It publishesdefault.ipxeatomically and keeps a.bakof the previous menu. SetGITHUB_TOKENto avoid the 60-req/hr unauthenticated GitHub API rate limit.- Lint locally the way CI does (
.github/workflows/lint.yml):shellcheck -S warningon the shell scripts andInvoke-ScriptAnalyzeron the PowerShell. - Build artifacts (
*.vhdx,*.iso,*.img,*.raw,pxe_test/,archiso/,custom_archiso/) are gitignored. - Server address/ports, mirror URLs, and the iSCSI IQN namespace
(
iqn.2026-02.lan.pxe) are currently hard-coded constants at the top ofupdate-pxe-images.shand inside the Win11 stanza. - The Win11 image intentionally trades security for LAN convenience (blank-password autologon admin, hardware-check bypasses, no CHAP on the target) — do not expose any of this beyond a trusted network.