Single-site bay-stuck issue at WJ: GE Intune Report IP script filters
Get-NetIPAddress on StartsWith("10.") and posts everything matching
to the GE Tines webhook. Bays at WJ get the PXE LAN 10.9.100.x IP
captured and reported -> GE backend tags bays as on a non-corp 10.x
subnet -> dynamic group eligibility for SFLD policy never matches.
Other GE sites work because their PXE LANs aren't on 10.x at all.
Renumber PXE LAN to RFC1918 172.16.9.0/24 so the GE filter naturally
skips wired PXE addresses without any disable-NIC dance.
Server-side already in flight (netplan dual-bound, dnsmasq scope +
boot URL repointed, blancco preferences + grub.cfg + iPXE GetPxeScript
all sed'd to 172.16.9.1). This commit is the playbook / scripts /
docs side: 109 hits across 35 files sed'd in one shot.
After this lands + boot.wim is rebuilt + bays renumber off DHCP,
the 10.9.100.1 binding will be dropped from netplan as the final
cleanup step.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
204 lines
9.7 KiB
Markdown
204 lines
9.7 KiB
Markdown
# PXE Server Architecture
|
|
|
|
This document describes the moving parts of the PXE server, the boot chain a
|
|
client follows, and how data flows between the server, clients, and external
|
|
systems.
|
|
|
|
## Hardware and host OS
|
|
|
|
- Single physical host (or VM) with at minimum 4 GB RAM, 4 CPU cores, and one
|
|
network interface attached to the isolated PXE LAN.
|
|
- Disk: 232 GB minimum if you stay slim (Dell_11 only, no Latitude); 500 GB
|
|
recommended for a full mirror; 2 TB+ recommended for headroom across all
|
|
driver sets and OS image variants.
|
|
- OS: Ubuntu Server 24.04 LTS (Noble), installed unattended via the autoinstall
|
|
USB built by `scripts/build-usb.sh`.
|
|
|
|
## Network layout
|
|
|
|
- PXE server static IP: `172.16.9.1/24` on an isolated subnet.
|
|
- DHCP range served by dnsmasq: `172.16.9.10 - 172.16.9.100`, 12h leases.
|
|
- Default gateway and DNS handed out via DHCP point at the PXE server itself.
|
|
- The subnet has no route to the corporate LAN. Client traffic (Blancco BMC
|
|
cloud, Intune enrollment) goes out via WiFi after Windows boots; PXE-time
|
|
traffic stays on the isolated LAN.
|
|
|
|
## Services on the PXE server
|
|
|
|
| Service | Port | Role |
|
|
|---------------|-----------|------------------------------------------------------|
|
|
| dnsmasq | 67/udp | DHCP. Hands out IPs and the next-server (TFTP) info. |
|
|
| dnsmasq | 69/udp | TFTP. Serves `ipxe.efi` to firmware PXE clients. |
|
|
| Apache | 80/tcp | HTTP. Serves wimboot, boot.wim, Blancco binaries, Clonezilla, memtest, and proxies the webapp on /. |
|
|
| Apache | 4433/tcp | HTTP. Serves `Altiris/iPXE/GetPxeScript.aspx` (the iPXE menu script). |
|
|
| Samba | 445/tcp | SMB shares. WinPE mounts these to fetch image content during deployment. |
|
|
| Flask webapp | 9009/tcp | Browser UI for image import, unattend editing, log/report viewing. |
|
|
|
|
`/etc/cron.d/dnsmasq-restart` restarts dnsmasq 15 seconds after every reboot to
|
|
work around a systemd-resolved race condition that can prevent dnsmasq from
|
|
binding to the PXE interface on cold boot.
|
|
|
|
`/etc/cron.d/media-tag-refresh` touches `Media.tag` in every image's
|
|
`Deploy/Control/` directory daily and on reboot. Without this, the WinPE
|
|
deployment loader stops finding the image after 30 days.
|
|
|
|
## Samba shares
|
|
|
|
| Share | Filesystem path | Purpose |
|
|
|------------------|-----------------------------|--------------------------------------------------------------|
|
|
| winpeapps | /srv/samba/winpeapps | Per-image-type Deploy/ trees (gea-standard, gea-shopfloor, etc.) and the deduped `_shared/` content (Operating Systems, Out-of-box Drivers, Packages). |
|
|
| clonezilla | /srv/samba/clonezilla | Clonezilla disk backup images (uploaded by clients running Clonezilla Live). |
|
|
| blancco-reports | /srv/samba/blancco-reports | XML erasure reports, written automatically by Blancco Drive Eraser at the end of each wipe. |
|
|
| enrollment | /srv/samba/enrollment | Single share that WinPE mounts as Y: during imaging. See "Enrollment share layout" below. |
|
|
| image-upload | /home/pxe/image-upload | Staging area for new image content uploaded from a Windows PC running `Upload-Image.ps1`. |
|
|
|
|
All shares are accessible to `pxe-upload` (password `pxe`) and the public-side
|
|
ones also allow guest access. The `blancco` user (password `blancco`) writes to
|
|
`blancco-reports` only.
|
|
|
|
## Enrollment share layout
|
|
|
|
The `enrollment` share is the catchall WinPE pulls from during imaging. New
|
|
fresh installs (built from this repo) deploy this layout:
|
|
|
|
```
|
|
/srv/samba/enrollment/
|
|
README.md
|
|
ppkgs/ GCCH bulk-enrollment PPKGs (.ppkg)
|
|
scripts/ run-enrollment.ps1, wait-for-internet.ps1, migrate-to-wifi.ps1
|
|
config/ site-config.json, FlatUnattendW10*.xml, per-site overrides
|
|
shopfloor-setup/ PC-type post-imaging scripts (CMM, Display, Standard, Lab, etc.)
|
|
pre-install/ WinPE-phase content
|
|
bios/ Dell BIOS update binaries + check-bios.cmd + models.txt
|
|
installers/ UDC, OpenText, etc. staged on client during preinstall
|
|
preinstall.json Preinstall manifest read by the WinPE preinstall stage
|
|
installers-post/ Post-OOBE app installers
|
|
cmm/ PC-DMIS patched MSIs
|
|
blancco/ Blancco custom images / configs (BDE715_GEAE_INTERNET.img.gz)
|
|
logs/ Client-uploaded logs and diagnostic bundles
|
|
```
|
|
|
|
Older servers (built before this repo's reorganization) use a flat layout
|
|
(everything at the share root). Both layouts work; the `startnet.cmd` baked
|
|
into each server's `boot.wim` matches its own layout.
|
|
|
|
## Boot chain (client perspective)
|
|
|
|
A client PXE-boots from the isolated LAN. UEFI Secure Boot is supported for
|
|
WinPE; the Blancco and Clonezilla utilities require Secure Boot disabled.
|
|
|
|
```
|
|
1. Client UEFI firmware sends DHCP DISCOVER on the isolated LAN.
|
|
2. dnsmasq replies with IP, next-server (PXE server IP), and bootfile=ipxe.efi.
|
|
3. Firmware fetches /srv/tftp/ipxe.efi via TFTP.
|
|
4. ipxe.efi (Broadcom-signed for Secure Boot) starts, gets DHCP, fetches the
|
|
iPXE menu script from http://<server>:4433/Altiris/iPXE/GetPxeScript.aspx.
|
|
5. Client picks an option:
|
|
|
|
a. Windows PE:
|
|
iPXE -> wimboot -> boot.wim
|
|
boot.wim runs startnet.cmd which mounts SMB shares (Y: enrollment,
|
|
Z: chosen winpeapps), kicks off FlatSetupLoader.exe -> PESetup.exe
|
|
to deploy the OS, then handles per-PC-type setup before reboot.
|
|
|
|
b. Blancco Drive Eraser:
|
|
iPXE chains http://<server>/blancco/grubx64.efi
|
|
GRUB loads vmlinuz-bde-linux + initramfs over TFTP (HTTP times out on
|
|
large files inside GRUB)
|
|
Blancco boot uses copytoram=y to load the rootfs into memory, mounts
|
|
the customized airootfs.sfs over HTTP, connects to BMC cloud over WiFi
|
|
for license validation, then runs the configured erasure profile.
|
|
Reports are written back to \\<server>\blancco-reports.
|
|
|
|
c. Clonezilla Live:
|
|
iPXE loads vmlinuz + initrd over HTTP, fetches filesystem.squashfs.
|
|
|
|
d. Memtest86+:
|
|
iPXE loads memtest.efi.
|
|
```
|
|
|
|
## Windows imaging lifecycle (gea-* images)
|
|
|
|
```
|
|
1. Boot to WinPE via PXE.
|
|
2. startnet.cmd mounts Y: \\server\enrollment and presents an interactive
|
|
image type and PC type menu.
|
|
3. Optionally checks BIOS firmware version against a manifest; if outdated,
|
|
stages the new firmware to the disk and reboots so it flashes on POST.
|
|
4. PESetup.exe runs the chosen image (image type determines OS, drivers,
|
|
apps to deploy).
|
|
5. After WinPE finishes, the system reboots into Windows OOBE.
|
|
6. During OOBE, the staged PPKG runs (GCCH bulk-enrollment, joins AAD, sets
|
|
up Intune enrollment).
|
|
7. After OOBE, the per-PC-type Run-ShopfloorSetup.ps1 runs from C:\Enrollment.
|
|
It installs the apps for that PC type (eDNC, OpenText, UDC, Dashboard,
|
|
etc. depending on the type), configures the desktop, and triggers Intune
|
|
sync.
|
|
```
|
|
|
|
## Webapp
|
|
|
|
`/opt/pxe-webapp/` runs as a systemd service, reverse-proxied by Apache on
|
|
port 80 (`/`) and accessible directly on port 9009. Built with Flask. Pages:
|
|
|
|
- Dashboard: service status, disk usage, recent activity.
|
|
- Images: import wizard for new content (from `image-upload` SMB share into
|
|
per-image Deploy/ trees), per-image driver and hardware config editing.
|
|
- Unattend editor: in-place editing of FlatUnattendW10.xml for each image.
|
|
- Startnet editor: edit and re-inject `Windows/System32/startnet.cmd` inside
|
|
the deployed `boot.wim` via wimupdate.
|
|
- Enrollment: PPKG inventory and upload.
|
|
- Backups: Clonezilla backup management.
|
|
- Reports: Blancco erasure report viewer.
|
|
- Audit: action log.
|
|
|
|
## Data flow summary
|
|
|
|
```
|
|
Build workstation (this repo)
|
|
|
|
|
| scripts/build-usb.sh /dev/sdX ubuntu-24.04.iso
|
|
v
|
|
USB installer (2 partitions: ISO + CIDATA)
|
|
|
|
|
| inserted into target server, boot from USB
|
|
v
|
|
Ubuntu auto-install + first-boot Ansible playbook
|
|
|
|
|
v
|
|
Configured PXE server (172.16.9.1) ----+
|
|
|
|
|
Windows PCs running Upload-Image.ps1 --+--> Image content (SMB, webapp import)
|
|
|
|
|
PXE clients (UEFI -> iPXE -> WinPE) ---+--> Image deployment (SMB, HTTP)
|
|
PXE clients (UEFI -> iPXE -> Blancco) -+--> Drive erasure + report upload
|
|
|
|
|
+--> Clonezilla backups (SMB)
|
|
```
|
|
|
|
## Where things live
|
|
|
|
- Ansible playbook: `playbook/pxe_server_setup.yml`. Single file, idempotent.
|
|
- WinPE startup script (template): `playbook/startnet.cmd` (canonical) and
|
|
`startnet-template.cmd` (mirror copy at repo root for editor convenience).
|
|
The playbook injects this into `Windows/System32/startnet.cmd` inside the
|
|
`boot.wim` it deploys to `/var/www/html/win11/sources/`.
|
|
- iPXE menu script source: embedded in the playbook (`Create GetPxeScript.aspx`
|
|
task); deployed to `/var/www/html/Altiris/iPXE/GetPxeScript.aspx`.
|
|
- Per-PC-type setup scripts: `playbook/shopfloor-setup/`. The playbook copies
|
|
the whole tree to the enrollment share so WinPE can fetch them.
|
|
- Blancco assets: `boot-tools/blancco/` in the repo, deployed to
|
|
`/var/www/html/blancco/` plus TFTP symlinks in `/srv/tftp/blancco/`.
|
|
- Site-specific values (IPs, SSIDs, BMC creds, hostnames): currently
|
|
hardcoded in multiple files; see SITE-CUSTOMIZATION.md for the migration
|
|
plan to consolidate these in `config/`.
|
|
|
|
## See also
|
|
|
|
- SETUP.md: build process and target server install
|
|
- SITE-CUSTOMIZATION.md: what to change when bringing up a new site
|
|
- TROUBLESHOOTING.md: known failure modes and fixes
|
|
- BLANCCO.md: erasure boot chain details, custom config.img, BMC licensing
|
|
- GEA-IMAGING.md: WinPE deployment internals, PPKGs, per-type setup
|
|
- OPERATIONS.md: day 2 procedures (PPKG bumps, BIOS updates, image upload)
|