Skip to content

Instantly share code, notes, and snippets.

@rma92
Last active October 24, 2024 10:17
Show Gist options
  • Save rma92/11a6169c68a740ad3dd2b61eac467e7b to your computer and use it in GitHub Desktop.
Save rma92/11a6169c68a740ad3dd2b61eac467e7b to your computer and use it in GitHub Desktop.
Set up AD + WDS + iPXE (2Pint signed)

Setting up a test deployment environment in VMWare Workstation

  • Turn off DHCP on the host-only network adapter in Virtual Network Editor. It uses 192.168.254.0/24, but you can use whatever IP or network you prefer.

Create a Windows Server VM to run a domain controller, DHCP, and WDS.

  • Create a VM using mostly normal settings. Make the main network adapter have NAT or however you connect VMs to the internet, and then add a second network adapter on the host-only network.
  • Set the NIC on the host only network to a static IP (no gateway, we will use the DC for routing. Don't do this in prod):
netsh int ip set address ethernet0 192.168.254.254 255.255.255.0

Install roles and DC

Install-WindowsFeature -Name AD-Domain-Services, DHCP, DNS -IncludeManagementTools
ipmo ADDSDeployment
Install-ADDSForest -DomainName "ad.lab.i.rm.vg" -InstallDNS -CreateDnsDelegation:$false -Force:$true
Restart-Coputer -Force

The computer will reboot and set up the domain controller. It would be advisable to snapshot or backup the VM at this time.

Then set up the DHCP server:

$DHCPServerIP = "192.168.254.254"
Add-DhcpServerInDC -DnsName localhost -IPAddress $DHCPServerIP
Add-DhcpServerv4Scope -Name "Scope1" -StartRange "192.168.254.100" -EndRange "192.168.254.200" -SubnetMask "255.255.255.0" -State Active
Set-DhcpServerv4Binding -InterfaceAlias "Ethernet0" -BindingState $true
Set-DhcpServerv4OptionValue -ScopeId $DHCPServerIP -Router "192.168.254.254"
Set-DhcpServerv4OptionValue -ScopeId $DHCPServerIP -DnsServer "192.168.254.254"

Setup WDS:

mkdir C:\RemoteInstall
$WDSPath = "C:\RemoteInstall"
Install-WindowsFeature -Name WDS,WDS-Deployment,WDS-Transport -IncludeManagementTools
ipmo WDS
wdsutil /Initialize-Server /Server:$env:COMPUTERNAME /reminst:C:\RemoteInstall
copy D:\sources\boot.wim C:\boot.wim
Import-WdsBootImage -Path C:\boot.wim -NewImageName "Win2022 Boot Wim"
wdsutil /Set-Server /AnswerClients:all
#Set-WdsServer -NewClientApprovalPolicy AutoApprove
Set-DhcpServerv4OptionValue -ScopeId "192.168.254.0" -OptionId 66 -Value "192.168.254.254"

Add-DhcpServerv4Class -Name "PXEClient (UEFI x64)" -Type Vendor -Data "PXEClient:Arch:00007"
#Add-DhcpServerv4Class -Name "PXEClient (UEFI x64) 8" -Type Vendor -Data "PXEClient:Arch:00008"
#Add-DhcpServerv4Class -Name "PXEClient (UEFI x64) 9" -Type Vendor -Data "PXEClient:Arch:00009"
Add-DhcpServerv4Class -Name "PXEClient (UEFI x86)" -Type Vendor -Data "PXEClient:Arch:00006"
#Add-DhcpServerv4Class -Name "PXEClient (UEFI x86) 2" -Type Vendor -Data "PXEClient:Arch:00002"
Add-DhcpServerv4Class -Name "PXEClient (BIOS x86 & x64)" -Type Vendor -Data "PXEClient:Arch:00000"

Add-DhcpServerv4Policy -Name "PXEClient (UEFI x64)" -ScopeId 192.168.254.0 -Condition OR -VendorClass EQ,"PXEClient (UEFI x64)*"
Add-DhcpServerv4Policy -Name "PXEClient (UEFI x86)" -ScopeId 192.168.254.0 -Condition OR -VendorClass EQ,"PXEClient (UEFI x86)*"
Add-DhcpServerv4Policy -Name "PXEClient (BIOS x86 & x64)" -ScopeId 192.168.254.0 -Condition OR -VendorClass EQ,"PXEClient (BIOS x86 & x64)*"

Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (UEFI x64)" -OptionId 067 -Value "boot\x64\wdsmgfw.efi"
Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (UEFI x86)" -OptionId 067 -Value "boot\x86\wdsmgfw.efi"
Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (BIOS x86 & x64)" -OptionId 067 -Value "boot\x64\wdsnbp.com"

Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (UEFI x64)" -OptionId 066 -Value "192.168.254.254"
Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (UEFI x86)" -OptionId 066 -Value "192.168.254.254"
Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (BIOS x86 & x64)" -OptionId 066 -Value "192.168.254.254"

copy C:\Windows\System32\RemInst\boot\x64\wdsmgfw.efi C:\RemoteInstall\boot\x64\wdsmgfw.efi

Add-DhcpServerv4Class -Name "iPXE" -Type User -Data "iPXE"
Add-DhcpServerv4Policy -Name "PXEClient (UEFI x64) iPXE" -ScopeId 192.168.254.0 -Condition And -UserClass EQ,"iPXE"

Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (UEFI x64) iPXE" -OptionId 067 -Value "boot\iPXE\iPXE.conf"

The WDS server now works.

Set up WDS to use iPXE

  • Copy the ipxe.zip files to C:\Remoteinstall\boot\ (this includes wimboot.x86_64.efi, x64\snponly_x64.efi, x64\snponly_usb_x64.efi, 2PXE\Boot, 2PXE\File\logo)
  • You need to open the WDS MMC, go to Properties (for the server) > "Boot" tab > Always continue the PXE boot (for both known and unknown clients).
  • Remove Option 60 from the DHCP server, this causes WDS to hijack the DHCP requests.

Set Booting to iPXE:

Set-DhcpServerv4OptionValue -ScopeId 192.168.254.0 -PolicyName "PXEClient (UEFI x64)" -OptionId 067 -Value "boot\x64\snponly_x64.efi"

The iPXE needs internet access, so you need to create a NAT gateway

New-NetNat -Name "Nat1" -InternalIPInterfaceAddressPrefix "192.168.254.0/24"
mkdir C:\RemoteInstall\Boot\iPXE\

Create an iPXE menu in REMINST\Boot\iPXE\iPXE.conf (notepad C:\RemoteInstall\Boot\iPXE\iPXE.conf) containing:

#!ipxe
chain --autofree Boot\iPXE\boot.ipxe.conf

Download Nginx to set up as a web server. In the config file server section, change:

  • listen to 8050 (or another port)
  • in the location / section, change root to C:\RemoteInstall\Boot (the root of TFTP server)
  • add a line error_page 405 =200 $uri;
    • this line allows a POST for a static file.
  • for debugging, add autoindex on; to location / section.
  • Remember to unblock the port in Windows Firewall.

Set DHCP option 175 (custom string) to refer to the HTTP URL for additional files, for example "http://192.168.254.254:8050/". (Note you must append the /)

Add-DhcpServerv4OptionDefinition -OptionId 175 -Name "ipxeUrl" -Type String -Description "iPxe HTTP URL"
Set-DhcpServerv4OptionValue -ScopeId "192.168.254.0" -OptionId 175 -Value "http://192.168.254.254:8050/"

Edit the boot config file to refer to the items that need boot. In this case, the boot config looks for the Windows boot image on our DC, and the Linux images on the internet. The ubuntu image is not working.

To add the RHEL files:

  • make a directory at C:\RemoteInstall\boot\rhel
  • Copy rhel-9.4-x86_64-dvd.iso\EFI\BOOT\BOOTX64.EFI from the RHEL DVD.
  • Copy the kernel (vmlinuz) and initrd.img from the rhel-9.4-x86_64-dvd.iso\images\pxeboot\ directory on the RHEL DVD.
#!ipxe

# Some menu defaults
set menu-timeout 60000
set submenu-timeout ${menu-timeout}
isset ${menu-default} || set menu-default exit


###################### MAIN MENU ####################################

:start
menu iPXE boot menu for Example Ltd
item --gap --               -----------------------  Glazier Images (Blank) --------------------------
item --key b windows-blank  Windows (supports secure boot)
item --key q netboot        NetbootXyz
item rhel9                  Red Hat Enterprise Linux 9 (supports secure boot)
item debian                 Debian
item fedora                 Fedora
item shell                  Drop to iPXE shell
item reboot                 Reboot computer
item
item --key x exit           Exit iPXE and continue BIOS boot
choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel
set menu-timeout 0
goto ${selected}

:cancel
echo You cancelled the menu, dropping you to a shell

:shell
echo Type 'exit' to get the back to the menu
shell
set menu-timeout 0
goto start

:failed
echo Booting failed, dropping to shell
goto shell

:reboot
reboot

:exit
exit

############ MAIN MENU ITEMS ############

:windows-blank
kernel http://192.168.254.254:8050/wimboot.x86_64.efi
initrd http://192.168.254.254:8050/x64/Images/boot.wim.bcd                      BCD
initrd http://192.168.254.254:8050/boot.sdi                 boot.sdi
initrd http://192.168.254.254:8050/x64/Images/boot.wim              boot.wim
boot || goto failed
goto start

:netboot
#chain --autofree http://boot.netboot.xyz/ipxe/netboot.xyz.efi
chain --autofree http://boot.netboot.xyz
boot || goto failed
goto start

:debian
set base-url http://deb.debian.org/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64
kernel ${base-url}/linux console=ttyS1,115200n8
initrd ${base-url}/initrd.gz
boot

:rhel9
set base-url http://192.168.254.254:8050/rhel
initrd ${base-url}/initrd.img
kernel ${base-url}/vmlinuz inst.stage2=hd:LABEL=RHEL-9-4-0-BaseOS-x86_64
shim ${base-url}/BOOTX64.EFI
boot || goto failed

:fedora
set base-url http://dl.fedoraproject.org/pub/archive/fedora/linux/releases/38/Server/x86_64/os/images/pxeboot
initrd ${base-url}/initrd.img
kernel ${base-url}/vmlinuz ip=dhcp ipv6.disable initrd=initrd.img
shim https://dl.fedoraproject.org/pub/archive/fedora/linux/releases/38/Server/x86_64/os/EFI/BOOT/BOOTX64.EFI
boot || goto failed

kernel ${dir}/linux ${install_params} ${mirrorcfg} -- quiet initrd=initrd.gz
initrd ${dir}/initrd.gz
boot || goto failed
goto start

Broken Ubuntu sections:

#item ubuntu                 Ubuntu
:ubuntu
set base-url http://archive.ubuntu.com/ubuntu/dists/focal/main/installer-amd64/current/legacy-images/netboot/ubuntu-installer/amd64/
kernel ${base-url}/linux console=ttyS1,115200n8
initrd ${base-url}/initrd.gz
boot

:ubuntu2
set install_params auto=true priority=critical
set mirror http://archive.ubuntu.com
set base_dir ubuntu
set ubuntu_version bionic
set arch amd64
set mirrorcfg mirror/suite=${ubuntu_version}
set dir ${mirror}/${base_dir}/dists/${version}/main/installer-${arch}/current/images/netboot/ubuntu-installer/${arch}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment