A Windows 11 ISO will not go onto a USB stick the way a Linux ISO does. Writing it with dd gives you a stick that starts Windows Setup and then fails, and the obvious fix of formatting the stick FAT32 and copying the files over stops at one file that is too big. On Linux the reliable answer is a FAT32 stick with that one file split in two, which boots on almost any UEFI PC with Secure Boot left on.
This guide builds that stick with plain Linux tools, then covers WoeUSB-ng as the one-command alternative and shows exactly why dd fails. Every command below was run on Ubuntu 26.04 in October 2026, and both finished sticks were booted on a UEFI machine with Secure Boot enabled, with one of them taken through a full Windows 11 install.
Pick a method
We wrote the same Windows 11 ISO to a 16 GB stick three ways and booted each one on a UEFI virtual machine with Secure Boot on. You can see the outcome of each in this table.
| Method | Result with Secure Boot on | Time on the lab VM | What it needs |
|---|---|---|---|
| FAT32 + split install.wim | Booted, full Windows install completed | About 1.5 minutes | parted, mkfs.vfat, rsync, wimlib |
| WoeUSB-ng | Booted to Windows Setup | 2 minutes 13 seconds | A Python tool with an awkward install on current Ubuntu |
dd straight to the stick | Setup started, then “A media driver your computer needs is missing” | Not measured | Nothing, which is why people try it |
The times come from a virtual disk, so on real hardware the stick’s write speed sets the pace. At 30 MB/s, 7.7 GB takes over four minutes on its own. The FAT32 method wins because the stick boots Microsoft’s own Windows-signed boot loader, so it does not depend on any extra certificate in your firmware. If you want one stick that carries several ISOs at once, Ventoy on Linux is the better tool, and the general bootable USB guide covers Linux ISOs, where dd is fine.
Download the Windows ISO and check it
Get the ISO from Microsoft’s Windows 11 download page in a browser. On Linux the page offers the ISO directly, without the Media Creation Tool. Scripted downloads are a different story. quickget from the quickemu package got this reply from Microsoft on our lab VM, shown here trimmed to the two relevant lines, so expect to click through the page yourself.
- WARNING! Microsoft blocked the automated download request based on your IP address.
Manually download the Windows 11 ISO using a web browser from: https://www.microsoft.com/en-us/software-download/windows11
Our lab used the Windows 11 Enterprise evaluation ISO from Microsoft’s Evaluation Center, because it has a direct download link. Its layout is the same as the consumer ISO, and Windows 10 ISOs use the same layout too. Mount the ISO read-only and look at the size of sources/install.wim, because that one file decides which method you need:
ISO=~/Win11_Enterprise_Eval_x64.iso
sha256sum "$ISO"
sudo mkdir -p /mnt/iso /mnt/usb
sudo mount -o loop,ro "$ISO" /mnt/iso
ls -l /mnt/iso/sources/install.wim
Set ISO to wherever your browser saved the file; ours sat in the home directory. Compare the hash with the one on Microsoft’s download page when it lists one. The evaluation page did not, so we recorded ours, which only matches that exact Enterprise evaluation build. The important number is the size of install.wim:
bc3f24086ebadc94489066b5ad78089e2cf5c3491e90e790bb81a2b199c10e38 /home/josphat/Win11_Enterprise_Eval_x64.iso
-r-xr-xr-x 1 nobody nogroup 7333902541 Sep 13 19:17 /mnt/iso/sources/install.wim
That is 7.3 GB in a single file. UEFI firmware reads FAT32, and FAT32 cannot hold a file of 4 GiB or more, so copying install.wim to a FAT32 stick fails partway with this error from cp:
cp: error writing '/mnt/usb/install.wim': File too large
If your install.wim is under 4 GiB, skip the split step below and drop --exclude=sources/install.wim from the rsync command so it copies everything. Check the number rather than assuming, because it grows with each Windows release. We tested with a Windows 11 ISO; Windows 10 media uses the same sources layout, so the steps carry over, but we did not boot a Windows 10 stick.
Find the USB stick
Everything on the stick is erased, so make sure you are pointing at the right device. Plug it in and list the block devices:
lsblk -o NAME,SIZE,TYPE,TRAN,MODEL,MOUNTPOINTS
On the lab VM the 16 GB stick is sda, and the system disk is vda with / mounted on it. A physical stick also shows usb in the TRAN column and its brand under MODEL, which makes it easy to tell apart from your SSD:
NAME SIZE TYPE TRAN MODEL MOUNTPOINTS
sda 16G disk QEMU HARDDISK
sr0 4M rom ata QEMU DVD-ROM
vda 60G disk virtio
├─vda1 58.9G part virtio /
├─vda13 1023M part virtio /boot
├─vda14 4M part virtio
└─vda15 106M part virtio /boot/efi
Store the device in a variable so the commands below cannot drift onto the wrong disk halfway through, and so you only have to get it right once. If your desktop auto-mounted the stick, unmount its partitions before you go on, since the next step rewrites the partition table under them and wipefs refuses a busy device. An error from the second line saying nothing is mounted is harmless:
USB=/dev/sda
sudo umount ${USB}?*
The commands below name the partition ${USB}1, which is right for sdX devices. A built-in SD card reader or an NVMe device adds a p, so use ${USB}p1 there, for example /dev/mmcblk0p1.
Build the stick with FAT32 and a split install.wim
You need a GPT partition table, one FAT32 partition, every file from the ISO except install.wim, and then install.wim split into .swm parts under 4 GiB. Windows Setup reads split images natively, so nothing else on the stick changes. The split comes from wimlib, which every major distribution packages:
- Ubuntu and Debian:
wimtools - Fedora:
wimlib-utils - Arch Linux:
wimlib
On Ubuntu, install it along with rsync:
sudo apt install -y wimtools rsync
Wipe the old signatures and create the partition. parted marks a FAT32 partition on GPT as Microsoft basic data on its own, which is what Windows Setup expects to see:
sudo wipefs -a $USB
sudo parted -s $USB mklabel gpt mkpart WINUSB fat32 1MiB 100%
sudo parted -s $USB print
The msftdata flag confirms the partition type. We trimmed the output to the partition line, without the disk header above it:
Number Start End Size File system Name Flags
1 1049kB 17.2GB 17.2GB fat32 WINUSB msftdata
Format it FAT32 with a label you will recognise in the firmware boot menu, then mount it next to the ISO:
sudo mkfs.vfat -F 32 -n WIN11 ${USB}1
sudo mount ${USB}1 /mnt/usb
Copy everything except the big file. The -r flag is enough here, because FAT32 cannot store Linux owners or permissions anyway:
sudo rsync -r --exclude=sources/install.wim /mnt/iso/ /mnt/usb/
Now split install.wim straight onto the stick. The last argument is the maximum part size in MiB. We used 3800 rather than something closer to 4096 because wimlib cannot divide a single compressed resource between parts, so a part can come out slightly larger than the number you give it:
sudo wimlib-imagex split /mnt/iso/sources/install.wim /mnt/usb/sources/install.swm 3800
On the lab VM the split took 1 minute 26 seconds and produced two parts, both under the FAT32 limit:
Finished splitting "/mnt/iso/sources/install.wim"
-rwxr-xr-x 1 root root 3984357833 Oct 24 12:42 /mnt/usb/sources/install.swm
-rwxr-xr-x 1 root root 3332199199 Oct 24 12:42 /mnt/usb/sources/install2.swm
Flush the writes and unmount both before you pull the stick. On real USB flash, sync is where you wait, because Linux caches the copy in RAM and only now pushes it to the slow flash:
sync
sudo umount /mnt/usb /mnt/iso
lsblk -o NAME,SIZE,FSTYPE,LABEL,PARTLABEL $USB
The stick should show one vfat partition labelled WIN11:
NAME SIZE FSTYPE LABEL PARTLABEL
sda 16G
└─sda1 16G vfat WIN11 WINUSB
That stick boots through the ISO’s own efi/boot/bootx64.efi. We checked its signature with sbverify --list, and it is signed by Microsoft Windows Production PCA 2011, Microsoft’s own Windows certificate rather than the third-party one. That is the reason we put this method first. One caveat applies to PCs that already have Microsoft’s BlackLotus (CVE-2023-24932) revocations turned on, because those put PCA 2011 on the block list and refuse older media, so on such a PC you need a Windows ISO whose boot files are signed with the 2023 certificate. The stick is also UEFI only, since it has no legacy boot code.
Use WoeUSB-ng for a one-command stick
WoeUSB-ng is an alternative to the FAT32 method, not an extra step, and it erases the same $USB device, so don’t run it on the stick you just built. It does the job in one command, and getting it installed on current Ubuntu is the hard part. The project’s README says sudo pip3 install WoeUSB-ng, and this Ubuntu release refuses that because system Python is marked as externally managed. These are the first lines of the error:
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
A normal pipx install fails too, because the package’s setup script tries to write /usr/local/bin/woeusbgui as your user. What worked on the lab VM was the project’s apt dependencies plus a global pipx install with sudo, which puts the tool in its own virtual environment under /opt/pipx. The --global flag needs pipx 1.5 or newer, which the lab’s Ubuntu 26.04 has but Ubuntu 24.04’s packaged pipx doesn’t, so on 24.04 the FAT32 method is the simpler route:
sudo apt install -y git p7zip-full python3-pip python3-wxgtk4.0 grub2-common grub-pc-bin parted dosfstools ntfs-3g pipx
sudo pipx install --global --system-site-packages WoeUSB-ng
woeusb --version
The --system-site-packages flag lets it use Ubuntu’s packaged wxPython, so nothing gets compiled. The version check returned:
0.2.12
We only used the woeusb command line. The install also drops a woeusbgui launcher, which we did not test with this method. WoeUSB-ng also downloads its UEFI:NTFS boot image from the Rufus project on GitHub while it writes the stick, so keep the machine online. Point it at the ISO and the whole device:
sudo woeusb --device "$ISO" $USB
WoeUSB-ng finished in 2 minutes 13 seconds. The run made three decisions for you without asking:
- NTFS for the main partition, because of the 7.3 GB file
- a 1 MB FAT partition holding a UEFI:NTFS loader
- GRUB on the stick for legacy BIOS booting
The resulting layout on the stick:
NAME SIZE FSTYPE LABEL
sda 16G
├─sda1 16G ntfs NTFS
└─sda2 1M vfat RUFUS_BOOT
On our Secure Boot VM this stick also booted into Windows Setup, but the path is different from the FAT32 stick. The firmware runs the UEFI:NTFS loader from the small partition, and that loader is signed through Microsoft Corporation UEFI CA 2011, the third-party certificate, not the Windows one. PCs that ship with the third-party certificate disabled will not start it with Secure Boot on, and you would have to turn Secure Boot off or enable that certificate in your firmware. Microsoft is also replacing its 2011 certificates, which the Secure Boot certificate update guide explains. That extra dependency is why WoeUSB-ng is the second choice here, even though it is the quicker one to run.
Skip dd for Windows ISOs
Writing the ISO with dd finished without an error, which is what makes it a trap. The result is a UDF filesystem written across the whole stick, with no partition table at all:
/dev/sda: UUID="fc4100004d532055" LABEL="CENA_X64FREE_EN-US_DV9" BLOCK_SIZE="2048" TYPE="udf"
Our VM’s firmware still started it, treating the stick like a DVD and showing the prompt you would get from a disc. That alone tells you it is not a USB boot layout, and a physical PC’s firmware may not offer that route at all:

