Files
pxe-server/SETUP.md
cproudlock d6776f7c7f Reorganize repo, enrollment share taxonomy, Blancco USB-build fixes, v4.10 PPKGs
Workstation reorganization:
- All build/deploy/helper scripts moved into scripts/ (paths updated to use
  REPO_ROOT instead of SCRIPT_DIR so they resolve sibling dirs from the new
  depth)
- New config/ directory placeholder for site-specific overrides
- Removed stale: mok-keys/, test-vm.sh, test-lab.sh, setup-guide-original.txt,
  unattend/ (duplicate of moved playbook/FlatUnattendW10.xml)
- README.md and SETUP.md structure listings updated, dead "Testing with KVM"
  section removed
- .claude/ gitignored

Enrollment share internal taxonomy (forward-looking; existing servers
unaffected since they keep their current boot.wim with flat paths):
- Single SMB share kept (WinPE only mounts one Y: drive), but content now
  organised into ppkgs/, scripts/, config/, shopfloor-setup/, pre-install/{bios,
  installers}, installers-post/cmm/, blancco/, logs/
- README.md deployed to share root explaining each subdir
- New playbook tasks deploy site-config.json + wait-for-internet.ps1 +
  migrate-to-wifi.ps1 explicitly (were ad-hoc on legacy servers)
- BIOS subdir moved into pre-install/bios/, preinstall/ renamed to pre-install/
- startnet.cmd + startnet-template.cmd updated with new Y:\subdir\ paths
- Bumped GCCH PPKG references v4.9 -> v4.10

Blancco USB-build fixes (so next fresh USB install boots Blancco end-to-end
without the manual fixup we did against GOLD):
- grub-blancco.cfg: kernel/initrd switched HTTP -> TFTP (GRUB's HTTP module
  times out on multi-MB files); added modprobe.blacklist=iwlwifi,iwlmvm,btusb
  (WiFi drivers hang udev on Intel business PCs)
- grubx64.efi rebuilt from updated cfg
- Playbook task added to create /srv/tftp/blancco/ symlinks pointing at the
  HTTP-served binaries

run-enrollment.ps1: OOBEComplete is now set AFTER PPKG install (Win11 22H2+
hangs indefinitely if OOBEComplete is set before the bulk-enrollment PPKG runs).

Also includes deploy-bios.sh / pull-bios.sh / busybox-static / models.txt
that were sitting untracked at the repo root.
2026-04-14 16:01:02 -04:00

11 KiB

PXE Server Setup Guide

Automated build process for deploying an Ubuntu-based PXE boot server that hosts GE Aerospace Windows PE images. The entire setup is air-gapped — no internet required on the target machine.

Architecture

Client PXE boot
  -> Broadcom signed iPXE (Secure Boot)
  -> iPXE boot menu (HTTP, port 4433)
     ├── Windows PE -> wimboot -> boot.wim -> startnet.cmd -> Samba -> Image deployment
     ├── Clonezilla -> vmlinuz/initrd -> Disk cloning/imaging
     ├── Blancco    -> Native kernel + initramfs -> NIST 800-88 drive erasure (auto-reports)
     └── Memtest86+ -> Memory diagnostics

Services on the PXE Server

Service Port Purpose
dnsmasq 67/udp DHCP (10.9.100.10-100)
dnsmasq 69/udp TFTP (serves ipxe.efi)
Apache 80/tcp HTTP (wimboot, WinPE boot files, proxy)
Apache 4433/tcp iPXE boot script (GetPxeScript.aspx)
Samba 445/tcp Deployment content + backup + reports
Flask Webapp 9009/tcp Web management interface

Prerequisites

Hardware

  • Server or PC with >= 8 GB RAM, >= 250 GB disk, one wired NIC
  • USB thumb drive >= 8 GB (32+ GB if bundling WinPE images)

Software (on your workstation)

  • Ubuntu Server 24.04 ISO — https://ubuntu.com/download/server
  • Linux workstation (Ubuntu/Mint) for running download and build scripts
  • GE Aerospace Media Creator LITE (for caching WinPE images)

GE Access Packages

  • EPM Rufus Exception Request
  • EPM DT Functions
  • DLP - Encrypted Removable (USB) Long Term Access

Setup Process

Step 1: Download Offline Packages (one-time, requires internet)

