Reorganize the brownfield repository, remove retired and generated artifacts, harden ignore rules, and record the GitOps/IaC redesign.
110 lines
6.1 KiB
Markdown
110 lines
6.1 KiB
Markdown
# netboot
|
|
|
|
Self-hosted [netboot.xyz](https://netboot.xyz) PXE boot server for the LAN, using the
|
|
official appliance container plus a `dnsmasq` proxyDHCP so it coexists with the existing
|
|
DHCP server (the **NEC IX router**, which is left untouched).
|
|
|
|
## Architecture
|
|
|
|
The NEC IX router keeps leasing IPs. `dnsmasq` runs in **proxyDHCP** mode and only answers
|
|
the PXE/boot part of the conversation, pointing clients at this host (`192.168.10.127`).
|
|
|
|
Client type (announced via DHCP option 60/93) → what it gets:
|
|
|
|
| Client | Transport | File |
|
|
|------------------------------------------|-----------|----------------------------------------------|
|
|
| Legacy BIOS (`arch 0`) | TFTP | `netboot.xyz.kpxe` |
|
|
| UEFI, normal PXE (`arch 7/9`) | TFTP | `netboot.xyz.efi` |
|
|
| UEFI with HTTP Boot (`vendor HTTPClient`)| HTTP | `http://192.168.10.127:8080/menus/netboot.xyz.efi` |
|
|
|
|
Fallback is automatic: a UEFI box only announces `HTTPClient` when HTTP Boot is actually
|
|
enabled/supported; otherwise it does normal PXE and lands on the TFTP `.efi` branch.
|
|
|
|
This is a **two-stage** chain, which matters for the dnsmasq config:
|
|
|
|
1. **Firmware → netboot.xyz iPXE.** Raw firmware (not iPXE) gets the binary above. proxyDHCP
|
|
*requires* `pxe-service` here — plain `dhcp-boot` produces no boot offer in proxy mode.
|
|
2. **netboot.xyz iPXE → menu.** The loaded `.efi`/`.kpxe` re-does DHCP (announcing itself via
|
|
option 175) and dnsmasq answers with `dhcp-boot=tag:ipxe,netboot.xyz.efi,,192.168.10.127`.
|
|
Two details matter, both dictated by the bootstrap **embedded in the netboot.xyz binary**:
|
|
|
|
- **The bootfile must be a *recognised binary name*** (`netboot.xyz.efi`), not `menu.ipxe`.
|
|
The embedded bootstrap only chains the menu **locally** (its `:tftpmenu` branch) when the
|
|
bootfile matches one of its own binary names; any other name skips that branch and boots
|
|
the **public** `boot.netboot.xyz` menu instead.
|
|
- **The router's DHCP `next-server` must point at `192.168.10.127`** (see below). Under
|
|
proxyDHCP the bootstrap fetches its `local-vars.ipxe` from `${next-server}` — the value
|
|
from the *real* DHCP server (the NEC IX router), **not** from dnsmasq's
|
|
`${proxydhcp/next-server}`. `local-vars.ipxe` is what sets `use_proxydhcp_settings true`
|
|
(the no-keypress switch), so if it can't be fetched the UEFI client stalls fetching from
|
|
the router, then prompts for a `p` keypress or falls back to the public menu.
|
|
|
|
The boot binaries then chain the menu **locally** over TFTP from `192.168.10.127`, so clients
|
|
boot *this* host's menu, not the public site. Only the version check and distro mirrors reach
|
|
the internet.
|
|
|
|
### Required NEC IX router setting
|
|
|
|
The router keeps leasing IPs as before, but its DHCP scope for the LAN must advertise
|
|
**`next-server 192.168.10.127`** (a.k.a. the `siaddr` / BOOTP server field) on the LAN DHCP
|
|
pool. This is the one piece of PXE config the router *does* need — it does not otherwise
|
|
PXE-boot anything, and regular (non-PXE) DHCP clients ignore `next-server`. Set it via the
|
|
DHCP-server/boot-server (`siaddr`) option of the IX DHCP profile serving the `192.168.10.0/24`
|
|
scope; leave the bootfile name unset (dnsmasq's proxyDHCP still supplies it).
|
|
|
|
## Services (all on host `192.168.10.127`)
|
|
|
|
| Port | Service | Provided by | Purpose |
|
|
|-------------|-----------|------------------------|------------------------------------------|
|
|
| `67/udp` | proxyDHCP | `dnsmasq` (host net) | PXE boot offers (no IP leasing) |
|
|
| `69/udp` | TFTP | `netbootxyz` | serves `/config/menus` (binaries + menu) |
|
|
| `8080` | HTTP | `netbootxyz` nginx | `/` = `/assets` mirror; `/menus/` = binaries (UEFI HTTP Boot) |
|
|
| `3000` | Web UI | `netbootxyz` | manage menus / download assets |
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
docker compose up -d # start
|
|
docker compose logs -f dnsmasq # watch DHCP offers during a client boot
|
|
docker compose down # stop
|
|
```
|
|
|
|
Config manager (add/update distros, edit menus): <http://192.168.10.127:3000>
|
|
|
|
## Verified
|
|
|
|
Both PXE paths were tested end-to-end with QEMU VMs bridged onto `br0` (real SeaBIOS and
|
|
OVMF/UEFI firmware), booting all the way to the local netboot.xyz menu:
|
|
|
|
- **Legacy BIOS** → proxyDHCP offered `netboot.xyz.kpxe` → TFTP → local menu rendered ✅
|
|
- **UEFI x64** → proxyDHCP offered `netboot.xyz.efi` → TFTP → local menu rendered ✅
|
|
- **UEFI HTTP Boot** → configured, not yet VM-tested (hard to trigger in QEMU).
|
|
|
|
To re-test: create a tap on `br0`, run a diskless QEMU VM with `-boot n`, and watch
|
|
`docker compose logs -f dnsmasq` + `docker logs -f netbootxyz`.
|
|
|
|
## Notes / gotchas
|
|
|
|
- **Host networking is required** for `netbootxyz`: TFTP renegotiates to an ephemeral
|
|
port that Docker's bridge NAT mangles (clients get `TID mismatch`). Host net serves TFTP
|
|
straight off the LAN interface.
|
|
- `NGINX_PORT` is ignored by the image; the nginx listen port is pinned to `8080` in
|
|
`config/nginx/site-confs/default`, which also adds a `/menus/` location so UEFI HTTP Boot
|
|
can fetch the first-stage `.efi`. (If the appliance ever regenerates that file on upgrade,
|
|
re-add the `listen 8080` and `/menus/` bits.)
|
|
- `dnsmasq` binds **only `br0`** (`interface=br0` + `bind-interfaces`) so it doesn't clash
|
|
with libvirt's own dnsmasq on `virbr0`/`virbr1`.
|
|
- `config/menus/local-vars.ipxe` sets `use_proxydhcp_settings true` so proxyDHCP clients
|
|
boot without a keypress prompt.
|
|
- The NEC IX router needs **no PXE configuration** — proxyDHCP handles everything.
|
|
- Editing `dnsmasq.conf` requires `docker restart netboot-dnsmasq` (compose won't
|
|
auto-recreate on a bind-mounted file content change).
|
|
|
|
## Files
|
|
|
|
- `compose.yaml` — the two services (`netbootxyz` + `dnsmasq`)
|
|
- `dnsmasq.conf` — proxyDHCP + arch detection
|
|
- `config/` — netbootxyz appliance state (menus, nginx conf); managed by the container
|
|
- `assets/` — optional locally-mirrored distro images
|
|
- `buildout/` — leftover from an earlier manual build; **no longer used** (safe to delete)
|