Skip to content
Home » How to Install Windows over PXE Using iPXE, wimboot, Nginx and Samba. Without Windows Server

How to Install Windows over PXE Using iPXE, wimboot, Nginx and Samba. Without Windows Server

A practical, step-by-step guide to deploying Windows 10 over the network using Debian Linux, Kea DHCP and the official iPXE Windows PE boot method.

Installing Windows over the network is particularly useful when managing multiple computers, refurbishing hardware or maintaining a home lab. Instead of preparing USB installation media for every machine, you can boot a computer directly from the network and launch Windows Setup.

In this tutorial, we’ll build a Windows 10 22H2 PXE installer using an existing Debian Linux server. No Windows Server, Windows Deployment Services (WDS) or Microsoft Deployment Toolkit (MDT) is required.

The result is a custom CODEXCITY NETWORK BOOT menu with a Windows 10 installation option.

1. Our Network Infrastructure

Our environment uses Proxmox VE, with the PXE services running inside a Debian Linux container.

ComponentConfiguration
VirtualizationProxmox VE
PXE serverDebian Linux LXC
DHCP serverKea DHCP
Web serverNginx
File sharingSamba
Network bootloaderiPXE
Windows bootloaderwimboot
Operating systemWindows 10 22H2
Installation imageinstall.esd

Kea DHCP and the PXE server run separately. the DHCP server directs network clients to the appropriate bootloader, while Nginx delivers the PXE scripts and Windows boot files.

Prerequisites: A working DHCP/PXE environment, an iPXE-capable client, a Debian server with Nginx and Samba, and legitimate Windows 10 installation media.

This tutorial focuses on adding Windows installation support to an existing iPXE environment. Initial Kea DHCP configuration and iPXE chainloading are outside its scope.

2. Understanding the Boot Process

The installation follows this sequence:

  1. The computer boots from its network interface.
  2. Kea DHCP provides the network configuration and PXE boot information.
  3. iPXE displays the CODEXCITY NETWORK BOOT menu.
  4. The Windows 10 entry loads wimboot, BCD, boot.sdi and boot.wim over HTTP.
  5. Windows PE starts.
  6. A startup script connects to the Samba share.
  7. Windows Setup launches using the installation files stored on the Linux server.

The important distinction is that booting Windows PE does not automatically make the complete Windows installation media available.

The Windows installation files must be provided separately, in our case through Samba.

3. Prepare the Windows Installation Files

First, create the directory for the Windows boot files:

sudo mkdir -p /var/www/html/images/windows10

Mount your Windows 10 ISO and copy its contents to the installation directory.

For example, if the ISO is located at /tmp/windows10.iso:

sudo mkdir -p /mnt/windows10iso
sudo mkdir -p /srv/windows10

sudo mount -o loop,ro /tmp/windows10.iso /mnt/windows10iso

sudo cp -a /mnt/windows10iso/. /srv/windows10/

sudo umount /mnt/windows10iso

The ISO path above is an example; replace it with the location of your own Windows installation media.

Next, make the Windows PE boot files available through Nginx:

cd /var/www/html/images/windows10

sudo mkdir -p boot sources

sudo cp /srv/windows10/boot/BCD boot/
sudo cp /srv/windows10/boot/boot.sdi boot/
sudo cp /srv/windows10/sources/boot.wim sources/

Download wimboot from the official iPXE project:

sudo wget -O wimboot https://boot.ipxe.org/wimboot

Verify the files:

ls -lh wimboot boot/BCD boot/boot.sdi sources/boot.wim

Our Windows 10 boot.wim was approximately 438 MB.

Important: We use the original Windows boot.wim. No modification of the image is necessary for this procedure.

4. Configure Samba

Windows PE needs access to the full Windows installation media, including setup.exe and sources/install.esd.

Install Samba if it is not already installed:

sudo apt update
sudo apt install samba

Create a dedicated deployment account if necessary:

sudo adduser pxedeploy
sudo smbpasswd -a pxedeploy