Windows Setup then loaded and stopped on the next screen. It did not find its installation files on the partitionless UDF stick and reported that as a missing driver, even though the disk sat on a standard SATA controller that Windows supports out of the box. Rewrite the stick with the FAT32 method and this screen goes away:

Nothing on a dd stick is worth keeping, so go back to the FAT32 steps above and start again at wipefs.
Boot the stick and install Windows
Plug the stick into the target PC and open its one-time boot menu, usually F12, F11, F8 or Esc depending on the vendor. Pick the entry that names your stick with a UEFI prefix. Leave Secure Boot on, because both working sticks above booted with it enabled, which we confirmed with mokutil --sb-state on the same VM. If you want to rehearse the install before touching real hardware, the same stick works in a VM, and the Windows 11 on KVM with virt-manager guide shows that setup. The first Setup screen asks for language and keyboard:

The first time through, our VM had no TPM and Setup refused to continue after the setup option page. The check lists only what failed, so a missing TPM shows up alone like this. Enable the firmware TPM, often labelled fTPM, PTT or Security Device, and boot the stick again. In a KVM guest you add a virtual TPM instead, which the TPM on KVM guide covers:

With a TPM added, Setup read the license from the split image and listed the disks. The stick shows up as a disk too, so pick the internal drive, not the partition labelled WIN11. Setup also printed “Windows 11 can’t be installed on this drive” under the list with the empty disk selected; Next stayed enabled, and the install went ahead when we clicked it:

