Four tools cover almost every way to create a bootable USB on macOS and Linux. The right one for you depends on how often you flash sticks and how much protection you want from picking the wrong disk. The dd command is already on both systems and writes a byte-for-byte copy. balenaEtcher wraps the same job in a GUI that keeps non-removable drives out of its default list and checks the write. Ventoy turns one stick into a menu of ISOs, and Raspberry Pi Imager handles any image file despite its name.
We’d use Etcher for a one-off stick, dd when you’re already in a terminal and know your device names, and Ventoy if you carry several installers around. The Linux steps were re-run on Ubuntu 26.04 in October 2026, writing a real distro ISO to a USB-attached disk and booting the result on a UEFI (OVMF) virtual machine. The macOS commands follow the macOS man pages and each tool’s own docs, but were not re-tested on a Mac for this update.
Which bootable USB tool to use
Pick by how you work, not by which tool you heard of last. The table sums up where each one runs and what we checked on Ubuntu 26.04 for this update:
| Tool | macOS | Linux | Best for | Tested on Ubuntu 26.04 |
|---|---|---|---|---|
dd | Built in | Built in | Fast one-off writes from a terminal | Yes, three writes and a boot test |
| balenaEtcher | Yes | Yes (.deb, .rpm, zip) | Beginners who want a guarded GUI | Yes, 2.1.7 .deb |
| Ventoy | No | Yes | Many ISOs on one stick | Yes, 1.1.18 |
| Raspberry Pi Imager | Yes | Yes | Images for SD cards and sticks, with a CLI | Yes, archive package CLI write |
Whichever tool you choose, your stick has to hold the whole image. Desktop ISOs commonly run past 3 GB (the CachyOS ISO we used is 3.19 GB), so 8 GB is the practical minimum and 16 GB leaves room for bigger images. A slow or worn-out stick is the most common reason a write crawls or a boot fails halfway, and our USB flash drive recommendations list the drives we’d pick and the specs to look at.
1. dd (Linux and macOS)
dd copies the ISO to the stick as raw bytes, which is exactly what modern hybrid ISOs expect. It needs nothing installed and produces a perfect copy. The trade-off is that it has no guard rails at all, so it will overwrite your system disk just as happily if you give it the wrong name, which is why every write below starts with a device check.
Write the stick on Linux
Unplug any other USB drives first, then plug the stick in and list the block devices with the removable and transport columns. A stick shows TRAN usb, but so does an external USB hard drive or SSD, and many fast sticks report RM 0, so match the SIZE and MODEL to the stick in your hand rather than trusting one column:
lsblk -o NAME,SIZE,RM,TRAN,MODEL
On our Ubuntu 26.04 test box the stick was sda and the system disk was a virtio device. The model reads QEMU HARDDISK because our stick was a disk attached through a virtual USB controller; a real one shows its brand. On a laptop with a SATA SSD, sda is usually the system disk, which is exactly why you never copy a device name from a guide:
NAME SIZE RM TRAN MODEL
sda 8G 1 usb QEMU HARDDISK
sr0 4M 1 ata QEMU DVD-ROM
vda 40G 0 virtio
├─vda1 38.9G 0 virtio
├─vda13 1023M 0 virtio
├─vda14 4M 0 virtio
└─vda15 106M 0 virtio
Put the device and the ISO path in two variables, so the dangerous commands cannot drift to a different disk halfway through. Replace sdX with the NAME of your stick from lsblk, and the ISO path with your file. The Ventoy and Raspberry Pi Imager sections below reuse both variables, so set them even if you skip dd:
export USB_DEV=/dev/sdX
export ISO=~/Downloads/cachyos-desktop-linux-260809.iso
Re-check the variable against the device before anything destructive, then unmount every partition on the stick. Desktops mount a stick the moment it’s plugged in, and writing to a mounted device can leave a broken image. “not mounted” messages are harmless, but “target is busy” means a file manager or terminal still has the stick open, so close it and run umount again. The dd line only runs if the device really is on the USB bus. If the guard fails it prints nothing and writes nothing, so when the line returns at once with no progress output, check USB_DEV again:
lsblk -o NAME,SIZE,RM,TRAN,MODEL,MOUNTPOINTS "${USB_DEV}"
sudo umount "${USB_DEV}"?*
[ "$(lsblk -dno TRAN "${USB_DEV}")" = usb ] && sudo dd if="${ISO}" of="${USB_DEV}" bs=4M status=progress conv=fsync
Do not drop conv=fsync. Without it, dd can return while data still sits in the kernel’s write cache, and pulling the stick then leaves a partial image. After the write, flush the device’s cached pages so the readback comes from the stick and not from RAM, then compare the stick’s hash with the checksum file the ISO came with. CachyOS ships a .sha256 file next to each ISO; for Ubuntu, Debian or Fedora, grep your ISO’s name in the release’s SHA256SUMS or CHECKSUM file instead. The two hashes must match before you eject:
sudo blockdev --flushbufs "${USB_DEV}"
sudo head -c "$(stat -c %s "${ISO}")" "${USB_DEV}" | sha256sum
cat "${ISO}.sha256"
sudo eject "${USB_DEV}"
Here’s that exact sequence on our test box, with USB_DEV set to /dev/sda. The progress line passed 3.1 GB at 8 seconds, but dd only returned at 18.1 seconds, once the flush had put everything on the stick, and both hashes match:

