Documentation
Exactly what happens to your server
An export touches somebody's production machine, so nothing here is hidden. This page describes every step, every resource we create in your Hetzner account, and every one we delete again.
The API token
A Hetzner API token is scoped to one project. Create one in the Hetzner Cloud console under Security → API tokens, and paste it into the connect screen. Hetzner shows the token once, and it only reaches the project it was created in — create it in the project that holds the server. We call the API once, right there, to confirm it works before we store anything.
Why it needs write access
Hetzner offers exactly two permission levels: Read, and Read & Write. Making a copy of a disk is a write operation, and so is creating the temporary machine that reads it. There is no narrower option we could ask for — if there were, we would use it.
|
What we call
|
Why
|
|---|---|
| GET /servers | To show you your machines and their disk sizes |
| POST /servers/{id}/actions/create_image | To freeze the copy of the disk |
| POST /servers | To create the temporary machine from that copy |
| POST /servers/{id}/actions/enable_rescue | To boot it into a maintenance system instead of your software |
| POST /servers/{id}/actions/poweron | To switch the temporary machine on once the rescue system is armed |
| GET /server_types, GET /locations | To find the cheapest machine type that can hold your disk |
| GET /actions/{id} | To wait for each of those steps to finish |
| GET /images | To count your snapshots before you pay, and to find copies we failed to delete |
| DELETE /servers/{id}, DELETE /images/{id} | To remove the temporary machine and the disk copy again when the run ends |
We never call anything else. In particular we never delete a server we did not create ourselves, never touch your firewalls, networks or load balancers, and never write to the machine you are exporting.
How it is stored, and how to take it back
The token is encrypted in our database and never appears in a log, an email or a page. Press Disconnect under Hetzner access and the row is deleted. You can also revoke the token in the Hetzner console at any time — the next export simply fails, and nothing else changes.
What happens during an export
Six steps. Your own server is only involved in the first one, and only as the subject of a copy.
-
1
We freeze a copy of the disk
Hetzner takes a point-in-time image of the running machine. Your server keeps serving traffic; it is not paused, restarted or logged into. The image is consistent the way a disk is after a power cut, which is what every snapshot of a running system is: a database that is writing hard at that moment will do its usual crash recovery on first boot. If that worries you, pause writes for the minute the copy takes.
-
2
We pick a temporary machine
The copy needs somewhere to be read. We look for the cheapest available server type with the same processor architecture and a disk at least as large as yours — never your own type, because paying for your CPU and memory again would be pointless.
-
3
We create it, switched off
The machine is built from your disk copy with start_after_create set to false. That matters: your operating system never boots a second time, so no service starts twice, no cron job fires, and nothing claims your IP address. Hetzner emails you whenever a server is created in your project, so this is the first of two messages you get per export, about a server whose name starts with hetshield-.
-
4
It boots a maintenance system instead
We arm Hetzner's rescue system while the machine is still off, then switch it on. The first and only thing that runs is a small Linux that lives in memory. Hetzner emails you its one-time password, which is the second message per export: the rescue system on that same hetshield- server. Both messages are Hetzner doing its job, not somebody breaking in.
-
5
We read the disk and send it away
From that maintenance system we read the disk from beginning to end, compress it on the fly, and stream it straight to storage. Nothing is written to the machine and no copy is buffered anywhere in between.
-
6
We delete everything we made
The temporary machine and the disk copy are removed, whether the run succeeded or failed. Cleanup happens even when something goes wrong halfway, because a forgotten machine would be billed to you by the hour. The export page shows you what was left behind, if anything ever is.
Longer write-up, with the two manual routes and what each costs in downtime: Can you download a Hetzner Cloud snapshot?
What it costs you at Hetzner
Two things appear on your Hetzner invoice, both for hours rather than months: the temporary machine for every started hour it runs, and the disk copy for the fraction of a month it exists. On a typical export both together come to a few cents. We do not mark that up and we never see it — it is billed to you directly by Hetzner.
What the file contains
A raw image of the whole disk, compressed with zstd. Partition table, bootloader, every partition, your software and your data, exactly as they were the moment you pressed Export. We read blocks, not files, so it makes no difference which distribution or filesystem you run.
Attached volumes are not in it
Hetzner deliberately leaves volumes out of the copy it makes of a server, and a volume can only be attached to one machine at a time. No agentless export can contain them — not ours, not anybody's. We list which of your servers have one before you pay, so the surprise never lands at restore time.
Longer write-up, with how to find a volume from the API and back it up separately: Hetzner snapshots do not include volumes
Restoring it
What you downloaded is a raw image of the whole disk — partition table, bootloader, every byte. Restoring it means three things: get the file ready on your computer, create a virtual machine whose firmware matches the disk, and give the machine a network when it wakes up somewhere new. The second step is where hypervisors differ; the third is where nearly everybody stumbles once.
- 1 Convert the file Run hetshield, sign in, pick the export: it downloads the file and writes the disk your hypervisor wants. The manual route is there too.
- 2 Match the firmware Create the machine as UEFI or BIOS, exactly as your download page says.
- 3 First boot Give it an address on your network, and switch off what only made sense at Hetzner.
Convert it with the hetshield tool
The hetshield tool is one file, no installer, for Linux, macOS and Windows; pick your system below, or take the same build from your export page. Run it and it asks three things: your hetshield sign-in (once per computer), which export, and what to do with it — convert it for a hypervisor, or look inside it and copy files out. The export is downloaded once and kept next to the tool as a raw disk image, so both keep working after the download link has expired. This is the way to do it; the manual route in the next section exists so that the file is never tied to our tool.
The computer you are restoring on
The guess puts every Mac on Apple Silicon, because a browser cannot tell; an Intel Mac takes the "macOS, Intel" build.
Checksums for every build: SHA256SUMS — compare with sha256sum, shasum -a 256 or Get-FileHash.
Where the raw image lands matters on Windows: on NTFS it takes only the space of the data it holds, on exFAT it takes the full disk size and the tool says so with a warning, and FAT32 cannot hold it at all (a file stops at 4 GB there).
Converting writes a second file beside the raw image, named after the export with the hypervisor's extension, and ends by telling you whether the machine needs UEFI or BIOS. That line may read "UEFI (a BIOS boot partition is present too)": the disk has both, and UEFI is the one to pick. Looking inside opens a small shell over the disk: ls, cd, cat, get to copy a file or a whole directory out, find to search by name. Nothing is mounted and no administrator rights are needed; the disk is read directly, which is why it works the same on all three systems.
The download resumes on its own: a connection that drops or stalls is picked up where it stopped, an outage of up to five minutes is waited out, and the occasional spurious 403 from Hetzner's object storage is retried rather than treated as the end. Stopping with Ctrl-C removes the unfinished file.
Every step is also a plain subcommand for scripts: hetshield exports lists them, hetshield restore <link or file> --to <target> converts without questions (targets: proxmox, esxi, vmware, hyperv, virtualbox, raw), --out <path> names the file or a folder to put it in, hetshield browse server.raw opens the shell on a file you already have, and hetshield version prints the release and the instance it talks to.
The sign-in is stored in your user profile and lasts 90 days; hetshield logout removes it on this computer and revokes it on the server. Settings → Security lists every signed-in computer and can revoke one; changing your password signs every computer out.
Longer write-up on the conversions, with the boot fixes each hypervisor needs: Hetzner server to VMDK, VHDX or VDI with qemu-img
Or by hand
Only if you would rather not run our tool, or cannot. The file is a plain zstd-compressed disk image, and two standard tools do what hetshield restore does: zstd to decompress, qemu-img to convert. The decompressed file is as large as the original disk, so make sure the drive has room; the note on NTFS, exFAT and FAT32 under the tool section applies here too.
Decompress
# Debian, Ubuntu: sudo apt install zstd Fedora, RHEL: sudo dnf install zstd Arch: sudo pacman -S zstd
zstd -d server.img.zst -o server.raw
No flags needed: the file was compressed at a level zstd decompresses with its defaults. Runs of zeros are written as holes, so the file usually takes far less space on disk than its size suggests.
The converter
# Debian, Ubuntu: sudo apt install qemu-utils Fedora: sudo dnf install qemu-img Arch: sudo pacman -S qemu-img
qemu-img info server.raw
Only needed for VMware, Hyper-V and VirtualBox. Proxmox and libvirt take the raw file directly. If you copy the raw file somewhere, use cp --sparse=always so the holes survive the trip.
Checking the firmware yourself
fdisk -l server.raw # or: sgdisk -p server.raw
Optional — the download page already tells you. A partition of type EFI System means UEFI; none means legacy BIOS. Both tools read a plain file; lsblk does not, it only knows block devices.
Decompress
brew install zstd
zstd -d server.img.zst -o server.raw
macOS ships no zstd and Archive Utility does not open .zst, so Homebrew is the shortest route. Keka opens it too if you prefer a window to a terminal; The Unarchiver does not read zstd.
The converter
brew install qemu
qemu-img info server.raw
Checking the firmware yourself
hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount -readonly server.raw
diskutil list # a row of TYPE "EFI" under the new diskN means UEFI
hdiutil detach diskN
Optional. Nothing is mounted and nothing is written. brew install gptfdisk followed by sgdisk -p server.raw does the same in one line.
Decompress
Right-click server.img.zst → 7-Zip → Extract here. 7-Zip has opened .zst since version 24.01; if the entry is missing, update it. 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. Windows Explorer itself does not open a bare .zst file, only .tar.zst.
# or in PowerShell - 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 # 7-Zip only drops the .zst, so the file comes out as server.img
The converter
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 & in front, as above; without the call operator PowerShell prints the quoted path instead of running it. Needed for Hyper-V and VMware; VirtualBox converts on its own.
Checking the firmware yourself
Optional. Right-click server.raw → 7-Zip → Open archive: 7-Zip reads a raw disk as though it were an archive and lists its partitions; look at the File System column. A row showing EFI System means UEFI. Windows itself cannot mount a raw image, but once you have converted to VHDX for Hyper-V you can also ask PowerShell:
# mounting a VHDX needs an elevated window, unlike an ISO
Mount-DiskImage -ImagePath C:\VMs\server.vhdx -Access ReadOnly -NoDriveLetter
Get-DiskImage -ImagePath C:\VMs\server.vhdx | Get-Disk | Get-Partition | Where-Object GptType -eq '{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}' # one row = UEFI
Dismount-DiskImage -ImagePath C:\VMs\server.vhdx
The conversion, by hand
One line per hypervisor. Nothing inside the disk changes; the same bytes get the container the hypervisor expects. Each hypervisor section below assumes the file this produces.
|
Target
|
Command
|
|---|---|
| Proxmox, libvirt, QEMU, UTM | none — they read server.raw as it is |
| VMware ESXi | qemu-img convert -p -f raw -O vmdk -o adapter_type=lsilogic,subformat=streamOptimized server.raw server-stream.vmdk |
| VMware Workstation, Fusion | qemu-img convert -p -f raw -O vmdk server.raw web-01.vmdk |
| Hyper-V | qemu-img convert -p -f raw -O vhdx -o subformat=dynamic server.raw C:\VMs\web-01.vhdx |
| VirtualBox | VBoxManage convertfromraw server.raw web-01.vdi --format VDI |
On Windows, qemu-img writes the VHDX as a sparse file and Hyper-V refuses to open one (error 0xC03A001A). Run fsutil sparse setflag C:\VMs\web-01.vhdx 0 once after the conversion; it clears the flag in place. The hetshield command writes the file so that this step is not needed.
UEFI or legacy BIOS
A machine set to UEFI will not boot a disk built for legacy BIOS, and the reverse is just as true. It fails before any operating system appears — a blank screen, a firmware shell, an endless loop — which looks exactly like a corrupt download and is not one. Hetzner does not use the same firmware for every image, which is why we read it off your disk and print it on the download page rather than guessing.
|
Hypervisor
|
Download page says UEFI
|
Download page says legacy BIOS
|
|---|---|---|
| Proxmox VE | BIOS: OVMF (UEFI), plus an EFI disk | BIOS: SeaBIOS — the default |
| VMware ESXi / Workstation / Fusion | Firmware: EFI on ESXi; Firmware type: UEFI on Workstation and Fusion | Firmware: BIOS |
| Hyper-V | Generation 2, Secure Boot off | Generation 1 |
| VirtualBox | System → Enable EFI, or --firmware efi | Leave EFI off — the default |
| libvirt / virt-manager | --boot uefi, or Firmware: UEFI in the overview — needs the host's OVMF package (ovmf on Debian and Ubuntu, edk2-ovmf on Fedora) | Nothing to set |
| QEMU / UTM | OVMF as pflash, or the UEFI Boot checkbox | Nothing to set, or UEFI Boot unticked |
Two things that are true of every UEFI restore, whatever the hypervisor. A brand-new machine has an empty boot list, so its firmware looks for a fallback loader at EFI\BOOT\BOOTX64.EFI (EFI\BOOT\BOOTAA64.EFI on Arm); stock Debian and Ubuntu images have one, but if yours boots into a firmware shell, open the boot menu once and pick the entry under EFI\ubuntu or EFI\debian. And Secure Boot: Debian and Ubuntu ship a signed loader and boot with it on, anything with a self-built kernel or out-of-tree modules does not — if in doubt, switch it off first and turn it on once the machine is up.
Arm servers — the CAX types — are always UEFI, and their image runs only on an Arm host. It will not boot on an x86 machine at all.
Longer write-up, with the firmware setting for each hypervisor: Hetzner server to VMDK, VHDX or VDI with qemu-img
Proxmox VE
The shortest path of all: Proxmox reads the raw file as it is. Copy it onto the host, create an empty machine, import the disk into your storage, attach it. The web UI can import OVA and ESXi machines but not a raw file, so the import itself is three lines in the host shell; everything after that works in the UI too.
# 1. an empty machine - adjust memory, cores and the bridge to taste
qm create 900 --name web-01 --memory 4096 --cores 2 --cpu host --ostype l26 \
--scsihw virtio-scsi-single --net0 virtio,bridge=vmbr0 --serial0 socket
# 2. UEFI image only: OVMF plus a small EFI disk (skip both lines for BIOS)
qm set 900 --bios ovmf
qm set 900 --efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=0
# 3. import - the raw file goes in as it is; the last line prints the new volume name
qm disk import 900 /root/server.raw local-lvm
# 4. attach the volume the import printed (vm-900-disk-1 after an EFI disk, vm-900-disk-0 without one), make it the boot disk, start
qm set 900 --scsi0 local-lvm:vm-900-disk-1,discard=on,iothread=1 --boot order=scsi0
qm start 900
- Replace local-lvm with your storage and check the volume name the import prints — on file-based storages it looks like local:900/vm-900-disk-1.raw instead.
- On Proxmox 7 and earlier the command is qm importdisk; on 8 and 9 that still works as an alias. Proxmox 7.2 and newer can also do it in one go: qm create ... --scsi0 local-lvm:0,import-from=/root/server.raw
- pre-enrolled-keys=0 creates the EFI disk without Secure Boot keys, which boots anything. Stock Debian and Ubuntu images boot with =1 as well; the web UI's "Pre-Enroll keys" checkbox is the same switch.
- In the UI: Hardware → double-click "Unused Disk 0" → Bus SCSI → Add, then Options → Boot Order → tick scsi0. For UEFI: Options → BIOS → OVMF, and Hardware → Add → EFI Disk.
- The default i440fx machine type boots Linux fine; q35 is only needed for PCIe passthrough.
Longer write-up, from the export to the first boot: Migrate a Hetzner Cloud VM to Proxmox without downtime
VMware ESXi
ESXi refuses a plain VMDK — "Unsupported or invalid disk type 7". It wants the stream-optimized flavour, uploaded to a datastore and cloned into a native thin disk with vmkfstools. That second step is not optional. In the hetshield tool, pick "VMware ESXi" when it asks which hypervisor: it writes the stream-optimized file next to itself. By hand it is the ESXi line under Or by hand.
# on your computer: sign in, pick the export, "Convert it for a hypervisor" → "VMware ESXi (stream-optimized VMDK)"
hetshield # writes web-01-stream.vmdk next to the tool; for a script: hetshield restore web-01.raw --to esxi
# on the ESXi host, over SSH - it is off by default: Host Client -> Host -> Actions -> Services -> Enable Secure Shell
mkdir -p /vmfs/volumes/datastore1/tmp /vmfs/volumes/datastore1/web-01
# on your computer
scp web-01-stream.vmdk root@esxi:/vmfs/volumes/datastore1/tmp/
# on the ESXi host
vmkfstools -i /vmfs/volumes/datastore1/tmp/web-01-stream.vmdk -d thin \
/vmfs/volumes/datastore1/web-01/web-01.vmdk
rm -r /vmfs/volumes/datastore1/tmp # the stream copy is dead weight once it is cloned
- Then in the Host Client: Create / Register VM → Create a new virtual machine → Guest OS family Linux → pick the datastore → on Customize settings 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.
- Firmware: still inside that wizard, on Customize settings → VM Options → Boot Options → Firmware → EFI or BIOS, to match your download page, before you press Finish. On ESXi 8 a machine created with EFI can never be switched to BIOS, not even before its first power-on; if the wizard is already finished, delete the machine and create it again. 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; there is no need to convert a BIOS disk to UEFI.
VMware Workstation and Fusion
Workstation Pro on Windows and Linux, and Fusion on an Intel Mac, take a plain VMDK. One conversion, then create a machine around the existing disk.
# sign in, pick the export, "Convert it for a hypervisor" → "VMware Workstation or Fusion (VMDK)"
hetshield # writes web-01.vmdk next to the tool; for a script: hetshield restore web-01.raw --to vmware
# by hand: the Workstation line under "Or by hand"
- Workstation: File → New Virtual Machine → Custom → "I will install the operating system later" → Linux → name it → the firmware page: UEFI or BIOS as your download page says → CPU, memory, network → Use an existing virtual disk → browse to web-01.vmdk → Finish. Fusion: File → New → Create a custom virtual machine → Linux → Use an existing virtual disk → web-01.vmdk → Finish.
- To change the firmware later, with the machine powered off: Workstation under VM → Settings → Options → Advanced → Firmware type; Fusion under Virtual Machine → Settings → Advanced → Firmware type. In the .vmx file that is the line firmware = "efi".
- Fusion on Apple Silicon runs Arm guests only; an x86 image will not start there, whatever you set. See the macOS tab above for what does work on an M-series Mac.
Hyper-V
Hyper-V's "generation" is the firmware setting, and it cannot be changed after the machine exists: Generation 1 is legacy BIOS, Generation 2 is UEFI and boots only from a VHDX on SCSI. Convert to VHDX, then create the generation your download page names. PowerShell as administrator:
# by hand instead: the Hyper-V line under "Or by hand", plus its fsutil step
New-Item -ItemType Directory -Force C:\VMs | Out-Null
Set-Location C:\VMs # put hetshield-windows-amd64.exe here: it keeps the raw image and writes the VHDX where it runs
.\hetshield-windows-amd64.exe # sign in, pick the export, "Convert it for a hypervisor" → "Hyper-V (VHDX)": writes web-01.vhdx
# for a script: .\hetshield-windows-amd64.exe restore web-01.raw --to hyperv --out C:\VMs\web-01.vhdx
# "Default Switch" exists on Windows 10 and 11; Windows Server has none until you create one
Get-VMSwitch | Format-Table Name
# 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 Windows-only template, and a Linux disk then stops in the firmware: no error, no console output, 0 % CPU. Switch it off, as above. Microsoft also offers a "Microsoft UEFI Certificate Authority" template meant for Linux; the Ubuntu image we restored did not boot with it on Windows 11, so treat it as something to try afterwards, not first.
- In Hyper-V Manager the same choice is on the "Specify Generation" page of the wizard, and "Use an existing virtual hard disk" on the disk page. Secure Boot is under Settings → Security after the machine exists; untick it before the first start.
- Generation 1 accepts VHDX as well as VHD; there is no reason to use the older format.
- If Start-VM fails with "virtual hard disk files must be uncompressed and unencrypted and must not be sparse", the VHDX was converted by hand and the fsutil step under "Or by hand" was skipped. It clears the flag in place; nothing is copied. The hetshield command writes the file so that this never comes up.
VirtualBox
VirtualBox reads a VDI; the virtualbox target writes one, and VirtualBox can also convert the raw file itself, no qemu-img needed. VBoxManage is not on the PATH on Windows or macOS, so call it by its full path — in PowerShell with the call operator in front, & "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe", and on a Mac /Applications/VirtualBox.app/Contents/MacOS/VBoxManage.
# sign in, pick the export, "Convert it for a hypervisor" → "VirtualBox (VDI)"
hetshield # writes web-01.vdi next to the tool; for a script: hetshield restore web-01.raw --to virtualbox
# by hand: VBoxManage convertfromraw, under "Or by hand"
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)".
- VirtualBox on Apple Silicon runs Arm guests only. An x86 image will not start there.
libvirt and virt-manager
libvirt reads the raw file as it is. Copy it into the images directory with holes intact, then import; converting to qcow2 first is optional and buys you snapshots and thin allocation.
# Debian, Ubuntu: sudo apt install virtinst ovmf Fedora: sudo dnf install virt-install edk2-ovmf
sudo cp --sparse=always server.raw /var/lib/libvirt/images/web-01.raw
sudo virsh net-start default # once, if virt-install complains the default network is not active
virt-install --name web-01 --memory 4096 --vcpus 2 --cpu host-passthrough --import \
--disk path=/var/lib/libvirt/images/web-01.raw,format=raw,bus=virtio \
--network network=default,model=virtio \
--osinfo detect=on,require=off --graphics none \
--boot uefi # UEFI image only; drop this line for BIOS
- Recent virt-install refuses to run without --osinfo; detect=on,require=off lets it guess and carry on. --boot uefi picks your distribution's OVMF build automatically and enforces Secure Boot; if the firmware stops with "Access Denied" (self-built kernel, unsigned loader), use --boot uefi,secure-boot=off instead.
- --graphics none puts you on the serial console. If it stays blank after boot, the image only logs to tty1 — start with --graphics vnc and open the machine in virt-manager for the first boot instead.
- In virt-manager: New VM → "Import existing disk image" → browse → tick "Customize configuration before install" → Overview → Firmware: UEFI or BIOS.
QEMU and UTM, just to look
Before you commit to any of the above, this boots the image exactly where it lies and proves the copy is good. -snapshot sends every write to a throwaway file, so the raw image is never touched.
# Debian, Ubuntu: sudo apt install qemu-system-x86 ovmf Fedora: sudo dnf install qemu-system-x86 edk2-ovmf macOS: brew install qemu
# keep exactly one -accel line and, for UEFI, exactly one firmware line
qemu-system-x86_64 -m 4096 -smp 2 -snapshot \
-drive file=server.raw,format=raw,if=virtio \
-netdev user,id=n0 -device virtio-net-pci,netdev=n0 \
-accel kvm -cpu host # Linux
-accel hvf -cpu host # Intel Mac
-accel tcg -cpu max # Apple Silicon: emulated, slow
-accel whpx # Windows: turn on "Windows Hypervisor Platform" under Windows Features first; leave -cpu out, -cpu max breaks on AMD
# UEFI image: add the firmware as a read-only flash device
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd # Debian, Ubuntu
-drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/ovmf/OVMF_CODE.fd # Fedora, RHEL
-drive if=pflash,format=raw,readonly=on,file=$(brew --prefix)/share/qemu/edk2-x86_64-code.fd # macOS
-drive if=pflash,format=raw,readonly=on,file="C:\Program Files\qemu\share\edk2-x86_64-code.fd" # Windows
UTM on a Mac
UTM is QEMU with a window. New → Emulate for an x86 image on Apple Silicon (Virtualize only when the image's architecture matches the Mac's) → Other → skip the ISO → set memory → Save. Then Edit: System → Architecture x86_64; Drives → delete the default drive → New Drive → Import → server.raw, interface VirtIO; QEMU → tick UEFI Boot for a UEFI image, untick it for BIOS. Give it more than one core and tick "Force multicore" too. Expect minutes, not seconds — it is emulation.
The first boot on the new host
The machine boots, and it cannot be reached. This catches nearly everybody, and it is the moment people decide the export is broken. It is not: your server carries the fixed address Hetzner gave it, a gateway of 172.31.1.1, and a network card called eth0 — none of which exist where it now lives. Open a console on the new machine, not SSH, and work through these in order.
1. Find the new name of the network card
ip -br link # ens18 on Proxmox, enp1s0 on libvirt, enp0s3 on VirtualBox, eth0 on Hyper-V
Hetzner's cloud-init pins the name eth0 to the MAC address of the original card. The new host hands out a different MAC, so that rename never fires, and the configuration you brought along, which talks about eth0, is ignored the moment the card is called anything else.
2. Give it an address — DHCP is the quickest way back
Ubuntu — netplan
# replace the contents of /etc/netplan/50-cloud-init.yaml with:
network:
version: 2
ethernets:
lan:
match: { name: "e*" }
dhcp4: true
sudo netplan apply
Debian — /etc/network/interfaces
# ls /etc/network/interfaces.d/ - the file is 50-cloud-init or, on older images, 50-cloud-init.cfg; replace its contents (NAME from step 1):
auto NAME
iface NAME inet dhcp
sudo systemctl restart networking
Rocky, Alma, Fedora — NetworkManager
sudo nmtui # Edit a connection -> set IPv4 to Automatic, device to the new name
# or without the menu:
sudo nmcli con add type ethernet ifname NAME con-name lan ipv4.method auto
sudo nmcli con up lan
3. Switch off what only made sense at Hetzner
sudo touch /etc/cloud/cloud-init.disabled # stops it looking for Hetzner's metadata service at every boot
sudo apt remove hc-utils # Debian images; Rocky/Alma: sudo dnf remove hc-utils - Ubuntu images do not have it
cloud-init on a foreign host either disables itself or waits a minute or two for a metadata service that is not there; the empty file is the supported off-switch and makes it deterministic. hc-utils is Hetzner's helper for private networks and starts its own DHCP client on any new network card, fighting the one you just configured. qemu-guest-agent, which Hetzner images also ship, is harmless and useful on Proxmox and libvirt — keep it.
4. If the boot stops at an emergency prompt
grep HC_Volume /etc/fstab
That is an attached volume, which no agentless export can contain. Hetzner's own fstab line carries nofail and the machine boots without the volume; a hand-written line without it drops you to this prompt. Comment the line out, or add nofail to it, and reboot. Then restore the volume's data from wherever you back that up.
5. Only if the copy runs next to the original
sudo rm -f /etc/machine-id /var/lib/dbus/machine-id && sudo systemd-machine-id-setup && sudo dbus-uuidgen --ensure
sudo rm -f /etc/ssh/ssh_host_* && sudo ssh-keygen -A && sudo systemctl restart ssh # the service is called sshd on Rocky, Alma and Fedora
A restore that replaces the original should keep its identity, so every client's known_hosts still matches. A second copy running alongside the first should not share a machine-id or host keys with it. Both machine-id files have to go: with only /etc/machine-id removed, systemd copies the old id straight back from the D-Bus one.
Where your data goes
The temporary machine uploads the file directly to our object storage. It does not travel through our application, and no employee is emailed a copy of anything.
The download link is signed and expires after seven days, after which the object is removed — or earlier, when you delete it from your export page. Until then it is yours alone: it is not listed anywhere, not indexed, and not shared. The rescue password Hetzner issues for the temporary machine is used once, in memory, and never written down.
Limits and failures
- Hetzner allows 30 disk copies per account. Ours exists for minutes and is then deleted, but if you are already at the limit the export cannot start. Delete a few in the Hetzner console and try again.
- Server types sell out. Hetzner stock changes by the minute. We walk through every suitable type in every location before giving up, and if all of them are gone we stop and tell you rather than leaving something half-built. Trying again a few minutes later usually works.
- A run that fails leaves nothing behind. Cleanup runs on the way out either way. If Hetzner refuses to delete something, the export page names the resource so you can remove it yourself, and we log it on our side too.
- One export per server at a time. Starting a second one while the first is running would spend two of your 30 disk copies for one result, so we send you back to the run already in progress.
Help and bug reports
One address for everything, read by the person who built this: mail@hetshield.com. There is no ticket system and no bot; you get an answer from a human, usually within a working day.
- An export stopped. You do not have to write for the refund: a paid export that does not finish is refunded on its own, and the export page says so. If you want to know why, send the link of the export page; we find the run by it and nothing else is needed.
- The machine will not boot or cannot be reached. Walk through the firmware section and the first-boot steps above first; they cover nearly every case. If it still stops, tell us the hypervisor and its version, the firmware your download page names, and what the screen shows at the point it stops — a photo of it is fine.
- A bug on this site or in the hetshield command. What you did, what you expected, what happened instead, and on which system. For the command, paste its last lines of output; it prints nothing secret.
- A security problem. Same address, with "security" in the subject. We fix first and talk after, and we say who found it if you want that.
- Something missing here. A hypervisor we do not cover, a distribution that behaves differently on first boot, a command that did not work as written: tell us and it goes into this page.
- An idea. A hypervisor you would like the tool to write for, a step the export page should show, a target the exports should go to: write it down as you would say it. What gets built next comes from these mails more than from anything else.
That is the whole thing.
A few minutes, a few cents at Hetzner, and a file on your disk.