File-existence detection on NTLARS.exe couldn't tell eDNC 6.4.3 from 6.4.4 (both installers leave the same binary in place), so the enforcer skipped upgrades. FileVersion compares the vendor-stamped FileVersion field on a named binary against the manifest's DetectionValue with exact-string match. Added to all three lib copies (common, Standard, CMM). Standard manifest template flipped to FileVersion against DncMain.exe -- the eDNC main binary is more reliably version-stamped than the bundled NTLARS sub-tool. Update workflow now: drop the new vendor MSI on the SFLD share, bump Installer + DetectionValue in machineapps-manifest.json, next user logon runs Machine-Enforce which detects mismatch and installs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GE Aerospace PXE Boot Server
Automated, air-gapped PXE boot server for deploying GE Aerospace Windows images. Built on Ubuntu 24.04 Server with zero-touch provisioning via autoinstall and Ansible.
Overview
This project provides a complete, repeatable build process for a PXE boot server that serves Windows PE images to client machines on an isolated network. Everything runs offline after initial setup — no internet required on the target server.
Boot Chain
Client PXE boot (UEFI Secure Boot)
-> iPXE (TFTP, Broadcom-signed for Secure Boot)
-> iPXE boot menu (HTTP, port 4433)
-> User selects boot option:
├── Windows PE -> wimboot -> boot.wim -> startnet.cmd -> Samba share -> Image deployment
├── Clonezilla -> vmlinuz/initrd -> Disk cloning/imaging
├── Blancco -> Native kernel + initramfs -> NIST 800-88 drive erasure
└── Memtest86+ -> Memory diagnostics
Services
| Service | Port | Purpose |
|---|---|---|
| dnsmasq | 67/udp | DHCP (10.9.100.10-100, 12h lease) |
| 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 + Clonezilla + Blancco |
| Flask Webapp | 9009/tcp | Web management interface |
Network
- PXE server IP:
10.9.100.1/24 - DHCP range:
10.9.100.10-10.9.100.100 - Firewall: UFW deny-by-default, only service ports open (22, 67, 69, 80, 445, 4433, 9009)
Quick Start
Prerequisites
On your workstation (internet-connected):
- Ubuntu 24.04 (or Linux Mint / similar) for downloading packages
- Ubuntu Server 24.04 ISO
- GE Aerospace Media Creator LITE (for WinPE images)
- USB drive >= 8 GB (32+ GB if bundling WinPE images)
GE Access Packages (MyAccess portal):
- EPM Rufus Exception Request
- EPM DT Functions
- DLP - Encrypted Removable (USB) Long Term Access
Step 1: Download Offline Packages
./scripts/download-packages.sh
Downloads all .deb packages and Python wheels for offline installation (~140 MB of debs, ~20 MB of wheels).
Step 2: Prepare Boot Tools (optional)
./scripts/prepare-boot-tools.sh /path/to/blancco.iso /path/to/clonezilla.zip /path/to/memtest.bin
Extracts and configures boot tool files (Blancco, Clonezilla, Memtest86+). Automatically patches Blancco's config.img to auto-save erasure reports to the PXE server's Samba share.
Step 3: Build the USB
sudo ./scripts/build-usb.sh /dev/sdX /path/to/ubuntu-24.04-live-server-amd64.iso
Creates a bootable USB with two partitions:
- Partition 1: Ubuntu Server installer
- Partition 2: CIDATA (autoinstall config, offline .debs, pip wheels, Ansible playbook, webapp, boot tools)
Step 4: Install on Target Server
- Insert USB into the target machine
- Press F12 and boot from USB
- Ubuntu auto-installs with no interaction
- After reboot, the first-boot script:
- Installs all offline .deb packages
- Runs the Ansible playbook (configures dnsmasq, Apache, Samba, UFW, webapp)
- Configures static IP
10.9.100.1/24
- Move the server's wired NIC to the isolated PXE switch
Step 5: Access the Web Interface
Open http://10.9.100.1:9009 from any machine on the isolated network.
Web Management Interface
The Flask webapp (port 9009) provides a browser-based management UI:
- Dashboard — Service status overview, disk usage, connected DHCP clients
- Image Import — Import WinPE deployment images from USB drives
- Unattend Editor — Edit Windows unattend.xml files per image type (XML syntax highlighting)
- startnet.cmd Editor — Modify the startnet.cmd inside boot.wim without Windows (uses wimtools)
- Clonezilla Backups — Upload, download, and manage disk backup images
- Blancco Reports — View, download, and manage drive erasure reports (auto-collected via Samba)
- Image Config — Per-image configuration editor (drivers, OS packages, hardware models)
- Enrollment — Upload, download, and manage GCCH bulk enrollment packages
- Audit Log — Activity history for all write operations (imports, edits, deletes)
Image Types Supported
| 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) |
Project Structure
pxe-server/
├── autoinstall/
│ ├── user-data # Cloud-init autoinstall config + first-boot script
│ └── meta-data # Cloud-init metadata (required, empty)
├── playbook/
│ ├── pxe_server_setup.yml # Ansible playbook: all server configuration
│ ├── 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/
│ │ ├── ge-aerospace-logo.svg # GE Aerospace branding
│ │ ├── favicon.ico # Browser favicon
│ │ ├── app.js # Frontend JavaScript
│ │ ├── bootstrap.min.css # Bootstrap 5 (bundled offline)
│ │ ├── bootstrap.bundle.min.js
│ │ ├── bootstrap-icons.min.css
│ │ └── fonts/ # Icon fonts (woff/woff2)
│ └── templates/
│ ├── base.html # Layout with GE branding and sidebar nav
│ ├── dashboard.html # Service status and overview
│ ├── import.html # USB image import wizard
│ ├── unattend_editor.html # XML editor for unattend files
│ ├── startnet_editor.html # startnet.cmd WIM editor
│ ├── image_config.html # Per-image driver and hardware config
│ ├── enrollment.html # GCCH bulk enrollment packages
│ ├── backups.html # Clonezilla backup management
│ ├── reports.html # Blancco erasure reports
│ └── audit.html # Activity audit log
├── docs/
│ └── shopfloor-display-imaging-guide.md # End-user imaging guide
├── boot-tools/ # Extracted boot tool files (gitignored)
│ ├── 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 installer USB (2-partition)
│ ├── build-proxmox-iso.sh # Builds self-contained Proxmox installer ISO
│ ├── prepare-boot-tools.sh # Extracts and patches boot tool files
│ ├── download-packages.sh # Downloads offline .debs + pip wheels
│ ├── download-drivers.py # Downloads Dell drivers directly 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 # This file
└── SETUP.md # Detailed setup guide
Proxmox Deployment
A single ISO can be built for deploying the PXE server in a Proxmox VM:
Build the ISO
# Prerequisites (on build workstation)
sudo apt install xorriso p7zip-full
# Build the installer ISO
./scripts/build-proxmox-iso.sh /path/to/ubuntu-24.04-live-server-amd64.iso
This creates pxe-server-proxmox.iso containing the Ubuntu installer, autoinstall config, all offline packages, the Ansible playbook, webapp, and boot tools.
Deploy on Proxmox
- Upload
pxe-server-proxmox.isoto Proxmox storage (Datacenter -> Storage -> ISO Images) - Create a new VM:
- OS: Linux 6.x kernel
- BIOS: OVMF (UEFI) or SeaBIOS
- Memory: 4096 MB
- CPU: 2+ cores
- Disk: 40+ GB (VirtIO SCSI)
- Network: Bridge connected to your isolated PXE network
- Attach the ISO as CD-ROM and start the VM
- Ubuntu auto-installs with zero interaction (~10-15 minutes)
- After reboot, first-boot configures all PXE services automatically
- Access the web interface at
http://10.9.100.1:9009
Import WinPE Images
After the server is running, import deployment images via the web interface at http://10.9.100.1:9009/import or by mounting a USB drive with WinPE content.
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 (no authentication) for ease of use on the isolated network.
Blancco Drive Erasure
Blancco Drive Eraser 7.15.1 boots via a native Ubuntu kernel with a custom initramfs (blancco-init.sh) that downloads and mounts the Blancco rootfs over HTTP. XML erasure reports are automatically saved to the PXE server's Samba share (blancco-reports). The server supports BMC cloud licensing for Blancco activation over WiFi.
Reports are viewable and downloadable from the web interface at http://10.9.100.1:9009/reports.
Notes
- Run
download-packages.shbefore building USB — it downloads all offline.debpackages including wimtools (needed for startnet.cmd editing) - The webapp uses session-based CSRF tokens on all POST forms and API endpoints
Commit History
| Commit | Description |
|---|---|
5791bd1 |
Initial project setup: automated PXE server provisioning |
cee4ecd |
Add web management UI, offline packages, WinPE consolidation |
f614596 |
Fix unattend.xml path to match actual image structure |
e7313c2 |
Add multi-boot PXE menu, Clonezilla backups, GE Aerospace branding |
89b5834 |
Add wimtools and startnet.cmd editor for boot.wim modification |
05dbb7e |
Add Blancco erasure reports Samba share and webapp viewer |
ef75839 |
Auto-patch Blancco config.img for network report storage |
92c9b0f |
Fix review findings: offline assets, security, audit logging |
725c8f4 |
Change webapp to port 9009, add test VM script |
f3a384f |
Add Proxmox ISO builder, CSRF protection, boot-files integration |
1a5c4f7 |
Eliminate USB requirement for WinPE PXE boot |
dd2fec5 |
Blancco PXE boot via Ubuntu kernel switch_root |
86660a0 |
Remove UEFI HTTP Boot config from dnsmasq |
6d0e6ee |
BIOS check fix, parallel downloads, shopfloor hardening |
7616549 |
Shopfloor PC type system, webapp enhancements |
b7cd097 |
Blancco 7.15.1 upgrade: native kernel boot, BMC cloud licensing |
163e58a |
Fix dnsmasq reboot cron: use /etc/cron.d/ instead of crontab |