./scripts/download-packages.sh

Downloads all .deb packages (ansible, dnsmasq, apache2, samba, wimtools, etc.) into offline-packages/ and Python wheels (flask, lxml) into pip-wheels/. Approximately 252 packages (~140 MB) + 8 Python wheels.

Packages included:

  • Server: dnsmasq, apache2, samba, ufw, cron
  • Automation: ansible
  • Tools: wimtools, unzip, p7zip-full
  • Python: python3-pip, python3-venv
  • Network: network-manager, wpasupplicant, wireless-tools, linux-firmware

Step 2: Prepare Boot Tools (optional)

./scripts/prepare-boot-tools.sh /path/to/blancco.iso /path/to/clonezilla.zip /path/to/memtest.bin

Extracts boot files for Blancco, Clonezilla, and Memtest86+ into the boot-tools/ directory. Automatically patches Blancco's config.img to auto-save erasure reports to the PXE server's Samba share.

Step 3: Build the USB

# Basic — server only (import WinPE images later)
sudo ./scripts/build-usb.sh /dev/sdX /path/to/ubuntu-24.04-live-server-amd64.iso

# With WinPE images bundled (single USB, larger drive needed)
sudo ./scripts/build-usb.sh /dev/sdX /path/to/ubuntu-24.04.iso /path/to/winpe-images

This creates a bootable USB with:

  • Partition 1: Ubuntu Server installer
  • Partition 2: CIDATA (autoinstall config, offline .debs, pip wheels, Ansible playbook, webapp, boot tools)

Step 4: Boot the Target Machine

  1. Insert the USB into the target machine
  2. Press F12 (or vendor boot key) and select the USB
  3. Ubuntu auto-installs — no interaction needed
  4. After reboot, the first-boot script installs all .deb packages and runs the Ansible playbook
  5. PXE services (dnsmasq, Apache, Samba) are configured automatically
  6. Flask webapp starts on port 9009

Step 5: Connect to Isolated Network

Move the server's wired NIC to the isolated switch for PXE clients.

Step 6: Import WinPE Content (if not bundled in Step 3)

Option A: Use the web interface at http://10.9.100.1:9009 to import from USB.

Option B: Manual copy:

sudo mkdir -p /mnt/usb2
sudo mount /dev/sdb2 /mnt/usb2
sudo cp -r /mnt/usb2/. /srv/samba/winpeapps/gea-standard
sudo umount /mnt/usb2

Web Management Interface

Access at http://10.9.100.1:9009 from any machine on the isolated network.