Ensure that the deployment account can read the installation files.

For our deployment, the following share was added to /etc/samba/smb.conf:

[windows10]
    browseable = No
    comment = Windows 10 PXE Installation
    path = /srv/windows10
    valid users = pxedeploy
    read only = yes
    acl allow execute always = yes

The acl allow execute always setting is relevant because files copied from a Windows ISO onto a Linux filesystem may not have Unix executable permissions.

We encountered an Access is denied error when attempting to launch an executable from the Samba share. Allowing execution through Samba resolved that particular permission problem.

Validate the configuration:

testparm -s

Then reload Samba:

sudo systemctl reload smbd

The installation files are now available at:

\\<ip-address>\windows10

5. Create the Windows PE Startup Script

This is the essential part of the solution.

Instead of modifying boot.wim, we use the file injection capability of wimboot to supply startup files directly to Windows PE.

Create /var/www/html/images/windows10/install.bat:

cd /var/www/html/images/windows10

sudo tee install.bat > /dev/null <<'EOF'
@echo off
wpeinit

echo Connecting to Windows 10 installation share...
net use Z: \\<ip-address>\windows10 /user:pxedeploy *

if errorlevel 1 (
    echo Network connection failed.
    pause
    exit /b 1
)

cd /d Z:\
setup.exe
EOF

Let’s examine what the script does.

wpeinit initializes Windows PE, including network services and Plug and Play device initialization.

The net use command connects to the Samba share and maps it to drive Z:. The asterisk instructs Windows to request the password interactively, rather than storing credentials in the script.

Finally, setup.exe launches Windows Setup from the network installation media.

This means the installer has access to the complete Windows installation source rather than only the files included in boot.wim.

6. Create winpeshl.ini

Windows PE supports a startup configuration file named winpeshl.ini.

Create it on the PXE server:

sudo tee winpeshl.ini > /dev/null <<'EOF'
[LaunchApps]
"install.bat"
EOF

This tells Windows PE to execute our deployment script at startup.

The key advantage is that both files can be injected into Windows PE during network boot.

We do not need to mount, edit, rebuild or replace the original boot.wim.

7. Configure the Windows iPXE Script

Create /var/www/html/images/windows10/boot.ipxe:

#!ipxe

echo ==========================================
echo       Windows 10 22H2 PXE Boot
echo ==========================================

set base http://<ip-address>/images/windows10

kernel ${base}/wimboot
initrd ${base}/install.bat install.bat
initrd ${base}/winpeshl.ini winpeshl.ini
initrd ${base}/boot/BCD BCD
initrd ${base}/boot/boot.sdi boot.sdi
initrd ${base}/sources/boot.wim boot.wim

boot

The two most important lines are:

initrd ${base}/install.bat install.bat
initrd ${base}/winpeshl.ini winpeshl.ini

These provide the startup files to Windows PE through wimboot.

The remaining lines load the standard Windows boot components.

This is the approach described in the official iPXE Windows PE documentation.

8. Add Windows 10 to the Main PXE Menu

Our existing CODEXCITY NETWORK BOOT menu is served from:

/var/www/html/boot.ipxe

The Windows 10 menu entry points to the dedicated Windows boot script.

For an existing menu, add an appropriate menu item and the following target:

:windows10
chain http://<ip-address>/images/windows10/boot.ipxe
goto start

The goto start line returns to our existing menu label if the chainloaded script exits.

This allows us to maintain a central PXE menu for multiple operating systems and recovery tools.

9. Test the HTTP Boot Files

Before attempting a network boot, verify that Nginx serves the required files.

curl -I http://<ip-address>/images/windows10/boot.ipxe
curl -I http://<ip-address>/images/windows10/install.bat
curl -I http://<ip-address>/images/windows10/winpeshl.ini
curl -I http://<ip-address>/images/windows10/wimboot

Each request should return HTTP status 200 OK.

Also verify that the Windows boot files are accessible:

