The Problem
If you work in IT, you’ve probably got a drawer full of USB drives - one for Windows 11, one for Windows 10, one with a Linux installer, maybe one with recovery tools. It’s messy, wasteful, and you never have the right one when you need it.
Ventoy solves this by turning a single USB drive into a multi-boot Swiss army knife. Drop ISO files onto the drive, boot from it, and pick which one to run. No burning, no reformatting, no dedicated drives per OS.
The catch: Ventoy’s installer only runs on Linux. If your daily driver is a Mac, you’re on your own.
Here’s how to set it up entirely from macOS.
What You’ll Need
- A USB flash drive, 128GB or larger. Get one with decent sustained write speeds - cheap drives stall on large ISO writes. The SanDisk Extreme Go (SDCZ810) handles it well at ~70-80MB/s sustained.
- The Ventoy release tarball from GitHub.
- ISO files for whatever operating systems and tools you want.
The Partition Layout
We’re creating four partitions on a GPT disk:
| Partition | Name | Size | Format | Purpose |
|---|---|---|---|---|
| 1 | EFI | 210MB | FAT32 | UEFI bootloader (Ventoy’s GRUB + EFI files) |
| 2 | VENTOY | 100GB | exFAT | ISO storage - drop files here |
| 3 | VTOYEFI | 64MB | FAT16 | Ventoy boot partition (written from Ventoy’s disk image) |
| 4 | TOOLS | Remaining | FAT32 | Scripts, utilities, data transfer |
The TOOLS partition is useful beyond just booting. FAT32 is readable by everything - Windows, Linux, macOS, even a Raspberry Pi. I use it to carry deployment scripts, portable binaries, and transfer data between machines.
Step 1: Download and Extract Ventoy
# Find the latest release
curl -sf https://api.github.com/repos/ventoy/Ventoy/releases/latest | \
python3 -c "
import sys, json
r = json.load(sys.stdin)
print(r['tag_name'])
for a in r['assets']:
if 'linux' in a['name'].lower():
print(a['browser_download_url'])
"
# Download and extract (adjust version as needed)
curl -sSfL -o /tmp/ventoy.tar.gz \
https://github.com/ventoy/Ventoy/releases/download/v1.1.11/ventoy-1.1.11-linux.tar.gz
cd /tmp && tar xzf ventoy.tar.gz
Yes, we’re downloading the Linux release. We need the boot images and EFI files from it, not the installer script.
Step 2: Partition the Drive
Identify your USB drive:
diskutil list external
Verify the disk number carefully. Getting this wrong will destroy data on the wrong drive. In these examples I’ll use disk4 - replace it with yours.
diskutil partitionDisk disk4 GPT \
ExFAT VENTOY 100G \
"MS-DOS FAT16" VTOYEFI 64M \
"MS-DOS FAT32" TOOLS R
Step 3: Write the Ventoy Boot Code
This is where it gets interesting. Ventoy’s Ventoy2Disk.sh uses Linux-specific tools, so we do it manually with dd. Three writes to the raw disk, all requiring sudo.
Important: Virtualization software like Parallels Desktop, VMware Fusion, or VirtualBox will grab USB devices and block unmount operations. If you see “Unmount was dissented by PID…” errors, quit the virtualization app before proceeding. Alternatively, force unmount with diskutil unmountDisk force disk4.
Set your variables:
VENTOY_DIR=/tmp/ventoy-1.1.11
DISK=disk4
MBR boot code (446 bytes to sector 0)
diskutil unmountDisk $DISK
sudo dd if=$VENTOY_DIR/boot/boot.img of=/dev/$DISK bs=1 count=446
GRUB core image (starts at sector 34 for GPT)
diskutil unmountDisk $DISK
xzcat $VENTOY_DIR/boot/core.img.xz | \
sudo dd of=/dev/$DISK bs=512 seek=34 count=2014
GPT marker byte
This one is tricky. macOS requires block-aligned writes to raw devices, so you can’t write a single byte at offset 92. Instead, read the whole first sector, patch it, write it back:
diskutil unmountDisk $DISK
sudo dd if=/dev/$DISK of=/tmp/mbr.bin bs=512 count=1
sudo sh -c 'printf "\x22" | dd of=/tmp/mbr.bin bs=1 count=1 seek=92 conv=notrunc'
diskutil unmountDisk $DISK
sudo dd if=/tmp/mbr.bin of=/dev/$DISK bs=512 count=1
rm -f /tmp/mbr.bin
Write the Ventoy ESP image
This writes Ventoy’s pre-built FAT16 filesystem (containing all its GRUB configs and boot files) directly to the VTOYEFI partition:
diskutil unmountDisk $DISK
xzcat $VENTOY_DIR/ventoy/ventoy.disk.img.xz | \
sudo dd of=/dev/${DISK}s3 bs=512
The 64MB partition gives plenty of room for the ~32MB image. If you see an “end of device” warning, your partition is too small - increase it.
Step 4: Set Up the EFI System Partition
UEFI firmware boots from the EFI System Partition (the one macOS created at partition 1), not from our VTOYEFI partition. We need to copy Ventoy’s EFI bootloader there.
# Format the EFI partition
sudo newfs_msdos -v EFI -F 32 /dev/r${DISK}s1
sudo diskutil mount ${DISK}s1
# Mount VTOYEFI (contains files from the image we wrote)
diskutil mount ${DISK}s3
# Copy everything
cp -r /Volumes/VTOYEFI/EFI /Volumes/EFI/
cp -r /Volumes/VTOYEFI/grub /Volumes/EFI/
cp -r /Volumes/VTOYEFI/ventoy /Volumes/EFI/
cp -r /Volumes/VTOYEFI/tool /Volumes/EFI/
cp /Volumes/VTOYEFI/ENROLL_THIS_KEY_IN_MOKMANAGER.cer /Volumes/EFI/
Step 5: Create the Folder Structure
diskutil mount ${DISK}s2
diskutil mount ${DISK}s4
mkdir -p /Volumes/VENTOY/iso/windows
mkdir -p /Volumes/VENTOY/iso/linux
mkdir -p /Volumes/VENTOY/iso/rescue
mkdir -p /Volumes/TOOLS/scripts
mkdir -p /Volumes/TOOLS/binaries
mkdir -p /Volumes/TOOLS/data
Tell Ventoy to scan the iso/ subdirectory for bootable images:
mkdir -p /Volumes/VENTOY/ventoy
cat > /Volumes/VENTOY/ventoy/ventoy.json << 'EOF'
{
"control": [
{ "VTOY_DEFAULT_SEARCH_ROOT": "/iso" }
],
"theme": {
"display_mode": "CLI"
}
}
EOF
Step 6: Load Your ISOs
Drop ISO files into the appropriate folders:
cp ~/Downloads/Win11_x64.iso /Volumes/VENTOY/iso/windows/
cp ~/Downloads/ubuntu-24.04-desktop-amd64.iso /Volumes/VENTOY/iso/linux/
cp ~/Downloads/systemrescue-11.03-amd64.iso /Volumes/VENTOY/iso/rescue/
A Note on Slow USB Drives
If your drive has poor sustained write speeds (common with budget drives), large ISO copies may stall. The USB controller’s write cache fills up and the kernel’s write call blocks indefinitely.
The fix is chunked copying with sync between each piece, giving the controller time to flush:
chunked_copy() {
local src="$1" dst="$2"
local size=$(stat -f%z "$src")
local chunk=$((512 * 1024 * 1024))
local offset=0
echo "Copying $(basename "$src") ($((size / 1024 / 1024))MB)..."
while [ $offset -lt $size ]; do
local remaining=$((size - offset))
[ $remaining -lt $chunk ] && chunk=$remaining
printf "\r %dMB / %dMB" $((offset / 1024 / 1024)) $((size / 1024 / 1024))
dd if="$src" of="$dst" bs=1m \
count=$((chunk / 1024 / 1024)) \
skip=$((offset / 1024 / 1024)) \
seek=$((offset / 1024 / 1024)) \
conv=notrunc 2>/dev/null
sync
offset=$((offset + chunk))
done
printf "\r Done: %dMB\n" $((size / 1024 / 1024))
}
chunked_copy ~/Downloads/Win11.iso /Volumes/VENTOY/iso/windows/Win11.iso
If you’re buying a drive specifically for this, save yourself the headache and get one rated for sustained writes. The SanDisk Extreme Go handles 6GB+ files without breaking a sweat.
Booting
- Plug the USB into the target machine.
- Enter the boot menu (usually F12, F2, or Del at POST).
- Select the USB drive.
- Ventoy’s menu appears, listing every ISO on the drive.
- Pick one. It boots.
If the machine has Secure Boot enabled, you’ll see a MOK enrollment prompt on first boot. Select “Enroll key from disk” and choose ENROLL_THIS_KEY_IN_MOKMANAGER.cer. After that, Ventoy boots normally.
Recommended ISOs
These are the ones I keep on mine:
- Windows 11 x64 and ARM64 - covers both Intel/AMD and ARM machines
- Windows 10 x64 - for older hardware or compatibility
- Ubuntu or Debian - general-purpose Linux
- SystemRescue - filesystem repair, partition tools, chntpw for Windows password resets
- Hiren’s Boot CD PE - Windows PE environment with recovery utilities
- Memtest86+ - memory diagnostics (tiny ISO, always worth having)
Adding a new one later is just dragging an ISO file onto the drive. No reformatting, no re-burning, no dedicated USB sticks. One drive to rule them all.