Page URL Path Purpose
Dashboard / Service status, disk usage, DHCP clients
Image Import /import Import WinPE images from USB drives
Unattend Editor /unattend Edit Windows unattend.xml per image type
startnet.cmd /startnet Edit startnet.cmd inside boot.wim (wimtools)
Clonezilla Backups /backups Upload/download/manage disk backup images
Blancco Reports /reports View/download drive erasure reports
Image Config /images/*/config Per-image driver, OS, and hardware config
Enrollment /enrollment GCCH bulk enrollment package management
Audit Log /audit Activity history for all write operations

Verification

  1. Connect a test workstation to the isolated switch
  2. Set Network Boot (PXE) as first boot in BIOS/UEFI
  3. Boot — the client should pull an IP from 10.9.100.x
  4. iPXE loads, fetches the boot script from port 4433
  5. Select an option from the boot menu:
    • Windows PE: Boots via wimboot + boot.wim, maps Samba shares, begins deployment
    • Clonezilla: Boots Clonezilla Live for disk imaging
    • Blancco: Boots Drive Eraser, auto-saves reports to server
    • Memtest86+: Runs memory diagnostics

Testing with KVM

# Download Ubuntu ISO
wget -O ~/Downloads/ubuntu-24.04.3-live-server-amd64.iso \
  https://releases.ubuntu.com/noble/ubuntu-24.04.3-live-server-amd64.iso

# Launch test VM
sudo ./test-vm.sh ~/Downloads/ubuntu-24.04.3-live-server-amd64.iso

# Watch progress (Ctrl+] to detach)
sudo virsh console pxe-test

# After install: ssh pxe@10.9.100.1 / http://10.9.100.1:9009

# Clean up
sudo ./test-vm.sh --destroy

Project Structure

pxe-server/
├── autoinstall/
│   ├── user-data                 # Cloud-init autoinstall + first-boot script
│   └── meta-data                 # Cloud-init metadata (required, empty)
├── playbook/
│   ├── pxe_server_setup.yml      # Ansible: dnsmasq, Apache, Samba, iPXE, UFW, webapp
│   ├── inventory.ini             # Ansible inventory
│   ├── startnet.cmd              # WinPE startup script (injected into boot.wim)
│   ├── blancco-init.sh           # Custom initramfs for Blancco PXE boot
│   ├── blancco-preferences.xml   # Blancco auto-report preferences
│   ├── check-bios.cmd            # Pre-imaging BIOS update checker
│   ├── FlatUnattendW10-shopfloor.xml  # Shopfloor unattend.xml
│   └── shopfloor-setup/          # PC type setup scripts (Standard, CMM, Display, etc.)
├── webapp/
│   ├── app.py                    # Flask application (~1600 lines)
│   ├── requirements.txt          # Python deps (flask, lxml)
│   ├── static/                   # CSS, JS, fonts, logo (all bundled offline)
│   └── templates/                # Jinja2 HTML templates (10 pages)
├── docs/
│   └── shopfloor-display-imaging-guide.md  # End-user imaging guide
├── boot-tools/                   # Extracted boot files (gitignored, built by prepare-boot-tools.sh)
│   ├── blancco/                  # Blancco Drive Eraser
│   ├── clonezilla/               # Clonezilla Live
│   └── memtest/                  # Memtest86+
├── boot-files/                   # WinPE boot files (boot.wim, wimboot, ipxe.efi, BCD)
├── offline-packages/             # .deb files (gitignored, built by download-packages.sh)
├── pip-wheels/                   # Python wheels (gitignored, built by download-packages.sh)
├── enrollment/                   # PPKGs and run-enrollment.ps1 (gitignored)
├── bios-staging/                 # Dell BIOS update binaries (gitignored)
├── scripts/                      # Build, deploy, and helper scripts
│   ├── build-usb.sh              # Builds the 2-partition installer USB
│   ├── build-proxmox-iso.sh      # Builds self-contained Proxmox installer ISO
│   ├── prepare-boot-tools.sh     # Extracts/patches boot tools from ISOs
│   ├── download-packages.sh      # Downloads all offline packages
│   ├── download-drivers.py       # Downloads Dell drivers from dell.com
│   ├── deploy-bios.sh            # Pushes BIOS updates to enrollment share
│   ├── pull-bios.sh              # Pulls BIOS binaries from upstream cache
│   ├── sync_hardware_models.py   # Syncs hardware model configs across images
│   ├── Upload-Image.ps1          # Windows: upload MCL cache to PXE via SMB
│   └── Download-Drivers.ps1      # Windows: download hardware drivers from GE CDN
├── config/                       # Site-specific configuration overrides
├── startnet-template.cmd         # startnet.cmd template (synced with playbook copy)
├── README.md                     # Project overview
└── SETUP.md                      # Detailed setup guide (this file)

Image Types

Image Type Domain Description
gea-standard geaerospace.com Standard desktop
gea-engineer geaerospace.com Engineering desktop
gea-shopfloor geaerospace.com Shop floor kiosk
ge-standard ge.com Standard desktop
ge-engineer ge.com Engineering desktop
ge-shopfloor-lockdown ge.com Shop floor (locked)
ge-shopfloor-mce ge.com Shop floor (MCE)

Network Configuration

  • PXE server static IP: 10.9.100.1/24
  • DHCP range: 10.9.100.10 - 10.9.100.100
  • Lease time: 12 hours
  • DNS: 8.8.8.8 (passed to clients, not used by server)
  • Firewall: UFW deny-by-default, allow 67/udp 69/udp 80/tcp 445/tcp 4433/tcp 9009/tcp

Samba Shares

Share Path Purpose
winpeapps /srv/samba/winpeapps WinPE deployment images
clonezilla /srv/samba/clonezilla Clonezilla disk backup images
blancco-reports /srv/samba/blancco-reports Blancco erasure reports (auto)
enrollment /srv/samba/enrollment GCCH bulk enrollment packages
image-upload /home/pxe/image-upload Image upload staging area

All shares use guest access for the isolated network.