Hetzner server to VMDK, VHDX or VDI: the qemu-img conversion guide
Convert a raw Hetzner disk image to VMDK, VHDX or VDI with qemu-img, plus the boot fixes each hypervisor needs. Commands for ESXi, Hyper-V and VirtualBox.
updated 10 minute read by Dominik Geimer
What you start from
The starting point for everything below is a raw image of the server's disk, compressed with zstd: a file such as server.img.zst. Hetzner has no download for snapshots, so the image comes from reading the disk block by block from a rescue system, which is covered in Can you download a Hetzner Cloud snapshot?.
Raw means exactly that: the partition table, the bootloader and every partition, byte for byte, with no container around them. Proxmox, libvirt and QEMU read such a file as it is. VMware, Hyper-V and VirtualBox each want the same bytes wrapped in their own container format, and that wrapping is all qemu-img convert does. Nothing inside the disk changes during a conversion. That is worth remembering when something later refuses to boot, because the cause is then almost never the conversion.
Decompress the file first
The decompressed file is as large as the original disk, so check free space before you start. On Windows the target drive has to be NTFS or exFAT; FAT32 cannot hold a single file above 4 GB.
Linux
# Debian, Ubuntu: apt install zstd Fedora, RHEL: dnf install zstd Arch: pacman -S zstd
zstd -d server.img.zst -o server.raw
No flags are needed. zstd writes long runs of zeros as holes, so the file usually occupies far less space on disk than ls -l reports.
macOS
brew install zstd
zstd -d server.img.zst -o server.raw
macOS ships no zstd and Archive Utility does not open .zst. Keka opens it if you prefer a window to a terminal; The Unarchiver does not read zstd.
Windows
Right-click server.img.zst, then 7-Zip, then Extract here. 7-Zip has unpacked .zst since version 24.01; if the entry is missing, update it. Windows Explorer opens .tar.zst but not a bare .zst file. The file comes out as server.img, because zstd stores no file name and 7-Zip only drops the .zst; rename it to server.raw so the commands below match.
# or from a terminal - the & in front is what makes PowerShell run a quoted path
winget install --id 7zip.7zip -e
& "C:\Program Files\7-Zip\7z.exe" x server.img.zst
Rename-Item server.img server.raw
Install qemu-img
qemu-img ships with QEMU and does every conversion in this guide except the VirtualBox one, which VirtualBox handles itself.
Linux
# Debian, Ubuntu: apt install qemu-utils Fedora: dnf install qemu-img Arch: pacman -S qemu-img
qemu-img info server.raw
On Debian and Ubuntu the package is qemu-utils; the binary inside it is qemu-img.
macOS
brew install qemu
qemu-img info server.raw
The Homebrew formula installs all of QEMU, qemu-img included.
Windows
winget install --id SoftwareFreedomConservancy.QEMU -e
& "C:\Program Files\qemu\qemu-img.exe" info server.raw
The installer does not add QEMU to your PATH, so call qemu-img.exe by its full path with the & call operator in front, as above; without it PowerShell prints the quoted path instead of running it.
qemu-img info on the raw file should report file format: raw and a virtual size equal to the server's disk. If it reports anything else, the decompression did not finish.
The conversion matrix
| Target | Command | Note |
|---|---|---|
| VMware ESXi | qemu-img convert -p -f raw -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized server.raw server-stream.vmdk |
Intermediate file; ESXi clones it with vmkfstools |
| VMware Workstation, Fusion | qemu-img convert -p -f raw -O vmdk server.raw web-01.vmdk |
Plain VMDK, used directly |
| Hyper-V | qemu-img convert -p -f raw -O vhdx -o subformat=dynamic server.raw C:\VMs\web-01.vhdx |
Dynamic VHDX, Generation 1 or 2 |
| VirtualBox | VBoxManage convertfromraw server.raw web-01.vdi --format VDI |
No qemu-img needed |
| Proxmox, libvirt, QEMU | none | Raw is read as it is; qcow2 is optional |
Three flags do the work. -f raw tells qemu-img what the input is; a raw file has no header to detect, so leave it in. -O names the output format and -o passes the format's own options, which the QEMU disk image documentation lists per format: subformat for VMDK (monolithicSparse by default, streamOptimized among the alternatives) and for VHDX (dynamic or fixed), adapter_type for VMDK. -p prints progress. The complete option reference is the qemu-img manual.
VMware ESXi
ESXi does not power on the VMDK that qemu-img writes by default. The error is "Unsupported and/or invalid disk type 7", and Broadcom's knowledge base article explains why: the hosted products (Workstation, Fusion, Player) and ESXi store virtual disks in different formats, and a hosted disk has to be imported with vmkfstools -i before ESXi can use it. So convert to the stream-optimized subformat, upload it to a datastore, and let ESXi clone it into a native thin disk. The second step is not optional.
# on your computer
qemu-img convert -p -f raw -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized \
server.raw server-stream.vmdk
scp server-stream.vmdk root@esxi:/vmfs/volumes/datastore1/tmp/
# on the ESXi host, over SSH
vmkfstools -i /vmfs/volumes/datastore1/tmp/server-stream.vmdk -d thin \
/vmfs/volumes/datastore1/web-01/web-01.vmdk
Then in the Host Client: New Virtual Machine, Custom, Guest OS family Linux, remove the disk it offers, Add hard disk, Existing hard disk, web-01/web-01.vmdk. LSI Logic SAS or VMware Paravirtual both work with stock Debian and Ubuntu.
Set the firmware before the first power-on: VM Options, Boot Options, Firmware, EFI or BIOS, matching what the disk was built for. The Secure Boot checkbox only appears with EFI; leave it off unless the image is a stock signed distribution. Legacy BIOS guests are still fully supported on vSphere 8, so a BIOS disk does not need converting to UEFI. The step-by-step version is at /docs#restore-esxi.
VMware Workstation and Fusion
Workstation Pro on Windows and Linux, and Fusion on an Intel Mac, take the plain VMDK directly.
qemu-img convert -p -f raw -O vmdk server.raw web-01.vmdk
File, New Virtual Machine, Custom, "I will install the operating system later", Linux, name it, CPU, memory, network, Use an existing virtual disk, browse to web-01.vmdk, Finish. The firmware is under VM, Settings, Options, Advanced, Firmware type, UEFI or BIOS, while the machine is powered off. In the .vmx file that is the line firmware = "efi".
On an Apple Silicon Mac this route is closed. Broadcom states that only Arm guests run in Fusion on Apple silicon, and VirtualBox on macOS/Arm virtualizes Arm guests only as well. An x86 Hetzner image will not start in either, whatever you set. UTM in its Emulate mode boots the raw file, slowly, which is enough to confirm the copy is good; to actually run an x86 server, put it on a Linux, Proxmox or Windows host.
Hyper-V
Hyper-V's generation is its firmware setting. Microsoft's generation guide lays it out: Generation 1 has a legacy BIOS and boots from an IDE disk, Generation 2 has UEFI firmware and boots from a SCSI VHDX, and "you can't change a virtual machine's generation once it's created". Convert to VHDX, then create the generation the disk needs. PowerShell as administrator:
& "C:\Program Files\qemu\qemu-img.exe" convert -p -f raw -O vhdx -o subformat=dynamic server.raw C:\VMs\web-01.vhdx
# qemu-img writes the VHDX as a sparse file, and Hyper-V refuses to open one (error 0xC03A001A)
fsutil sparse setflag C:\VMs\web-01.vhdx 0
# legacy BIOS image
New-VM -Name web-01 -Generation 1 -MemoryStartupBytes 4GB -VHDPath C:\VMs\web-01.vhdx -SwitchName "Default Switch"
# UEFI image
New-VM -Name web-01 -Generation 2 -MemoryStartupBytes 4GB -VHDPath C:\VMs\web-01.vhdx -SwitchName "Default Switch"
Set-VMFirmware -VMName web-01 -EnableSecureBoot Off
Start-VM web-01
Generation 2 turns Secure Boot on with a template that trusts Windows only, and a Linux disk then stops in the firmware with no message and 0 % CPU. Microsoft documents three Secure Boot templates and names "Microsoft UEFI Certificate Authority" as the one for Linux, but an Ubuntu image restored on Windows 11 on 8 September 2026 did not boot with it either. Switching Secure Boot off is what worked, which is also the fallback in Microsoft's Ubuntu on Hyper-V notes. Try the template afterwards if you want Secure Boot back.
In Hyper-V Manager the same choice sits on the "Specify Generation" page of the wizard, and "Use an existing virtual hard disk" on the disk page. Generation 1 accepts VHDX as well as VHD, so there is no reason to produce the older format. The full walkthrough is at /docs#restore-hyperv.
VirtualBox
VirtualBox converts raw images itself with VBoxManage convertfromraw, which writes VDI, VMDK or VHD. VBoxManage is not on the PATH on Windows or macOS, so call it by its full path: "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" or /Applications/VirtualBox.app/Contents/MacOS/VBoxManage.
VBoxManage convertfromraw server.raw web-01.vdi --format VDI
VBoxManage createvm --name web-01 --ostype Ubuntu_64 --register
VBoxManage modifyvm web-01 --memory 4096 --cpus 2 --nic1 nat
VBoxManage modifyvm web-01 --firmware efi # UEFI image only; BIOS is the default
VBoxManage storagectl web-01 --name SATA --add sata --controller IntelAhci
VBoxManage storageattach web-01 --storagectl SATA --port 0 --device 0 --type hdd --medium web-01.vdi
VBoxManage startvm web-01
In the window: New, Expert mode, "Use an Existing Virtual Hard Disk File". The firmware switch is Settings, System, Motherboard, "Enable EFI (special OSes only)". If you would rather stay with qemu-img, -O vdi produces a file VirtualBox accepts too; the result is the same. More at /docs#restore-virtualbox.
Sparse files and disk space
A server disk is mostly zeros. zstd writes zero runs as holes, so server.raw occupies far less than its apparent size; du -h server.raw shows the real figure. If you copy the raw file to another machine, use cp --sparse=always or rsync -S so the holes survive the trip; otherwise the copy inflates to the full disk size. qemu-img convert detects runs of zeros itself, 4 KiB at a time by default and adjustable with -S according to the manual, and leaves them out of the output. The default VMDK, dynamic VHDX and VDI formats only store blocks that hold data, so the converted file ends up roughly the size of the data on the disk rather than the size of the disk.
After the conversion: the first boot
Two things go wrong on first boot, and neither is caused by the conversion. The first is firmware. A machine set to UEFI will not boot a legacy-BIOS disk, and the reverse is just as true; the failure is a blank screen, a firmware shell or a boot loop, which looks exactly like a corrupt image. A stock x86 CX23 created from a current image boots through UEFI, but Hetzner does not use the same firmware for every image, so check the disk before you choose: fdisk -l server.raw on Linux lists a partition of type "EFI System" if the disk is UEFI and none if it is BIOS. The table at /docs#restore-firmware maps that answer onto each setting above, and /docs#restore-prepare has the equivalent check for macOS and Windows.
The second is the network. The machine boots and cannot be reached, because it still carries the fixed address Hetzner assigned, a gateway of 172.31.1.1, and a network card named eth0, none of which exist on the new host. Open a console, not SSH, find the new interface name with ip -br link, and switch the configuration to DHCP; then disable cloud-init, which otherwise waits for a metadata service that is not there, and remove hc-utils on Debian-based images. The commands for Ubuntu, Debian and the Red Hat family are at /docs#restore-firstboot.
Know the firmware before you create the machine
The one step with no forgiving failure mode is the firmware choice, and it has to be made before the machine is created on Hyper-V and before the first power-on everywhere else. If the image came from hetshield, the download page already states UEFI or legacy BIOS, read off the partition table during the export, so that decision is settled before the file reaches your disk. Otherwise run fdisk -l once before you pick a hypervisor setting.