curl -I http://<ip-address>/images/windows10/boot/BCD
curl -I http://<ip-address>/images/windows10/boot/boot.sdi
curl -I http://<ip-address>/images/windows10/sources/boot.wim

Once all files are accessible, the server is ready for testing.

10. Boot Windows 10 over the Network

We tested the installation process on a Dell computer using its network boot capability.

The procedure is straightforward:

  1. Enable network/PXE boot in the computer’s firmware.
  2. Boot from the network interface.
  3. Wait for the CODEXCITY NETWORK BOOT menu.
  4. Select Windows 10 22H2 Installation.
  5. Allow iPXE to download Windows PE.
  6. Enter the Samba deployment password when requested.
  7. Continue through the Windows Setup interface.

During our successful test, Windows PE automatically displayed:

Connecting to Windows 10 installation share...
Type the password for \\<ip-address>\windows10:

This confirmed that the injected startup script was executing correctly.

After authentication, the installation files were available through the network share and Windows Setup could be launched.

Note: Reaching Windows Setup confirms the network deployment mechanism is working. A complete installation should also be tested through disk selection, image application and the first Windows boot before considering the entire deployment process validated.

11. Troubleshooting Lessons

Our initial attempts took considerably longer than expected. Several observations are worth documenting.

Windows PE boots, but Setup asks for a driver

A missing-media-driver message does not necessarily mean the computer needs a storage controller driver.

In our case, Windows PE detected the internal disk and could access the network. The problem was that the Windows installation source was not being supplied through a proper startup workflow.

Booting boot.wim alone does not automatically mount the full Windows ISO.

Check whether install.esd is accessible

From Windows PE, after mapping the Samba share, use:

dism /Get-WimInfo /WimFile:Z:\sources\install.esd

In our test, DISM successfully listed seven Windows 10 editions, including Windows 10 Pro at index 6.

This confirmed that the installation image was accessible and readable over the network.

Access is denied when executing setup.exe

Check Samba permissions and the execute-access configuration.

For our share, this setting was useful:

acl allow execute always = yes

Reload Samba after modifying the configuration.

Setup starts incorrectly or immediately exits

Avoid repeatedly launching different copies of setup.exe from an already-running Windows Setup environment.

Instead, start Windows PE with a defined deployment script that connects to the network installation source before launching Setup.

This was the key architectural improvement in our final configuration.

PXE does not start at all

Before debugging DHCP or iPXE configuration, verify basic network connectivity, including the Ethernet cable.

One of our test interruptions turned out to be a disconnected LAN cable!

12. Back Up the Working Configuration

Once the deployment works, preserve the configuration.

On the PXE server:

cd /var/www/html/images/windows10

sudo tar -czf /root/codexcity-win10-pxe-working.tar.gz \
  boot.ipxe install.bat winpeshl.ini

This creates a small archive containing the three essential configuration files.

The original Windows installation media and boot.wim should also be preserved separately.

For disaster recovery, remember that the complete deployment additionally depends on Nginx, Samba, DHCP and the wimboot binary.

13. Conclusion

We now have a Windows 10 network installation workflow running entirely on Linux infrastructure.

The solution combines:

  • Kea DHCP for network boot configuration.
  • iPXE for the boot menu and HTTP downloads.
  • wimboot for starting Windows PE.
  • Nginx for serving boot files.
  • Samba for providing the Windows installation media.
  • winpeshl.ini and install.bat for starting the installation process.

The most important lesson is simple: you don’t need to modify the Windows boot image to launch a network-based Windows installer.

By injecting a small startup script with wimboot, we can connect Windows PE to the installation source and start Windows Setup using the existing infrastructure.

This provides a reusable foundation for future Windows deployment projects in the Codexcity home lab.

References

Why Windows 10?

I chose Windows 10 for this tutorial because I was refurbishing an older laptop. Although Windows 11 is the current Microsoft desktop operating system in 2026, Windows 10 remains useful for testing and refurbishing older hardware.

The same PXE deployment principles can also be applied to Windows 11.

Leave a Reply

Your email address will not be published. Required fields are marked *