H1 corp_admin_cidrs (UFW 22/9009 on the corp NIC from these only; refuses
when it would lock out the current SSH client) and corp_ssh_password_auth
(sshd drop-in, passwords only from the imaging subnet). Defaults keep the
current behaviour and print a loud warning.
H2 pxe-netplan-apply.sh: pre-flight refusal (pxe-MAC NIC holds the default
route, a DHCP lease or the route to an SSH client), run from the USB
before anything changes; post-apply checks (names, imaging IPv4, corp
IPv4 back within 30 s, SSH route) and a 120 s systemd-run auto-revert.
H3 restore() puts the previous NIC names back (two-phase rename via
temporary names, so swaps work) before generate + apply.
H4 a failed rename is fatal (restore + exit 1); the play drops the old
any-interface UFW rules only after verifying both NICs and their
per-interface SSH rules.
H5 first-boot checks the playbook exit code, retries at next boot (max 5),
writes /var/lib/pxe-firstboot.failed and /etc/issue + /etc/motd banners.
M1 build-usb.sh verifies iPXE files against the playbook pins, every wheel
against its own package's hashes, drops the unpinned pip fallback,
requires --site-vars or --no-site-vars.
M2 webapp restarts when the code, wheels or unit changed.
M3 ignore-carrier on the imaging NIC; ip_nonlocal_bind kept for the
apache/networkd boot race.
M4 menu suffix must match blancco_kver; missing kernel with no earlier
build is fatal; a live menu with the staged Blancco test entry is not
overwritten.
M5 build-proxmox-iso.sh is unsupported (hard exit); use build-usb --image.
M6 deploy-unattend.sh: password via SSHPASS env and sudo stdin only,
%q-quoted remote args, sha256 check of the live file; lint-unattend.py
reads PXE_SERVER/PXE_USER/PXE_PASS and uses sshpass -e.
M7 the playbook lints the unattend files before the force: yes copies
(lint-unattend.py ships on CIDATA as scripts/); pre-commit ACMR.
M8 Blancco initramfs build: no ignore_errors, pipefail, trap cleanup.
Also: Send-ImagingStage.ps1 deploy, carrier hook install tasks
(pxe-nic-carrier, networkd-dispatcher), L1 imaging-active hold
(allow_disruptive) and no iPXE downgrade below an Updates-page install,
L2 iso-volid, L3 kver pin read from the playbook, L4 cp -rL, L5 refuse
>= 4 GiB WinPE files, L6 PIP_DIR wipe guard, L7 per-package wheel hashes,
no online fallback, L8 check-updates.py (apt_pkg/cached compare, all
components, exit 2 on no debs / bad answers).
236 lines
11 KiB
Markdown
236 lines
11 KiB
Markdown
# Site Customization
|
|
|
|
The PXE server in this repo was built for the GE Aerospace West Jefferson site.
|
|
To stand it up at another site, several values need to change. This document
|
|
lists every site-specific value, where it lives today, and the recommended
|
|
forward state.
|
|
|
|
## Status
|
|
|
|
The repo has not yet been parameterized. As of 2026-04-14 the site-specific
|
|
values below are hardcoded in multiple files. The `config/` directory at the
|
|
repo root is a placeholder for the future state where one YAML file drives
|
|
substitution at build time. Until that exists, customizing for a new site
|
|
means editing the source files directly.
|
|
|
|
If you are bringing up the first non-WJ site, expect to do this manually and
|
|
contribute a `config/sites/<sitename>.yaml` template back to the repo.
|
|
|
|
## Values to change
|
|
|
|
### Network
|
|
|
|
Every server has two NICs: the imaging NIC (isolated imaging LAN, static
|
|
172.16.9.1, the only NIC that serves DHCP/TFTP/HTTP boot/SMB) and the GE
|
|
corporate NIC (DHCP client; SSH and the webapp on 9009 only). Put both MACs
|
|
in `playbook/site-vars.yml` (copy `playbook/site-vars.example.yml`) before
|
|
building the USB: `pxe_nic_mac`, `corp_nic_mac`. The installer brings the
|
|
network up with DHCP only; the first-boot playbook stops before changing
|
|
anything if either MAC is unset or missing, then pins both NICs by MAC in
|
|
netplan (names `pxe0` / `corp0`, overridable), dnsmasq, UFW and Samba.
|
|
|
|
| Value | Default | Where it lives |
|
|
|-------------------|----------------------|--------------------------------------------------------------------------------|
|
|
| PXE server IP | 172.16.9.1 | `playbook/pxe_server_setup.yml` (dnsmasq config, iPXE script, samba conf, webapp env), `playbook/startnet.cmd` (mount paths), `boot-tools/blancco/grub-blancco.cfg` (TFTP/HTTP URLs) |
|
|
| PXE subnet | 172.16.9.0/24 | Same as above, plus `playbook/pxe_server_setup.yml` (UFW rules) |
|
|
| DHCP range | 172.16.9.10-100 | `playbook/site-vars.yml` (`pxe_dhcp_start`, `pxe_dhcp_end`) |
|
|
| NIC MACs / names | (required) / pxe0, corp0 | `playbook/site-vars.yml` (`pxe_nic_mac`, `corp_nic_mac`, `pxe_nic_name`, `corp_nic_name`) |
|
|
| Hostname | pxeserver | `autoinstall/user-data` (identity.hostname) |
|
|
|
|
### Access from the GE corporate network
|
|
|
|
SSH (password auth, the shared `pxe` password) and the webapp on 9009 (no
|
|
login, runs as root) are reachable on the corp NIC. By default from ALL of
|
|
GE, as before, so a re-run never locks anyone out; the play prints a loud
|
|
warning on every run while that is so. Set these in `playbook/site-vars.yml`:
|
|
|
|
| Var | Default | Effect |
|
|
|--------------------------|---------|--------|
|
|
| `corp_admin_cidrs` | `[]` | List of admin subnets/hosts, e.g. `["10.134.48.0/24", "3.12.34.56/32"]`. When non-empty, UFW allows 22 and 9009 on `corp_nic_name` from these only and drops the any-source rules. The play refuses (nothing changed) if an entry is invalid or your own SSH session is not inside one of them. The imaging NIC keeps its rules. |
|
|
| `corp_ssh_password_auth` | `true` | `false` adds `/etc/ssh/sshd_config.d/10-pxe-corp-auth.conf`: `PasswordAuthentication no`, re-allowed by a `Match Address` block for `pxe_subnet` and localhost. Keys only from GE. The play refuses while `pxe` has no `~/.ssh/authorized_keys`, and removes the drop-in again if `sshd -t` rejects it. |
|
|
| `allow_disruptive` | `false` | Re-runs while imaging is active (SMB sessions on 445, or DHCP leases granted in the last `pxe_busy_window_min` = 30 min) do not bounce the NICs or restart dnsmasq/Apache/Samba; a needed network change stops the play. `-e allow_disruptive=true` overrides. |
|
|
|
|
Recommended for a production box: `corp_admin_cidrs` set to the admin
|
|
desks' subnet, then (after `ssh-copy-id`) `corp_ssh_password_auth: false`.
|
|
|
|
### Re-running the playbook over SSH (from the GE side)
|
|
|
|
The network step refuses before changing anything when the NIC that
|
|
`pxe_nic_mac` names holds the default route, a DHCP lease, or the route to
|
|
your SSH client (swapped MACs or cables). When it does apply, it arms a
|
|
120 s auto-revert timer (`pxe-netplan-revert-*`), checks both names, the
|
|
imaging address and that the corp NIC gets its IPv4 back within 30 s, and
|
|
restores the previous netplan config AND NIC names on any failure. Backups:
|
|
`/var/backups/netplan-<timestamp>/`.
|
|
|
|
### Identity and credentials
|
|
|
|
| Value | Default | Where it lives |
|
|
|-----------------------------|---------------------------------------|---------------------------------------------------------|
|
|
| Linux user | pxe / pxe | `autoinstall/user-data` (identity.username, password hash) |
|
|
| Samba upload user | pxe-upload / pxe | `playbook/pxe_server_setup.yml` (Samba user creation) |
|
|
| Samba blancco user | blancco / blancco | `playbook/pxe_server_setup.yml` |
|
|
| Sudo password | pxe | autoinstall password hash; also referenced in scripts that ssh + sudo |
|
|
|
|
### WiFi and BMC (Blancco licensing)
|
|
|
|
The Blancco custom `config.img` carries WiFi credentials and BMC cloud
|
|
credentials in plaintext. These are GE-Aerospace specific.
|
|
|
|
| Value | Default | Where it lives |
|
|
|---------------|----------------------|-------------------------------------------------------------------------|
|
|
| WiFi SSID | INTERNETACCESS | `boot-tools/blancco/config.img` (inside the cpio archive: preferences.xml) |
|
|
| WiFi password | Acc3ssGr@nted22 | Same |
|
|
| BMC endpoint | classic.eu-west-1.blancco.cloud:443 | Same; encrypted credentials inside config.img |
|
|
|
|
To rebuild `config.img` for a different site, see BLANCCO.md ("Rebuilding
|
|
config.img").
|
|
|
|
### Image types
|
|
|
|
The repo defines seven image types (see `playbook/pxe_server_setup.yml`,
|
|
`image_types`). Most sites likely only need a subset. The current set:
|
|
- gea-standard
|
|
- gea-engineer
|
|
- gea-shopfloor
|
|
- ge-standard
|
|
- ge-engineer
|
|
- ge-shopfloor-lockdown
|
|
- ge-shopfloor-mce
|
|
|
|
Trim or extend this list and the matching `shopfloor_types` filter as needed.
|
|
|
|
### PC types (shopfloor sub-types)
|
|
|
|
`playbook/shopfloor-setup/` contains per-PC-type install logic. The current
|
|
types reflect WJ shopfloor needs:
|
|
- CMM (PC-DMIS)
|
|
- WaxAndTrace
|
|
- Keyence
|
|
- Genspect
|
|
- Display (Lobby and Dashboard variants)
|
|
- Standard (Timeclock and Machine variants)
|
|
- Lab
|
|
|
|
A site without CMMs can drop the CMM type and its installers entirely.
|
|
|
|
### GCCH bulk-enrollment PPKGs
|
|
|
|
PPKG filenames are baked into `playbook/startnet.cmd` and
|
|
`startnet-template.cmd`. They are tied to the GE Aerospace tenant. Other
|
|
sites/tenants will have their own PPKGs with different filenames.
|
|
|
|
| PPKG enrollment menu choice | Default filename |
|
|
|-----------------------------|---------------------------------------------------------------|
|
|
| 1 NoOffice | GCCH_Prod_SFLD_NoOffice_US_Exp_20260430_v4.10.ppkg |
|
|
| 2 StdOffice x86 | GCCH_Prod_SFLD_StdOffice-x86_US_Exp_20260430_v4.10.ppkg |
|
|
| 3 StdOffice x64 | GCCH_Prod_SFLD_StdOffice-x64_US_Exp_20260430_v4.10.ppkg |
|
|
| 4 ProPlusOffice x86 | GCCH_Prod_SFLD_ProPlusOffice-x86_US_Exp_20260430_v4.10.ppkg |
|
|
| 5 ProPlusOffice x64 | GCCH_Prod_SFLD_ProPlusOffice-x64_US_Exp_20260430_v4.10.ppkg |
|
|
|
|
When you bump PPKG versions, update the filenames in startnet.cmd, drop the
|
|
new PPKGs in `enrollment/` on the workstation, and rebuild the USB.
|
|
|
|
### Site-specific shopfloor config
|
|
|
|
`playbook/shopfloor-setup/site-config.json` has site-specific values like
|
|
default machine number ranges, share paths for software, and more. Inspect
|
|
that file for site name strings, share UNC paths, and machine number ranges.
|
|
|
|
### Branding
|
|
|
|
The Flask webapp uses GE Aerospace branding:
|
|
- Logo: `webapp/static/ge-aerospace-logo.svg`
|
|
- Favicon: `webapp/static/favicon.ico`
|
|
- Page titles and templates reference "GE Aerospace" in `webapp/templates/*.html`
|
|
- iPXE menu title: "GE Aerospace PXE Boot Menu" in `playbook/pxe_server_setup.yml`
|
|
|
|
### Drivers (Dell)
|
|
|
|
Driver content is hardware-specific, not strictly site-specific, but the set
|
|
of driver families to bundle changes by what hardware the site deploys:
|
|
- `Dell_11/Pro` and `Dell_11/ProMax`: Dell Pro Micro PCs (most common shopfloor)
|
|
- `Dell_11/Optiplex`: traditional desktops
|
|
- `Dell_11/Precision`: workstations
|
|
- `Dell_11/Latitude`: laptops (large, often excluded if site has none)
|
|
|
|
The `scripts/download-drivers.py` and `scripts/Download-Drivers.ps1` scripts
|
|
populate `drivers-staging/` from upstream sources. Edit these to target the
|
|
relevant hardware lists.
|
|
|
|
### BIOS update manifest
|
|
|
|
`playbook/shopfloor-setup/BIOS/models.txt` maps Dell model strings to the
|
|
BIOS .exe to flash. Update this whenever new hardware arrives or Dell
|
|
publishes a new firmware release for a model already in the fleet.
|
|
|
|
### Intune DSC categories
|
|
|
|
The post-enrollment Intune DSC delivery (per `intune-dsc.md` memory) pulls
|
|
per-category YAML from Azure Blob:
|
|
- main
|
|
- cmm
|
|
- displaypcs
|
|
- waxtrace
|
|
|
|
Different sites/tenants will need their own categories and their own Azure
|
|
Blob storage account.
|
|
|
|
### Image-upload paths on Windows
|
|
|
|
`scripts/Upload-Image.ps1` defaults to:
|
|
- `\\172.16.9.1\image-upload` as the destination
|
|
- `C:\ProgramData\GEAerospace\MediaCreator\Cache\` as the source
|
|
|
|
Update both for a different site.
|
|
|
|
## Recommended forward state
|
|
|
|
A site config file should drive substitution at build time. Proposed schema:
|
|
|
|
```yaml
|
|
# config/sites/<sitename>.yaml
|
|
site:
|
|
name: westjeff
|
|
pxe_server_ip: 172.16.9.1
|
|
pxe_subnet: 172.16.9.0/24
|
|
dhcp_range_start: 172.16.9.10
|
|
dhcp_range_end: 172.16.9.100
|
|
hostname: pxeserver
|
|
|
|
credentials:
|
|
pxe_user: pxe
|
|
pxe_password: pxe
|
|
pxe_upload_password: pxe
|
|
blancco_password: blancco
|
|
|
|
blancco:
|
|
wifi_ssid: INTERNETACCESS
|
|
wifi_password: Acc3ssGr@nted22
|
|
bmc_endpoint: classic.eu-west-1.blancco.cloud:443
|
|
|
|
ppkg_versions:
|
|
current: v4.10
|
|
expiry: 20260430
|
|
|
|
intune_dsc_categories: [main, cmm, displaypcs, waxtrace]
|
|
|
|
image_types: [gea-standard, gea-engineer, gea-shopfloor]
|
|
shopfloor_types: [gea-shopfloor]
|
|
```
|
|
|
|
`scripts/build-usb.sh` and the playbook would consume this and substitute
|
|
into the templated config files. Implementing this is a separate piece of
|
|
work; until then, edit source files directly.
|
|
|
|
## Secrets handling
|
|
|
|
Some values above are sensitive (WiFi passwords, BMC credentials, Samba
|
|
passwords). Today these sit in plain text in the repo. For a multi-site
|
|
deployment, treat them as per-site secrets:
|
|
- Keep `config/sites/<sitename>.secrets.yaml` out of git (gitignore).
|
|
- Distribute via secure channel (1Password, Vault, etc.) when standing up
|
|
a new site.
|
|
- The `eMxInfo.txt` precedent (see `feedback_emxinfo_secret.md`) is a good
|
|
template: never commit, document where the canonical copy lives.
|