I have figured out how to install Windows 10 directly into iSCSI LUNs for diskless clients. Tiny PXE Server is set up on the iSCSI server. A customized WinPE with iSCSI Initiator enabled, along with Win10 OS installation files, are put into a small (8-10GB) iSCSI LUN to support over-the-network OS installation. iPXE is used on the diskless clients. The high level steps are as follows:
- Windows Server 2012 R2, Tiny PXE Server & iPXE used in this procedure
- Recommend using dynamically expanding VHDX file with Windows Server 2012 R2
A. Create and quick format iSCSI LUN disk partition to NTFS
B. Add client MAC address to IQN for its dedicated iSCSI LUN
A. Add client MAC addresses to IQN for this iSCSI LUN
B. Prepare customized WinPE with iSCSI Initiator enabled
- See add_iscsi.cmd batch file example to customize WinPE
C. Mount iSCSI LUN to drive letter
D. Transfer customized WinPE and OS installation files into iSCSI LUN
- WinPE files to root (\sources, \boot, \efi, \bootmgr, \bootmgr.efi, etc.)
- OS installation files to a folder, e.g. \Win10
E. Set iSCSI LUN disk partition to Active for booting
- e.g. DISKPART - sel dis 1, sel par 1, active
F. Unmount/Eject iSCSI LUN
- Configure iPXE boot script to support both OS installation (once per client) and diskless booting for clients
- See iscsi.ipxe script example
- e.g. C:\Win10\sources
Here's a sample iscsi.ipxe file:
================================================
#!ipxe
ifopen net0
dhcp
set net0/gateway 0.0.0.0
echo IP: ${net0/ip}, Gateway: ${net0/gateway}
set net0/keep-san 1
echo keep-san: ${net0/keep-san}
sanboot iscsi:<server IP>::::iqn.1991-05.com.microsoft:<server name>-win10-client1-target ||
sanboot iscsi:<server IP>::::iqn.1991-05.com.microsoft:<server name>-win10-client2-target ||
sanboot iscsi:<server IP>::::iqn.1991-05.com.microsoft:<server name>-win10-install-target
================================================
Note:
- replace <server IP> with iSCSI server static IP address: e.g. 192.168.0.100
- replace <server name> with iSCSI server name, e.g. iSCSIserver. This name must match what the client sees within iSCSI Initiator
- setting gateway address to 0.0.0.0 is a workaround to avoid Windows 10 suffering an "INACCESSIBLE BOOT DEVICE" blue screen crash during boot
This script supports a one-time OS installation into a diskless client, as well as the subsequent OS bootups. The above example has iSCSI LUNs set up for two clients, but can be extended to an arbitrary number of clients. The iSCSI LUNs are set up to match the MAC address of the intended clients, so a given client will always sanboot from its corresponding iSCSI LUN.
By pre-formatting the iSCSI LUN disk partitions (for each client), the first time the client PXE boots, the sanboot command for the iSCSI LUN will fail, since the disk is still blank (though formatted), so the iPXE script falls through to the last line which connects to the "OS install" iSCSI LUN and boots to a WinPE command prompt. After running iSCSI Initiator (iscsicpl) to connect to the iSCSI LUN, OS installation can start in much the same way as for a local physical disk.
I have been successfully using ipxe-undionly.kpxe included in Tiny PXE Server 1.0.0.19.
Following is a batch file used to customize WinPE (64-bit) to add iSCSI Initiator support:
Add_iSCSI.cmd:
===================================
set WindowsPE=C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\WinPE_OCs
if not exist C:\Mounted_WIM md C:\Mounted_WIM
Dism /Mount-Image /ImageFile:C:\WinPE\media\sources\boot.wim /Index:1 /MountDir:C:\Mounted_WIM
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\WinPE-WMI.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\en-us\WinPE-WMI_en-us.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\WinPE-NetFX.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\en-us\WinPE-NetFX_en-us.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\WinPE-Scripting.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\en-us\WinPE-Scripting_en-us.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\WinPE-PowerShell.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\en-us\WinPE-PowerSHell_en-us.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\WinPE-StorageWMI.cab"
Dism /Add-Package /Image:C:\Mounted_WIM /PackagePath:"%WindowsPE%\en-us\WinPE-StorageWMI_en-us.cab"
copy C:\windows\system32\iscsicpl.dll C:\Mounted_WIM\windows\system32
copy C:\windows\system32\iscsicpl.exe C:\Mounted_WIM\windows\system32
copy C:\windows\system32\en-us\iscsicpl.dll.mui C:\Mounted_WIM\windows\system32\en-us
copy C:\windows\system32\en-us\iscsicpl.exe.mui C:\Mounted_WIM\windows\system32\en-us
Dism /Get-Packages /Image:C:\Mounted_WIM
pause
Dism /Unmount-Image /MountDir:C:\Mounted_WIM /commit
===================================
This batch file works with Windows 10 ADK (Assessment and Deployment Kit) which can be downloaded from Microsoft.
A firewall opening for Tiny PXE Server is needed. This type of remote OS booting from iSCSI LUN apparently works only if the network interconnecting the server and clients is set to "private" (instead of "public") at the server. If Windows Server OS see the network as "unidentified", run gpedit.msc to change the network type from "public" to "private".
I'm working on a more detailed step-by-step procedure to be available later.
A big thanks to Erwan for Tiny PXE Server in making this possible.