Our three dd runs took 13.0, 18.1 and 26.8 seconds for the same 3.2 GB ISO, but that stick was a virtual disk on fast storage. A real USB 3 stick is limited by its own write speed, so a few minutes is normal and much longer on a cheap or USB 2 stick. If the hashes differ, write the stick again before you suspect the ISO. After eject the device reads as 0B, so unplug and replug the stick before you use another tool on it, and run lsblk again, because the name can change.
Write the stick on macOS
macOS uses diskutil instead of lsblk, and its disk names look like disk4. List the disks and look for an (external, physical) entry whose size matches your stick:
diskutil list
Set the disk identifier you found and check it before you touch it. disk4 is only our example and could just as well be a backup drive or a mounted disk image on your Mac. In the info output, confirm Device Location: External and a size that matches your stick:
DISK=disk4
diskutil info "/dev/${DISK}"
Then unmount the whole disk. Use unmountDisk rather than Eject in Finder, because Eject disconnects the device and dd then has nothing to write to:
diskutil unmountDisk "/dev/${DISK}"
Write to the raw device, /dev/rdiskN, not /dev/diskN. The r version skips the buffer cache, which makes a large sequential write like this faster. Note the lowercase 4m: the macOS dd documents its size suffixes in lower case, unlike GNU dd on Linux:
sudo dd if=~/Downloads/cachyos-desktop-linux-260809.iso of="/dev/r${DISK}" bs=4m status=progress
diskutil eject "/dev/${DISK}"
The current macOS dd man page documents status=progress; on an older release that rejects it, drop the option and press Ctrl+T during the write to print progress. These macOS commands were not re-run on a Mac for this update. If dd reports “Resource busy”, the disk is mounted again, so run diskutil unmountDisk once more and retry.
2. balenaEtcher (macOS and Linux)
Etcher is the safest choice for anyone who doesn’t write sticks every week. It shows only removable drives by default, keeps the rest behind a “Show hidden” toggle, and reads the stick back after writing to check it. On macOS it installs with Homebrew (brew install --cask balenaetcher, which we did not run here). On Linux, the Etcher releases page ships a .deb, an .rpm and a zip, and no longer an AppImage.
On Ubuntu or Debian, fetch the latest .deb together with its checksum file, check it, then let apt pull in the dependencies:
ETCHER_VER=$(curl -sL https://api.github.com/repos/balena-io/etcher/releases/latest | grep tag_name | head -1 | sed 's/.*"v\([^"]*\)".*/\1/')
echo "${ETCHER_VER}"
wget "https://github.com/balena-io/etcher/releases/download/v${ETCHER_VER}/balena-etcher_${ETCHER_VER}_amd64.deb"
wget "https://github.com/balena-io/etcher/releases/download/v${ETCHER_VER}/SHA256SUMS.Linux.x64.txt"
grep "_amd64.deb" SHA256SUMS.Linux.x64.txt | sha256sum -c -
sudo apt-get update
sudo apt-get install -y "./balena-etcher_${ETCHER_VER}_amd64.deb"
The version check printed 2.1.7 and the checksum line ended in OK. Fedora and RHEL users can grab the .rpm from the same release and install it with sudo dnf install ./balena-etcher-${ETCHER_VER}-1.x86_64.rpm; we did not test the .rpm. Launch Etcher from the app menu or with balena-etcher, click Flash from file and pick the ISO:

Etcher picked our only removable drive on its own. You should still open Change anyway and check the size and device path. Our stick still carried the Ventoy layout from an earlier test, hence its label. The list keeps the other drives behind “Show 1 hidden”, which is the protection dd doesn’t give you:

Click Flash!. Etcher writes the image first, then switches to a validating pass that reads it back. The screenshot shows the write stage at 54%:

The whole job, write plus validation, finished in under a minute on our virtual stick at an effective 349.7 MB/s, and the stick’s hash matched the ISO afterwards. Etcher needs root to write to a disk; we started it as root on a headless test VM, so the password prompt you get on a normal desktop was not part of our run:

Skip Etcher if you want something small. The .deb is 124 MB because it bundles Electron, and on a minimal Ubuntu server install apt pulled in a full graphical stack to satisfy it.
3. Ventoy (Linux)
Ventoy is the tool to pick when one stick should boot several things. Instead of writing an ISO, you install Ventoy’s bootloader on the stick once, then copy ISO files onto it like normal files and pick one from a menu at boot. The Ventoy docs list Windows and Linux as the only systems that run the installer, so on a Mac you’ll need one of the other tools.
Every command in this section uses the USB_DEV and ISO variables from the dd section, so set those first if you jumped straight here. Download the latest Linux release and its checksum list, check the tarball and unpack it:
VENTOY_VER=$(curl -sL https://api.github.com/repos/ventoy/Ventoy/releases/latest | grep tag_name | head -1 | sed 's/.*"v\([^"]*\)".*/\1/')
echo "Latest Ventoy: ${VENTOY_VER}"
wget "https://github.com/ventoy/Ventoy/releases/download/v${VENTOY_VER}/ventoy-${VENTOY_VER}-linux.tar.gz"
wget "https://github.com/ventoy/Ventoy/releases/download/v${VENTOY_VER}/sha256.txt"
grep linux.tar.gz sha256.txt | sha256sum -c -
tar xzf "ventoy-${VENTOY_VER}-linux.tar.gz"
Install Ventoy on the stick. This wipes it, so re-check USB_DEV first, then answer y to both confirmation prompts. Ventoy unmounts the stick’s partitions itself before it writes:
lsblk -o NAME,SIZE,RM,TRAN,MODEL,MOUNTPOINTS "${USB_DEV}"
cd "ventoy-${VENTOY_VER}"
sudo sh Ventoy2Disk.sh -i "${USB_DEV}"
Our test box printed the whole run below, both prompts included. The “mknod: File exists” line is harmless, and the install still finished:

The install leaves the stick split in two, and only one half is yours to use:
- Ventoy (exFAT, the rest of the stick): your ISOs go here, copied like any other file.
- VTOYEFI (32 MB FAT): Ventoy’s own boot files. Leave it alone.
- Partition table: MBR by default. Add
-gto the install command if you need GPT.
Once udev has caught up, lsblk shows both partitions with their labels:
lsblk -o NAME,SIZE,FSTYPE,LABEL "${USB_DEV}"
Ours listed the 8 GB exFAT partition and the 32 MB VTOYEFI one:
NAME SIZE FSTYPE LABEL
sda 8G
├─sda1 8G exfat Ventoy
└─sda2 32M vfat VTOYEFI
Mount the data partition, copy the ISOs on and unmount it before you pull the stick:
sudo mkdir -p /mnt/ventoy
sudo mount "${USB_DEV}1" /mnt/ventoy
sudo cp "${ISO}" /mnt/ventoy/
sudo umount /mnt/ventoy
The copy took 12.7 seconds, but umount needed another 6.3 seconds to flush the data, so wait for the prompt to return. Pulling the stick early can leave a truncated ISO on it. With Secure Boot on, a fresh Ventoy stick stops at “Verification failed: (0x1A) Security Violation” until you enroll Ventoy’s key once through MokManager. The full Ventoy guide walks through that key enrolment, updates that keep your ISOs, VentoyWeb, legacy BIOS boot and ISOs that will not boot. We installed and loaded the stick here but booted the dd-written stick, not the Ventoy one, in this round of testing.
4. Raspberry Pi Imager (macOS and Linux)
Raspberry Pi Imager is built for SD cards, but its Use custom option writes any local .iso or .img to any drive, and it verifies the write afterwards. Its command-line mode earns it a place in this list, because you can write and verify a stick in one command with no GUI. Ubuntu 26.04’s archive carries an older 1.8.5 build, while the upstream releases are on 2.0.x with .deb packages and AppImages. We tested the archive package:
sudo apt install -y rpi-imager
In the 1.8.5 GUI the flow is CHOOSE OS, then Use custom and your ISO, then CHOOSE STORAGE, then NEXT; answer No to the OS customisation question and Yes to the erase warning. We only opened the GUI and wrote with the CLI, so the GUI write itself is untested here. The main window from the Ubuntu package looks like this:

The CLI does the write in one line, using the USB_DEV and ISO variables from the dd section. It erases the target without asking, so the same re-check and USB guard go in front of it. On a desktop you can drop QT_QPA_PLATFORM=offscreen, which we only needed because our test box had no display:
lsblk -o NAME,SIZE,RM,TRAN,MODEL,MOUNTPOINTS "${USB_DEV}"
[ "$(lsblk -dno TRAN "${USB_DEV}")" = usb ] && sudo QT_QPA_PLATFORM=offscreen rpi-imager --cli "${ISO}" "${USB_DEV}"
Imager unmounted the drive, zeroed its first and last megabyte, then wrote and verified the 3.2 GB ISO in 27 seconds on our latest run (31.5 on the first). The end of its output:
Writing: [-------------------->] 100 %
Verifying: [-------------------->] 100 %
Write successful.
Imager also ejects the stick when it’s done, so a readback right after fails with “No medium found” until you replug it. That’s expected, not a failed write. On macOS, the Homebrew cask is brew install --cask raspberry-pi-imager, which we did not test.
Check that the stick boots
A stick that writes cleanly can still fail to boot, so test it on the machine you plan to install on. We moved the dd-written CachyOS stick to a UEFI (OVMF) virtual machine, attached as a plain disk, and it reached the live ISO’s GRUB menu, then the live desktop:

That boot needed Secure Boot turned off. With Secure Boot on, the OVMF firmware refused the same stick with “Access Denied”; the message varies by firmware, and real machines word it differently. The CachyOS wiki says to turn Secure Boot off for the install. Other distros differ, so check your distro’s install docs before you change firmware settings. Pick the stick from the firmware’s one-time boot menu instead of changing the boot order permanently. Once it boots, these walkthroughs pick up from the first installer screen:
- Debian: the Debian 13 installation walkthrough covers both the graphical and the text installer.
- Linux Mint: installing Linux Mint step by step is the friendliest first desktop install.
- CachyOS: our CachyOS install guide uses the same stick we wrote here.
Windows ISOs are the exception to everything above. They are not hybrid images, so dd and Etcher don’t give you a working Windows installer stick. Ventoy usually boots them, but in our testing it failed to start the 26H2 ISO on our OVMF test VM. The Windows 11 USB guide covers Rufus, WoeUSB-ng and the FAT32 plus wimlib route, along with what we saw from Ventoy.
Where each tool falls short
None of these tools is perfect, and the gaps are what should decide it for you:
- dd: no safety net. One wrong letter in the device name wipes a disk, and it never checks the write unless you read it back yourself.
- balenaEtcher: heavy for what it does, a 124 MB Electron app, and it can’t do multi-ISO sticks.
- Ventoy: no macOS installer, and it puts its own boot menu between the firmware and the ISO, so test unusual images before you rely on the stick.
- Raspberry Pi Imager: the Ubuntu archive build lags well behind upstream, and the GUI is designed around Raspberry Pi images.
For most people the answer is Etcher for the first stick and Ventoy once you’re carrying three or more installers. Keep dd for the times you’re already in a terminal, with lsblk open next to it.