The copy phase reads both .swm parts, and on the lab VM it was at 36% after 3 minutes and 76% after about 7:

Pull the stick when the PC restarts for the first time. We left it in, the firmware booted it again ahead of the internal disk, and Setup stopped with a confusing upgrade question:

The dialog itself says to remove the media and click Yes to continue. We powered off instead, removed the stick and started the VM again, which works too. It booted from the internal disk, carried on at “Installing 94%” and finished at the first screen of the out-of-box setup:

From here on, Windows no longer needs the stick. If you are installing next to an existing Linux system, the Fedora and Windows 11 dual boot guide covers the partitioning that comes before this step. Keep the FAT32 stick afterwards, because it doubles as a repair disk and you can refresh it for the next Windows release by deleting its files and repeating the copy and split steps.
Hi, I get
“The following packages have unmet dependencies:
woeusb : Depends: libwxgtk3.0-0v5 (>= 3.0.4+dfsg) but it is not installable
E: Unable to correct problems, you have held broken packages”
when trying sudo apt install woeusb on ubuntu 20.04
when trying mk-build-deps, the control file | package name is missing.
Could you please update the tutorial?
Hi,
Please try updated method.
Hey , thank you very much sir ! i tryed to follows the steps in the official page in github woeusb , but with my poor english …. Now everything work , thank again man 🙂
Thanks and welcome!
It’s not just an English level issue because the steps as you explain here are not mentioned anywhere in git. There’s some information about dependencies, but I think it’s outdated, but you got the job done here! Thanks again 🙂 .