Files
pxe-server/docs/ARCHITECTURE.md
cproudlock adef507084 Add ARCHITECTURE.md, SITE-CUSTOMIZATION.md, mirror-from-gold.sh
Two new docs cover what the system is (boot chain, services, shares,
enrollment layout, data flow) and what to change per site (every
hardcoded value, where it lives, secrets handling).

scripts/mirror-from-gold.sh replicates content from an existing PXE
server (Operating Systems, drivers, packages, custom installers, BIOS,
PCDMIS, Blancco custom image, site-config) onto a freshly-installed PXE
server. Translates the legacy flat enrollment layout on the source into
the reorganized taxonomy (ppkgs/, pre-install/installers/, installers-
post/cmm/, blancco/, config/) on the destination. Tolerates rsync
exit 23 (permission-denied subdirs like the OpenText W10shortcuts dir
that is pxe-upload-group-only on legacy servers).
2026-04-14 17:56:46 -04:00

9.7 KiB

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: 10.9.100.1/24 on an isolated subnet.
  • DHCP range served by dnsmasq: 10.9.100.10 - 10.9.100.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 (10.9.100.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)