commit 5791bd1b492a24931aceae3cf79e89d41cdec188 Author: cproudlock Date: Fri Feb 6 15:47:36 2026 -0500 Initial project setup: automated PXE server provisioning Reorganized from OneDrive export into a clean project structure: - autoinstall/: cloud-init user-data and meta-data for Ubuntu 24.04 autoinstall - playbook/: Ansible playbook for PXE server config (dnsmasq, Apache, Samba, iPXE) - unattend/: Windows unattend.xml sample for image deployment - build-usb.sh: builds a bootable USB with Ubuntu installer + CIDATA partition - download-packages.sh: downloads all offline .deb dependencies via Docker Key improvements over original: - Fully air-gapped: all packages bundled offline, no WiFi needed - Hardware-agnostic network config (wildcard NIC matching) - Removed plaintext WiFi credentials - Single USB build process (was 15+ manual steps) Co-Authored-By: Claude Opus 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a9f73d --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Large binary files — download/build these, don't commit them +*.deb +*.zip +*.wim +*.iso +*.efi +*.sdi + +# OneDrive download artifacts +OneDrive_*/ + +# Error folders from OneDrive download +__*/ +___*.txt + +# Original OneDrive folder structure (reorganized into autoinstall/ and playbook/) +WestJeff*/ + +# Duplicate at root (canonical copy in unattend/) +/FlatUnattendW10.xml + +# Offline packages (built by download-packages.sh) +offline-packages/ + +# OS files +.DS_Store +Thumbs.db + +# Secrets +secrets.md diff --git a/autoinstall/meta-data b/autoinstall/meta-data new file mode 100644 index 0000000..e69de29 diff --git a/autoinstall/user-data b/autoinstall/user-data new file mode 100644 index 0000000..5a01193 --- /dev/null +++ b/autoinstall/user-data @@ -0,0 +1,106 @@ +#cloud-config +autoinstall: + version: 1 + + # Locale, keyboard, timezone + locale: en_US.UTF-8 + keyboard: + layout: us + variant: "" + timezone: America/New_York + + # Network configuration + # Uses a broad match so any wired NIC gets the static PXE address. + # No WiFi needed — all packages are on the CIDATA partition. + network: + version: 2 + ethernets: + any-eth: + match: + name: "en*" + addresses: + - 10.9.100.1/24 + dhcp4: false + dhcp6: false + optional: true + + # Storage configuration + storage: + layout: + name: lvm + match: + size: largest + swap: + size: 0 + + # User identity + identity: + hostname: pxeserver + username: pxe + password: "$6$rounds=656000$TpsuBw0N85085mpx$KtKsCwFlowg4NY41gUqx5ljef8cJ8uPFfgg43MyCPWByfXkhM5XushcdtkNps6lKeQFQZtli/QU.s52AUc7XC." + + # Installer-stage late commands + late-commands: + # Install deb packages from CIDATA USB + - | + curtin in-target --target=/target -- bash -c ' + mkdir -p /mnt/cidata + CIDATA_DEV=$(blkid -L CIDATA) + if [ -n "$CIDATA_DEV" ]; then + mount "$CIDATA_DEV" /mnt/cidata + if compgen -G "/mnt/cidata/packages/*.deb" > /dev/null; then + cp /mnt/cidata/packages/*.deb /tmp/ + dpkg -i /tmp/*.deb 2>/dev/null || true + dpkg -i /tmp/*.deb 2>/dev/null || true + if command -v nmcli >/dev/null; then + systemctl enable NetworkManager + fi + fi + umount /mnt/cidata + fi + ' + + # Create first-boot.sh + - | + curtin in-target --target=/target -- bash -c ' + cat <<"EOF" > /opt/first-boot.sh + #!/bin/bash + CIDATA_DEV=$(blkid -L CIDATA) + if [ -n "$CIDATA_DEV" ]; then + mkdir -p /mnt/usb + mount "$CIDATA_DEV" /mnt/usb + # Install all offline .deb packages (ansible, dnsmasq, apache2, samba, etc.) + if compgen -G "/mnt/usb/packages/*.deb" > /dev/null; then + dpkg -i /mnt/usb/packages/*.deb 2>/dev/null || true + dpkg -i /mnt/usb/packages/*.deb 2>/dev/null || true + fi + # Run the Ansible playbook + if [ -f /mnt/usb/playbook/pxe_server_setup.yml ]; then + cd /mnt/usb/playbook + ansible-playbook -i localhost, -c local pxe_server_setup.yml + fi + umount /mnt/usb + fi + # Disable rc.local to prevent rerunning + sed -i "s|^/opt/first-boot.sh.*|# &|" /etc/rc.local + lvextend -r -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv || true + EOF + ' + - curtin in-target --target=/target -- chmod +x /opt/first-boot.sh + + # Create rc.local without unintended indentation + - | + curtin in-target --target=/target -- bash -c ' + cat <<"EOF" > /etc/rc.local + #!/bin/bash + /opt/first-boot.sh > /var/log/first-boot.log 2>&1 & + exit 0 + EOF + ' + - curtin in-target --target=/target -- chmod +x /etc/rc.local + + user-data: + disable_root: false + + refresh-installer: + update: yes diff --git a/build-usb.sh b/build-usb.sh new file mode 100755 index 0000000..e474e4f --- /dev/null +++ b/build-usb.sh @@ -0,0 +1,196 @@ +#!/bin/bash +# +# build-usb.sh — Build a bootable PXE-server installer USB +# +# Creates a two-partition USB: +# Partition 1: Ubuntu Server 24.04 installer (ISO contents) +# Partition 2: CIDATA volume (autoinstall config, .debs, playbook) +# +# The target machine boots from this USB, Ubuntu auto-installs with +# cloud-init (user-data/meta-data from CIDATA), installs offline .debs, +# and on first boot runs the Ansible playbook to configure PXE services. +# +# Usage: +# sudo ./build-usb.sh /dev/sdX /path/to/ubuntu-24.04-live-server-amd64.iso +# +# WARNING: This will ERASE the target USB device. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +AUTOINSTALL_DIR="$SCRIPT_DIR/autoinstall" +PLAYBOOK_DIR="$SCRIPT_DIR/playbook" +OFFLINE_PKG_DIR="$SCRIPT_DIR/offline-packages" + +# --- Validate arguments --- +if [ $# -ne 2 ]; then + echo "Usage: sudo $0 /dev/sdX /path/to/ubuntu-24.04.iso" + echo "" + echo "Available removable devices:" + lsblk -d -o NAME,SIZE,TRAN,RM | grep -E '^\S+\s+\S+\s+(usb)\s+1' + exit 1 +fi + +USB_DEV="$1" +ISO_PATH="$2" + +# Safety checks +if [ "$(id -u)" -ne 0 ]; then + echo "ERROR: Must run as root (sudo)." + exit 1 +fi + +if [ ! -b "$USB_DEV" ]; then + echo "ERROR: $USB_DEV is not a block device." + exit 1 +fi + +if [ ! -f "$ISO_PATH" ]; then + echo "ERROR: ISO not found at $ISO_PATH" + exit 1 +fi + +# Verify it's a removable device (safety against wiping system disks) +REMOVABLE=$(lsblk -nd -o RM "$USB_DEV" 2>/dev/null || echo "0") +if [ "$REMOVABLE" != "1" ]; then + echo "WARNING: $USB_DEV does not appear to be a removable device." + read -rp "Are you SURE you want to erase $USB_DEV? (type YES): " CONFIRM + if [ "$CONFIRM" != "YES" ]; then + echo "Aborted." + exit 1 + fi +fi + +# Verify required source files exist +if [ ! -f "$AUTOINSTALL_DIR/user-data" ]; then + echo "ERROR: user-data not found at $AUTOINSTALL_DIR/user-data" + exit 1 +fi + +if [ ! -f "$AUTOINSTALL_DIR/meta-data" ]; then + echo "ERROR: meta-data not found at $AUTOINSTALL_DIR/meta-data" + exit 1 +fi + +if [ ! -f "$PLAYBOOK_DIR/pxe_server_setup.yml" ]; then + echo "ERROR: pxe_server_setup.yml not found at $PLAYBOOK_DIR/" + exit 1 +fi + +echo "============================================" +echo "PXE Server USB Builder" +echo "============================================" +echo "USB Device : $USB_DEV" +echo "ISO : $ISO_PATH" +echo "Source Dir : $SCRIPT_DIR" +echo "" +echo "This will ERASE all data on $USB_DEV." +read -rp "Continue? (y/N): " PROCEED +if [[ ! "$PROCEED" =~ ^[Yy]$ ]]; then + echo "Aborted." + exit 1 +fi + +# --- Unmount any existing partitions --- +echo "" +echo "[1/6] Unmounting existing partitions on $USB_DEV..." +for part in "${USB_DEV}"*; do + umount "$part" 2>/dev/null || true +done + +# --- Write ISO to USB --- +echo "[2/6] Writing Ubuntu ISO to $USB_DEV (this may take several minutes)..." +dd if="$ISO_PATH" of="$USB_DEV" bs=4M status=progress oflag=sync +sync + +# --- Find the end of the ISO to create CIDATA partition --- +echo "[3/6] Creating CIDATA partition after ISO data..." + +# Get ISO size in bytes and calculate the start sector for the new partition +ISO_SIZE=$(stat -c%s "$ISO_PATH") +SECTOR_SIZE=512 +# Start the CIDATA partition 1MB after the ISO ends (alignment) +START_SECTOR=$(( (ISO_SIZE / SECTOR_SIZE) + 2048 )) + +# Use sfdisk to append a new partition +echo " ISO size: $((ISO_SIZE / 1024 / 1024)) MB" +echo " CIDATA partition starts at sector $START_SECTOR" + +# Add a new partition using sfdisk --append +echo "${START_SECTOR},+,L" | sfdisk --append "$USB_DEV" --no-reread 2>/dev/null || true +partprobe "$USB_DEV" +sleep 2 + +# Determine the new partition name (could be sdX3, sdX4, etc.) +CIDATA_PART="" +for part in "${USB_DEV}"[0-9]*; do + # Find the partition that starts at or after our start sector + PART_START=$(sfdisk -d "$USB_DEV" 2>/dev/null | grep "$part" | grep -o 'start=[[:space:]]*[0-9]*' | grep -o '[0-9]*') + if [ -n "$PART_START" ] && [ "$PART_START" -ge "$START_SECTOR" ]; then + CIDATA_PART="$part" + break + fi +done + +# Fallback: use the last partition +if [ -z "$CIDATA_PART" ]; then + CIDATA_PART=$(lsblk -ln -o NAME "$USB_DEV" | tail -1) + CIDATA_PART="/dev/$CIDATA_PART" +fi + +echo " CIDATA partition: $CIDATA_PART" + +# --- Format CIDATA partition --- +echo "[4/6] Formatting $CIDATA_PART as FAT32 (label: CIDATA)..." +mkfs.vfat -F 32 -n CIDATA "$CIDATA_PART" + +# --- Mount and copy files --- +echo "[5/6] Copying autoinstall config, packages, and playbook to CIDATA..." +MOUNT_POINT=$(mktemp -d) +mount "$CIDATA_PART" "$MOUNT_POINT" + +# Copy cloud-init files +cp "$AUTOINSTALL_DIR/user-data" "$MOUNT_POINT/" +cp "$AUTOINSTALL_DIR/meta-data" "$MOUNT_POINT/" + +# Copy offline .deb packages into packages/ subdirectory +mkdir -p "$MOUNT_POINT/packages" +DEB_COUNT=0 + +if [ -d "$OFFLINE_PKG_DIR" ]; then + for deb in "$OFFLINE_PKG_DIR"/*.deb; do + if [ -f "$deb" ]; then + cp "$deb" "$MOUNT_POINT/packages/" + DEB_COUNT=$((DEB_COUNT + 1)) + fi + done +fi +echo " Copied $DEB_COUNT .deb packages to packages/" + +# Copy playbook directory +cp -r "$PLAYBOOK_DIR" "$MOUNT_POINT/playbook" +echo " Copied playbook/" + +# List what's on CIDATA +echo "" +echo " CIDATA contents:" +ls -lh "$MOUNT_POINT/" | sed 's/^/ /' + +# --- Cleanup --- +echo "" +echo "[6/6] Syncing and unmounting..." +sync +umount "$MOUNT_POINT" +rmdir "$MOUNT_POINT" + +echo "" +echo "============================================" +echo "USB build complete!" +echo "============================================" +echo "" +echo "Next steps:" +echo " 1. Insert USB into target machine" +echo " 2. Boot from USB (F12 / boot menu)" +echo " 3. Ubuntu will auto-install and configure the PXE server" +echo " 4. After reboot, move the NIC to the isolated PXE network" +echo "" diff --git a/download-packages.sh b/download-packages.sh new file mode 100755 index 0000000..9c92a15 --- /dev/null +++ b/download-packages.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# +# download-packages.sh — Download all .deb packages needed for offline PXE server setup +# +# Run this on a machine with internet access running Ubuntu 24.04 (Noble). +# It downloads every .deb needed by the Ansible playbook into a local directory, +# which then gets bundled onto the installer USB. +# +# Usage: +# ./download-packages.sh [output_directory] +# +# Default output: ./offline-packages/ + +set -euo pipefail + +OUT_DIR="${1:-./offline-packages}" +mkdir -p "$OUT_DIR" + +# Packages installed by the Ansible playbook (pxe_server_setup.yml) +PLAYBOOK_PACKAGES=( + ansible + dnsmasq + apache2 + samba + unzip + ufw + cron +) + +# Packages installed during autoinstall late-commands (NetworkManager, WiFi, etc.) +# These are already in your ubuntu_playbook/*.deb files, but we can refresh them here too. +AUTOINSTALL_PACKAGES=( + network-manager + wpasupplicant + wireless-tools + linux-firmware + firmware-sof-signed +) + +ALL_PACKAGES=("${PLAYBOOK_PACKAGES[@]}" "${AUTOINSTALL_PACKAGES[@]}") + +echo "============================================" +echo "Offline Package Downloader" +echo "============================================" +echo "Output directory: $OUT_DIR" +echo "" +echo "Packages to resolve:" +printf ' - %s\n' "${ALL_PACKAGES[@]}" +echo "" + +# Update package cache +echo "[1/3] Updating package cache..." +sudo apt-get update -qq + +# Simulate install to find all dependencies +echo "[2/3] Resolving dependencies..." +DEPS=$(apt-get install --simulate "${ALL_PACKAGES[@]}" 2>&1 \ + | grep "^Inst " \ + | awk '{print $2}' \ + | sort -u) + +DEP_COUNT=$(echo "$DEPS" | wc -l) +echo " Found $DEP_COUNT packages (including dependencies)" + +# Download all packages +echo "[3/3] Downloading packages to $OUT_DIR..." +cd "$OUT_DIR" +apt-get download $DEPS 2>&1 | tail -5 + +DEB_COUNT=$(ls -1 *.deb 2>/dev/null | wc -l) +TOTAL_SIZE=$(du -sh . | cut -f1) + +echo "" +echo "============================================" +echo "Download complete!" +echo "============================================" +echo " Packages: $DEB_COUNT" +echo " Total size: $TOTAL_SIZE" +echo " Location: $OUT_DIR/" +echo "" +echo "Next: copy these into your ubuntu_playbook/ directory" +echo " cp $OUT_DIR/*.deb /path/to/ubuntu_playbook/" +echo "" diff --git a/playbook/inventory.ini b/playbook/inventory.ini new file mode 100644 index 0000000..da6afa1 --- /dev/null +++ b/playbook/inventory.ini @@ -0,0 +1,2 @@ +[pxe_servers] +localhost ansible_connection=local diff --git a/playbook/pxe_server_setup.yml b/playbook/pxe_server_setup.yml new file mode 100644 index 0000000..d380452 --- /dev/null +++ b/playbook/pxe_server_setup.yml @@ -0,0 +1,272 @@ +--- +- name: PXE Server Setup (Ubuntu with dnsmasq) + hosts: localhost + connection: local + become: yes + gather_facts: yes + + pre_tasks: + - name: "Verify required packages are installed (pre-installed from offline .debs)" + command: dpkg -s {{ item }} + loop: + - dnsmasq + - apache2 + - samba + - unzip + - ufw + - cron + - ansible + register: pkg_check + failed_when: false + changed_when: false + + - name: "Warn about missing packages" + debug: + msg: "WARNING: {{ item.item }} is not installed! Install offline .debs first." + loop: "{{ pkg_check.results }}" + when: item.rc != 0 + + vars: + tftp_dir: "/srv/tftp" + web_root: "/var/www/html" + samba_share: "/srv/samba/winpeapps" + usb_mount: "/mnt/usb/playbook" # where your USB is mounted + image_types: + - geastandardpbr + - geaengineerpbr + - geashopfloorpbr + - gestandardlegacy + - geengineerlegacy + - geshopfloorlegacy + deploy_subdirs: + - Applications + - Control + - "Operating Systems" + - "Out-of-box Drivers" + - Packages + - Tools + + tasks: + - name: "Gather minimal network facts" + ansible.builtin.setup: + filter: + - ansible_interfaces + - ansible_default_ipv4 + + - name: "Bring up all ethernet-like interfaces" + command: ip link set dev {{ item }} up + loop: "{{ ansible_interfaces | select('match','^e(th|n)') | list }}" + ignore_errors: yes + + - name: "Determine PXE interface" + set_fact: + pxe_iface: >- + {{ (ansible_interfaces + | select('match','^e(th|n)') + | reject('equalto','lo') + | reject('equalto', ansible_default_ipv4.interface) + | list + ) + | first + | default(ansible_default_ipv4.interface) }} + + - name: "Debug: final pxe_iface choice" + debug: + msg: "Using {{ pxe_iface }} for DHCP/TFTP" + + - name: "Configure dnsmasq for DHCP and TFTP" + copy: + dest: /etc/dnsmasq.conf + backup: yes + content: | + port=0 + interface={{ pxe_iface }} + bind-interfaces + dhcp-range=10.9.100.10,10.9.100.100,12h + dhcp-option=3,10.9.100.1 + dhcp-option=6,8.8.8.8 + enable-tftp + tftp-root={{ tftp_dir }} + dhcp-boot=ipxe.efi + + - name: "Create TFTP directory" + file: + path: "{{ tftp_dir }}" + state: directory + mode: '0755' + owner: nobody + group: nogroup + + - name: "Create Win11 directory structure" + file: + path: "{{ web_root }}/win11/{{ item }}" + state: directory + mode: '0755' + loop: + - "EFI/Boot" + - "EFI/Microsoft/Boot" + - "Boot" + - "sources" + + - name: "Create Altiris iPXE directory" + file: + path: "{{ web_root }}/Altiris/iPXE" + state: directory + mode: '0755' + + - name: "Create GetPxeScript.aspx" + copy: + dest: "{{ web_root }}/Altiris/iPXE/GetPxeScript.aspx" + backup: yes + content: | + #!ipxe + + set server 10.9.100.1 + + kernel http://${server}/win11/wimboot gui + + initrd http://${server}/win11/EFI/Microsoft/Boot/boot.stl EFI/Microsoft/Boot/Boot.stl + initrd http://${server}/win11/EFI/Microsoft/Boot/BCD EFI/Microsoft/Boot/BCD + initrd http://${server}/win11/EFI/Boot/bootx64.efi EFI/Boot/bootx64.efi + initrd http://${server}/win11/Boot/boot.sdi Boot/boot.sdi + initrd http://${server}/win11/sources/boot.wim sources/boot.wim + + boot + + - name: "Ensure Apache listens on port 4433" + lineinfile: + path: /etc/apache2/ports.conf + line: "Listen 4433" + backup: yes + state: present + + - name: "Create VirtualHost for Altiris iPXE on 4433" + copy: + dest: /etc/apache2/sites-available/altiris-ipxe.conf + backup: yes + content: | + + DocumentRoot {{ web_root }} + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + AddType text/plain .aspx + + + + - name: "Enable Altiris iPXE site" + command: a2ensite altiris-ipxe.conf + args: + creates: /etc/apache2/sites-enabled/altiris-ipxe.conf + + - name: "Reload Apache to apply changes" + systemd: + name: apache2 + state: reloaded + + - name: "Create Samba share root" + file: + path: "{{ samba_share }}" + state: directory + mode: '0777' + + - name: "Configure Samba share" + blockinfile: + path: /etc/samba/smb.conf + backup: yes + block: | + [winpeapps] + path = {{ samba_share }} + browseable = yes + read only = no + guest ok = yes + + - name: "Create image-type top-level directories" + file: + path: "{{ samba_share }}/{{ item }}" + state: directory + mode: '0777' + loop: "{{ image_types }}" + + - name: "Create Deploy subdirectories for each image type" + file: + path: "{{ samba_share }}/{{ item.0 }}/Deploy/{{ item.1 }}" + state: directory + mode: '0777' + with_nested: + - "{{ image_types }}" + - "{{ deploy_subdirs }}" + + - name: "Copy WinPE & boot files from USB" + copy: + src: "{{ usb_mount }}/{{ item.src }}" + dest: "{{ web_root }}/win11/{{ item.dest }}" + mode: '0644' + loop: + - { src: "wimboot", dest: "wimboot" } + - { src: "boot.stl", dest: "EFI/Microsoft/Boot/boot.stl" } + - { src: "BCD", dest: "EFI/Microsoft/Boot/BCD" } + - { src: "bootx64.efi", dest: "EFI/Boot/bootx64.efi" } + - { src: "boot.sdi", dest: "Boot/boot.sdi" } + - { src: "boot.wim", dest: "sources/boot.wim" } + + - name: "Copy iPXE binaries from USB" + copy: + src: "{{ usb_mount }}/{{ item }}" + dest: "{{ tftp_dir }}/{{ item }}" + mode: '0755' + loop: + - ipxe.efi + + - name: "Restart and enable services" + systemd: + name: "{{ item }}" + state: restarted + enabled: yes + loop: + - dnsmasq + - apache2 + - smbd + + - name: "Allow necessary firewall ports (UFW)" + ufw: + rule: allow + port: "{{ item }}" + proto: "{{ 'udp' if item in ['67','69'] else 'tcp' }}" + loop: + - 67 + - 69 + - 80 + - 4433 + - 445 + + - name: "Enable UFW firewall" + ufw: + state: enabled + policy: allow + + - name: "Schedule dnsmasq restart 15s after reboot" + cron: + name: "Restart dnsmasq after reboot" + user: root + special_time: "reboot" + job: "/bin/sleep 15 && /usr/bin/systemctl restart dnsmasq.service" + + - name: "Configure static IP for PXE interface" + copy: + dest: /etc/netplan/50-cloud-init.yaml + backup: yes + content: | + network: + version: 2 + renderer: networkd + ethernets: + {{ pxe_iface }}: + dhcp4: no + addresses: [10.9.100.1/24] + notify: "Apply netplan" + + handlers: + - name: "Apply netplan" + command: netplan apply diff --git a/setup-guide-original.txt b/setup-guide-original.txt new file mode 100644 index 0000000..2eaa0f6 --- /dev/null +++ b/setup-guide-original.txt @@ -0,0 +1,129 @@ +Purpose +Document a repeatable, “build-from-scratch” procedure for deploying an Ubuntu-based PXE boot server that can host GE Aerospace Windows PE images. + +Prerequisites +Hardware: Server or PC with ≥ 8 GB RAM, ≥ 250 GB disk, and one NIC (one for build / Internet, one for isolated PXE LAN) + +https://myaccess.microsoft.us/@ge.onmicrosoft.us#/access-packages/active + +EPM Rufus Exception Request +EPM DT Functions +DLP - Encrypted Removable (USB) Long Term Access + +Software: + +Ubuntu Server 24.04 ISO + +Rufus (latest) + +playbook folder containing pxe_server_setup.yml and supporting files + +GE Aerospace Media Creator LITE (for caching WinPE images) + +Two USB thumb drives (one ≥ 8 GB for Ubuntu install; one ≥ 32 GB for WinPE media) + +Step-by-Step Procedure +Create the Ubuntu Server installer USB +1.1 Download Ubuntu Server 24.04 from https://ubuntu.com/download/server. +1.2 Download and run Rufus (https://rufus.ie/en/). +1.3 Insert an empty USB, select it in Rufus. +1.4 Click Select, browse to the Ubuntu ISO, then click Start. +1.5 When Rufus finishes, copy your playbook folder to the root of that same USB, then eject it safely. + +Install Ubuntu on the PXE server +2.1 Insert the USB into the target machine and power on. +2.2 Press F12 (or the vendor’s one-time boot key) and choose the USB device. +2.3 Follow Ubuntu’s installer; +Network configuration screen. +Select the fist option select give it random network and IPv4 address +Then select WiFi and choose the guest network. +Follow the prompts and enter the information for your network. +Click done. + +You do not need a proxy hit done. +For mirror address add nothing and hit done. The download should start. + +After that select next +You'll be in file system summary: Hit done, box will pop up "confirm destructive action" select "continue" + +Configure your profile. Done +Skip the upgrade to ubuntu pro +No ssh +Don't select featured server snaps just select done + +Ubuntu will install…..then reboot your system +2.4 Create a user (e.g., pxe) with a simple, temporary password (change later). + +Prepare the OS +3.1 Log in as the user you created. + +3.2 Update the system: + +bash +Copy +sudo apt update && sudo apt upgrade -y + +3.3 Install Ansible: + +bash +Copy +sudo apt install ansible -y +Mount the installer USB and run the playbook + +4.1 Identify the USB device: + +bash +Copy +lsblk +Note the device (e.g., /dev/sda1). + +4.2 Mount it and run the playbook: + +bash +Copy +sudo mkdir -p /mnt/usb +sudo mount /dev/sda1 /mnt/usb +cd /mnt/usb/playbook +ansible-playbook pxe_server_setup.yml + + +4.3 When Ansible finishes, umount the USB: + +bash +Copy +cd ~ +sudo umount /mnt/usb + +Cache Windows PE images +5.1 On a separate workstation, use GE Aerospace Media Creator LITE to cache all desired images (or start with one). +5.2 Create a WinPE USB using the same tool and eject it safely. + +Import WinPE content to the PXE share +6.1 Insert the WinPE USB into the PXE server. +6.2 Find the new device (e.g., /dev/sdb2) with lsblk. +6.3 Mount it and copy files: + +bash +Copy +sudo mkdir -p /mnt/usb2 +sudo mount /dev/sdb2 /mnt/usb2 +sudo cp -r /mnt/usb2/. /srv/samba/winpeapps/standard +sudo umount /mnt/usb2 +Finalise and isolate + +7.1 Reboot the server: + +bash +Copy +sudo reboot + +7.2 After it comes back up, move the primary NIC from the Internet-enabled network to the isolated switch that will serve PXE clients. + +6. Verification +Connect a test workstation to the isolated switch. + +In BIOS/UEFI, set Network Boot (PXE) as first boot, then boot. + +Confirm the client pulls an IP from the PXE server and sees the WinPE menu. + +Launch a WinPE image to ensure TFTP, HTTP (NBD), and SMB shares respond correctly. diff --git a/unattend/FlatUnattendW10.xml b/unattend/FlatUnattendW10.xml new file mode 100644 index 0000000..4a0b18d --- /dev/null +++ b/unattend/FlatUnattendW10.xml @@ -0,0 +1,222 @@ + + + + + + + + + + + + W:\Drivers + + + W:\Deploy\Applications\extra\printdrivers\BROTHER\UNIV-PS-01181\PS\64 + + + W:\Deploy\Applications\extra\printdrivers\HP + + + W:\Deploy\Applications\extra\printdrivers\XEROX\UNIV_5.1035.2.0_PS_x64_Driver + + + + + + + + + + H%serialnumber% + GE Aerospace + GE + Eastern Standard Time + + + + + + + + 1 + msiexec /i "C:\Deploy\Applications\extra\wireless\EAP-PEAP.msi" /quiet /norestart + Install EAP-PEAP + + + + + 2 + cmd /c netsh wlan add profile filename="C:\Deploy\Applications\extra\wireless\BLUESSO.xml" user=all + Add BLUESSO WiFi profile + + + 3 + cmd /c netsh wlan add profile filename="C:\Deploy\Applications\extra\wireless\WiFi-Profile.xml" user=all + Add generic WiFi profile + + + + + 4 + cmd /c certutil -addstore Root "C:\Deploy\Applications\GE_External_Root_CA_2_1.cer" + Install External Root Certificate + + + 5 + cmd /c certutil -addstore CA "C:\Deploy\Applications\GE_External_Intermediate_CA_2_1.cer" + Install External Intermediate Certificate + + + 6 + cmd /c certutil -addstore Root "C:\Deploy\Applications\GE_Enterprise_Root_CA_2_1.cer" + Install Enterprise Root Certificate + + + 7 + cmd /c certutil -addstore CA "C:\Deploy\Applications\GE_Enterprise_Device_Issuing_CA_2_1.cer" + Install Enterprise Device Issuing Certificate + + + 8 + cmd /c certutil -addstore CA "C:\Deploy\Applications\GE_Enterprise_Server_Issuing_CA_2_1.cer" + Install Enterprise Server Issuing Certificate + + + 9 + cmd /c certutil -addstore CA "C:\Deploy\Applications\GE_Enterprise_Smart_Card_Issuing_CA_2_1.cer" + Install SmartCard Issuing Certificate + + + 10 + cmd /c certutil -addstore CA "C:\Deploy\Applications\GE_Enterprise_User_Issuing_CA_2_1.cer" + Install User Issuing Certificate + + + 11 + cmd /c certutil -addstore Root "C:\Deploy\Applications\GE_Aerospace_Enterprise_Root_CA_1.cer" + Install Aerospace Enterprise Root CA + + + 12 + cmd /c certutil -addstore Root "C:\Deploy\Applications\ZscalerCommercialCertificate-2048-SHA256.crt" + Install Zscaler Certificate + + + + + 13 + cmd /c copy "C:\Deploy\Applications\extra\fonts\3OF9.TTF" "%WINDIR%\Fonts\" /Y + Copy 3OF9 Font + + + 14 + cmd /c reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /v "3 of 9 Barcode" /t REG_SZ /d "3OF9.TTF" /f + Register 3OF9 Barcode Font + + + 15 + cmd /c copy "C:\Deploy\Applications\extra\fonts\Code39AzaleaNarrow3.ttf" "%WINDIR%\Fonts\" /Y + Copy Code39 Azalea Narrow Font + + + 16 + cmd /c reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /v "Code39AzaleaNarrow3" /t REG_SZ /d "Code39AzaleaNarrow3.ttf" /f + Register Code39 Azalea Narrow Font + + + 17 + cmd /c copy "C:\Deploy\Applications\extra\fonts\Code39Azalea.ttf" "%WINDIR%\Fonts\" /Y + Copy Code39 Azalea Font + + + 18 + cmd /c reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /v "Code39Azalea" /t REG_SZ /d "Code39Azalea.ttf" /f + Register Code39 Azalea Font + + + + + 19 + C:\Deploy\Applications\extra\opentext\opentext_hostexplorer_sp1_15.0_v01.exe /quiet /norestart + Install OpenText HostExplorer SP1 + + + 20 + C:\Deploy\Applications\extra\opentext\J2SE_Runtime_Environment_1.6.0_22_Static_Config_V2_Co-Exist.EXE /silent /norestart + Install J2SE Runtime Environment 1.6.0_22 + + + 21 + C:\Deploy\Applications\extra\opentext\unattended.bat + Install J2SE Runtime Environment 1.6.0_22 + + + + + 22 + msiexec /i "C:\Deploy\Applications\extra\adobe\AcroRead.msi" TRANSFORMS="C:\Deploy\Applications\extra\adobe\AcroRead.mst" /quiet /norestart + Install Adobe + + + 23 + msiexec /p "C:\Deploy\Applications\extra\adobe\AcroRdrDCUpd2500120531.msp" /quiet /norestart + Apply Adobe Reader Update + + + + + + + + + + true + true + false + false + true + Work + 3 + false + false + + + + 1 + C:\Deploy\Applications\extra\zscaler\zscaler.bat + Install Zscaler Client Connector + + + 2 + shutdown -a + Cancel any scheduled shutdown from Office installation + + + 3 + cmd /c cd C:\Deploy\Applications\extra\office && install.bat + Install Office + + + + + + \ No newline at end of file