🔀 VMware to Proxmox VE

The VMware-to-Proxmox word map, importing OVF files and VMDK disks (tested), what the import does not bring over (the NIC), UEFI, VirtIO, MAC addresses and a safe cutover

Video: VMware to Proxmox VE (DevOps video)
Prefer to watch? This short video runs this page's main commands in a real lab, with on-screen captions and no voiceover. Click to play, or watch it on YouTube.
Moving from VMware to Proxmox VE: concepts, importing disks and OVF files, and the gotchas
qm importovf 105 legacy-vm.ovf local-lvm; qm disk import 100 disk.vmdk local-lvm

Many teams are looking at Proxmox VE as a replacement for VMware vSphere/ESXi. The good news is that the building blocks are familiar: hypervisor hosts, shared or local datastores, virtual switches, snapshots, templates, clones, backups. The bad news is that the names change, the defaults are different, and a few steps (the disk controller, the network card, the boot firmware) decide whether an imported guest boots on the first try.

This page is the migration companion to "Proxmox VE: install it, set it up and run it day to day". Everything marked as run was run for real on a Proxmox VE 9.2 lab (a virtual machine under QEMU/KVM, with nested virtualization). The lab had no VMware product, so the test disks and the OVF file were made by hand: the disk with qemu-img, in the VMDK format VMware uses, and the OVF file written by hand in the same layout VMware's exporter produces. That tests the import commands themselves; it does not test how a real VMware guest boots afterwards. Anything about ESXi itself, Windows or boot behaviour is marked "from the documentation, not run here".

1. VMware words and their Proxmox equivalents

  VMware                                    Proxmox VE
  vCenter Server                            the web page of any node, or a cluster (no separate management server to install)
  ESXi host                                 a node (a Proxmox VE install; a Debian system with extra packages)
  datacenter / cluster                      "Datacenter" (the cluster) with its nodes
  datastore (VMFS, NFS)                     storage: directory, LVM-thin, ZFS, NFS, iSCSI, Ceph (a storage lists the content it may hold)
  virtual machine disk (.vmdk)              a volume on a storage; imported disks are converted to the storage's format
  VM (.vmx, .vmdk)                          QEMU/KVM guest, configuration in /etc/pve/qemu-server/ID.conf
  vSwitch / port group                      Linux bridge (vmbr0), optionally VLAN-aware, with a VLAN tag on each guest NIC
  VMXNET3 / PVSCSI                          VirtIO network card / VirtIO SCSI: the fast paravirtual devices (vmxnet3 and others still exist)
  VMware Tools                              QEMU guest agent (qemu-guest-agent) plus VirtIO drivers on Windows
  template / clone                          template / clone (a clone of a template can be "linked")
  snapshot                                  snapshot (on the storage; LVM-thin, ZFS and qcow2 support them)
  vMotion                                   live migration between nodes of a cluster (from the documentation, not run here)
  DRS / HA                                  high availability (HA) in a cluster; automatic load balancing like DRS is more limited, so check Proxmox's documentation for your version (from the documentation, not run here)
  vSAN                                      Ceph, or ZFS replication (from the documentation, not run here)
  backup products (Veeam and others)        built-in vzdump, and Proxmox Backup Server; several third-party tools also support Proxmox
  OVF/OVA export and import                 qm importovf, and the import wizard in the web page

One difference to understand early: a Proxmox node is an ordinary Linux machine. You can ssh in, run apt, read journalctl and use every Linux tool you already know. There is no black-box console and no separate vendor shell.

2. Plan the migration before you touch a VM

  1. Inventory: list every VM with its CPU count, memory, disks, NICs and the operating system. Mark which ones are Windows, which Linux, and which use UEFI or secure boot.
  2. Mark special hardware: PCI passthrough, USB devices, vGPU, shared (clustered) disks, RDMs, or anything attached to a physical device. These need individual planning.
  3. Pick a pilot: move one unimportant VM first and write down every step. Move the rest in groups.
  4. Decide the storage: LVM-thin or ZFS on local disks, or shared storage. Size it, remembering that thin-provisioned disks do not grow beyond their pool.
  5. Plan the network: the VLANs the VMs use must exist on the Proxmox bridge (section 7 of the companion page) and on the physical switch ports.
  6. Plan the cutover: for each VM decide the downtime window, the order (databases before the apps that use them), and who tests it.
  7. Back up everything first, on the VMware side, and keep the originals until the new guests have run for a while (section 12).

3. Prepare the guest before you leave VMware

This section is from the documentation and from general practice, not run in the lab (no real guests were migrated):

  Linux guests: modern kernels already include the VirtIO drivers, so the guest will usually find a VirtIO disk and network card. Make sure /etc/fstab uses UUIDs or labels, not device names such as /dev/sdb. Note the current network interface names and addresses (ip -br a): interface names change on the new hardware, for example ens192 to ens18, and a config tied to the old name will not come up.
  Windows guests: Windows does not include VirtIO drivers. Either install them before the move (the "virtio-win" driver ISO is published by the Fedora project) or import the VM with an emulated disk (SATA) and an emulated NIC (e1000) first, install the drivers, and switch to VirtIO afterwards. Starting a Windows guest on a controller it has no driver for ends in a boot failure ("inaccessible boot device" is the classic one).
  Both: write down the IP address, the MAC address, and any licence tied to the MAC or to the hardware. Install the QEMU guest agent in the guest (the qemu-guest-agent package on Linux) so that Proxmox can see the guest's address and shut it down cleanly.
  VMware Tools: they are useless on Proxmox. Remove them after the move, when the guest is running and you can reach it.

4. Method A: import straight from an ESXi host

Recent Proxmox VE versions include an import wizard for ESXi: you add the ESXi host as a storage of type "ESXi" (Datacenter, Storage, Add), browse the VMs it holds, and import one into Proxmox. Proxmox's documentation describes the steps and the limits (for example, what happens with snapshots and with VMs that use features it cannot convert). This method was not run in the lab, because the lab had no ESXi host, so read Proxmox's documentation for your version before relying on it. Its advantages are that nothing needs exporting and that the VM can be imported while the ESXi host stays up; its limits are the same as any import: you still fix the controller, NIC and firmware afterwards (sections 6 and 7).

5. Method B: import an OVF or a VMDK (tested)

If you export the VM from VMware as an OVF/OVA, or copy its VMDK, Proxmox can import it from the command line. Copy the files to the Proxmox node first (scp is enough); a VM exported as an OVF is a descriptor file (.ovf) plus the disk file(s) (.vmdk), and they must be in the same folder. An OVA is a tar archive of the same files: unpack it with tar first (this unpacking step was not run). The lab used these two files:

$ ls -l /root/legacy-vm.ovf /root/esxi-test.vmdk | awk '{print $5,$9}'
327680 /root/esxi-test.vmdk
3209 /root/legacy-vm.ovf

Import the OVF as a new VM (ID 105) with its disks on the local-lvm storage:

$ qm importovf 105 /root/legacy-vm.ovf local-lvm
  Logical volume "vm-105-disk-0" created.
  Logical volume pve/vm-105-disk-0 changed.
transferred 0.0 B of 2.0 GiB (0.00%)
transferred 2.0 GiB of 2.0 GiB (100.00%)

$ qm list
      VMID NAME                 STATUS     MEM(MB)    BOOTDISK(GB) PID
       100 lab-vm               stopped    512                2.00 0
       102 lab-vm               stopped    512                2.00 0
       104 from-template        stopped    512                2.00 0
       105 legacy-vm            stopped    2048               0.00 0

To import only a disk into a VM that already exists, use qm disk import (the older name, qm importdisk, still works and printed no warning in the lab):

$ qm disk import 100 /root/esxi-test.vmdk local-lvm
importing disk '/root/esxi-test.vmdk' to VM 100 ...
  Logical volume "vm-100-disk-1" created.
  Logical volume pve/vm-100-disk-1 changed.
transferred 0.0 B of 2.0 GiB (0.00%)
transferred 2.0 GiB of 2.0 GiB (100.00%)
unused0: successfully imported disk 'local-lvm:vm-100-disk-1'

The disk arrives as "unused0": it exists on the storage but is not attached to anything. Attach it to a controller slot:

$ qm config 100 | grep -E '^(unused|scsi)'
scsi0: local-lvm:vm-100-disk-0,size=2G
scsihw: virtio-scsi-single
unused0: local-lvm:vm-100-disk-1

$ qm set 100 --scsi1 local-lvm:vm-100-disk-1
update VM 100: -scsi1 local-lvm:vm-100-disk-1

$ qm config 100 | grep -E '^scsi'
scsi0: local-lvm:vm-100-disk-0,size=2G
scsi1: local-lvm:vm-100-disk-1,size=2G
scsihw: virtio-scsi-single

Notice what the progress shows: "transferred 2.0 GiB of 2.0 GiB". The source disk was almost empty (a 320 KB sparse file), but the copy into an LVM-thin volume wrote the whole 2 GB, because LVM-thin stores raw disks and the import converts the format as it copies. Allow time for large disks and check where the data is going (an almost empty disk may take longer than its file size suggests).

The "does not support vm images" trap. Importing into the default "local" directory storage failed:

$ qm disk import 100 /root/esxi-test.qcow2 local --format qcow2
storage local does not support vm images

The directory storage called "local" is installed to hold ISO images, container templates, backups and import files, not disk images. Allow disk images on it, then repeat the import:

$ pvesm set local --content iso,vztmpl,backup,import,images

$ grep -A3 '^dir: local' /etc/pve/storage.cfg
dir: local
	path /var/lib/vz
	content images,vztmpl,backup,import,iso

$ qm disk import 100 /root/esxi-test.qcow2 local --format qcow2
transferred 0.0 B of 2.0 GiB (0.00%)
transferred 2.0 GiB of 2.0 GiB (100.00%)
unused1: successfully imported disk 'local:100/vm-100-disk-0.qcow2'

$ ls -lh /var/lib/vz/images/100/ ; du -h /var/lib/vz/images/100/vm-100-disk-0.qcow2
-rw-r----- 1 root root 2.1G Oct  4 05:43 vm-100-disk-0.qcow2
520K	/var/lib/vz/images/100/vm-100-disk-0.qcow2

ls reports the virtual size (2.1G) while du shows the real space used (520K): the file is sparse. A qcow2 file on a directory storage supports snapshots and thin allocation; a raw volume on LVM-thin or ZFS is usually faster. Pick a format and storage deliberately for each class of VM.

6. What the OVF import did and did not bring over

This is the most important finding of the lab. The OVF file described a VM with 2 CPUs, 2 GB of memory, a SCSI controller, one disk and one VMXNET3 network adapter on the "VM Network" port group. The imported VM looks like this:

$ qm config 105
boot: order=scsi0
cores: 2
memory: 2048
name: legacy-vm
scsi0: local-lvm:vm-105-disk-0
smbios1: uuid=82681ba8-f8ee-4301-8cd9-87d68386f893
vmgenid: 17dd5c30-3561-46a3-8d23-ef85cf3ad993

  Imported:       the name, the number of CPUs, the memory size and the disk (on scsi0, with the boot order set to it)
  NOT imported:   the network adapter (there is no net0 at all), the disk controller type (no scsihw line), the operating system type (no ostype), the firmware (no bios line: it defaults to SeaBIOS, the legacy BIOS) and any VMware-specific hardware

So an OVF import gives you a VM that will not have a network card until you add one, and that will try to boot a UEFI guest in BIOS mode. Checking and fixing these is the real work of an import, and why the next section matters. (The lab's OVF was hand-written in VMware's layout; a real export from VMware may carry more or fewer details, so look at every imported VM's config before you start it.)

7. Fixing up the imported VM: controller, NIC, firmware, disk options

Add the network card, the controller, the OS type and the guest agent in one command, then set the firmware:

$ qm set 105 --net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-single --ostype l26 --agent enabled=1
update VM 105: -agent enabled=1 -net0 virtio,bridge=vmbr0 -ostype l26 -scsihw virtio-scsi-single

If the guest boots with UEFI on VMware, give it UEFI firmware and an EFI variable disk on Proxmox. The command creates the small EFI disk and pre-loads the standard Secure Boot keys:

$ qm set 105 --bios ovmf --efidisk0 local-lvm:1,efitype=4m,pre-enrolled-keys=1
INFO: reading raw edk2 varstore from /usr/share/pve-edk2-firmware//OVMF_VARS_4M.ms.fd
efidisk0: successfully created disk 'local-lvm:vm-105-disk-1,efitype=4m,ms-cert=2023k,pre-enrolled-keys=1,size=4M'

(How to tell whether the guest was UEFI or BIOS on VMware: in its VM options the "Boot options / firmware" setting says "EFI" or "BIOS". A Linux guest can also check for /sys/firmware/efi; this check was not run in the lab.) Disk options that usually help on SSD storage: discard passes deletes down to the storage so thin pools get space back, ssd tells the guest it is an SSD, and iothread gives the disk its own I/O thread:

$ qm set 105 --scsi0 local-lvm:vm-105-disk-0,discard=on,iothread=1,ssd=1
update VM 105: -scsi0 local-lvm:vm-105-disk-0,discard=on,iothread=1,ssd=1

The NIC model can be changed at any time. A guest without VirtIO drivers can start with an emulated card, and vmxnet3 is also available if you want to stay close to what the guest used on VMware:

$ qm set 105 --net0 e1000,bridge=vmbr0
$ qm set 105 --net0 vmxnet3,bridge=vmbr0 && qm config 105 | grep -E '^(net0|scsi0)'
update VM 105: -net0 vmxnet3,bridge=vmbr0
net0: vmxnet3=BC:24:11:6C:AE:48,bridge=vmbr0
scsi0: local-lvm:vm-105-disk-0,discard=on,iothread=1,size=2G,ssd=1

Each guest NIC can be put on a VLAN, which replaces the VMware port group (the bridge must be VLAN-aware; see the companion page):

$ qm set 100 --net0 virtio,bridge=vmbr0,tag=20
net0: virtio=BC:24:11:7C:DC:49,bridge=vmbr0,tag=20

The imported VM then started (the lab used an empty disk, so the proof is only that the VM and its OVMF firmware start):

$ qm start 105; sleep 4; qm status 105; qm stop 105
status: running

8. Method C: convert the disk yourself with qemu-img

If you only have a VMDK, or you want to choose the format yourself, convert it with qemu-img (it comes with Proxmox, and with QEMU on any Linux). The lab converted a VMDK to qcow2 on the laptop and copied it over:

$ qemu-img convert -p -f vmdk -O qcow2 esxi-test.vmdk esxi-test.qcow2
$ qemu-img info esxi-test.qcow2 | grep -E 'file format|virtual size|disk size'
file format: qcow2
virtual size: 2 GiB (2147483648 bytes)
disk size: 196 KiB

Use "-O raw" for a raw image, which is what LVM-thin and ZFS volumes hold. Then import it as shown above. (A VMware "flat" disk is a pair of files: a small name.vmdk descriptor and a large name-flat.vmdk with the data. Keep both in the same folder and point qemu-img at the descriptor. That pair layout is from VMware's documentation and was not run here.)

9. Keep the old MAC address, and a safe cutover

A VM that gets a new MAC address on the new platform can break DHCP reservations, firewall rules, licences and some network policies. Keep the old MAC on the new NIC (the lab used a VMware-style 00:50:56 address as the example):

$ qm set 105 --net0 virtio,bridge=vmbr0,macaddr=00:50:56:AA:BB:CC && qm config 105 | grep ^net0
net0: virtio=00:50:56:AA:BB:CC,bridge=vmbr0

The risk during a cutover is two copies of the same guest on the same network (the old one on VMware, the new one on Proxmox) answering to the same address. Prevent it: shut the old VM down first, and import and test the new one with its network cable "unplugged", then connect it:

$ qm set 105 --net0 virtio,bridge=vmbr0,macaddr=00:50:56:AA:BB:CC,link_down=1
net0: virtio=00:50:56:AA:BB:CC,bridge=vmbr0,link_down=1

(Start it, check it boots to the console, then remove link_down by setting the net0 line again without it.)

$ qm set 105 --net0 virtio,bridge=vmbr0,macaddr=00:50:56:AA:BB:CC && qm config 105 | grep ^net0
net0: virtio=00:50:56:AA:BB:CC,bridge=vmbr0

To make the guest start with the host and in a controlled order (databases before applications), set start-on-boot and a startup order with a delay:

$ qm set 105 --onboot 1 --startup order=2,up=30 && qm config 105 | grep -E '^(onboot|startup)'
onboot: 1
startup: order=2,up=30

The final configuration of the migrated VM, with everything above applied:

$ qm config 105
agent: enabled=1
bios: ovmf
boot: order=scsi0
cores: 2
efidisk0: local-lvm:vm-105-disk-1,efitype=4m,ms-cert=2023k,pre-enrolled-keys=1,size=4M
memory: 2048
name: legacy-vm
net0: virtio=00:50:56:AA:BB:CC,bridge=vmbr0
onboot: 1
ostype: l26
scsi0: local-lvm:vm-105-disk-0,discard=on,iothread=1,size=2G,ssd=1
scsihw: virtio-scsi-single
smbios1: uuid=82681ba8-f8ee-4301-8cd9-87d68386f893
startup: order=2,up=30
vmgenid: 17dd5c30-3561-46a3-8d23-ef85cf3ad993

10. Backups, snapshots and templates after the move

After the move, set up backups first, before anything else depends on the new platform. The lab backed up the migrated guest (a stopped VM here; on a running guest "snapshot" mode backs it up without stopping it) and restored it under a new ID:

$ vzdump 105 --storage local --mode snapshot --compress zstd
INFO: starting new backup job: vzdump 105 --compress zstd --mode snapshot --storage local
INFO: creating vzdump archive '/var/lib/vz/dump/vzdump-qemu-105-2026_10_04-05_46_56.vma.zst'
INFO: transferred 2.00 GiB in 2 seconds (1.0 GiB/s)
INFO: archive file size: 95KB
INFO: Finished Backup of VM 105 (00:00:05)
INFO: Backup job finished successfully

$ qmrestore /var/lib/vz/dump/vzdump-qemu-105-2026_10_04-05_46_56.vma.zst 205 --storage local-lvm
total bytes read 2148073472, sparse bytes 2147483648 (100%)
rescan volumes...

$ qm config 205 | grep -E '^(bios|net0|name|efidisk0)'
bios: ovmf
efidisk0: local-lvm:vm-205-disk-0,efitype=4m,ms-cert=2023k,pre-enrolled-keys=1,size=4M
name: legacy-vm
net0: virtio=00:50:56:AA:BB:CC,bridge=vmbr0

The restored copy kept the UEFI firmware setting, the EFI disk and the VMware-style MAC address, so a restore is also a way to clone a migrated guest for testing (change its MAC and address first, or the copy will clash with the original).

A backup contains the guest's current state only. As the lab's vzdump printed: "snapshots found (not included into backup)". VMware habits to unlearn: a long chain of snapshots is not a backup and not a good idea here either (snapshots live on the same storage as the disk). Templates and clones work as you expect: turn a prepared guest into a template and clone it; on LVM-thin the clone is a linked clone sharing blocks with the template until it diverges (tested on the companion page).

11. When the imported guest does not boot or has no network

These are the usual causes and fixes. Items marked (lab) were seen in the lab; the others are from the documentation and general practice and were not run here.

  No network card at all after an OVF import (lab)
        The import does not create the NIC. Add one with qm set ID --net0 virtio,bridge=vmbr0 (section 7).
  "Storage local does not support vm images" (lab)
        Allow images on that storage with pvesm set, or import to a storage that holds images (section 5).
  A UEFI guest drops to a boot menu or says there is no bootable device
        The imported VM defaulted to BIOS firmware. Set --bios ovmf and add an efidisk0 (section 7), and check the boot order.
  A BIOS (legacy) guest will not start under OVMF
        Do the opposite: use the default SeaBIOS (qm set ID --bios seabios; remove the efidisk0).
  Windows blue-screens early with "inaccessible boot device" (documentation)
        The boot disk is on a controller Windows has no driver for. Boot it on SATA (qm set ID --sata0 ...) with the old disk, install the VirtIO drivers, then switch to VirtIO SCSI.
  Linux boots to the initramfs prompt or cannot find the root filesystem (documentation)
        The root device name changed or the initramfs lacks the disk driver. Use UUID in fstab/boot config, and rebuild the initramfs with the VirtIO modules.
  The guest has no network but the NIC exists (documentation)
        The interface name or MAC changed. Look at ip a inside the guest, then fix the network configuration to the new name, or set the old MAC with macaddr=.
  Two machines answer on the same address
        The old VM is still running. Shut it down before connecting the new NIC (section 9).
  The guest is slow
        Check that it uses VirtIO devices and the "host" or a recent x86-64-v2 CPU type, not an emulated disk and NIC.

12. Rollback plan

Do not delete anything on the VMware side until the new guest has run correctly for a while. Keep the original VM powered off but intact (with its snapshots and disks), or at least a verified backup. Rolling back means shutting the Proxmox guest down and powering the VMware one on again, which only works if nothing was changed in the original. If the guest wrote data in the meantime (a database, a mail store) rolling back also loses that data, so decide the "point of no return" in advance and tell the people involved.

13. What this page did not test

Run in the lab: qm importovf and qm disk import (with an OVF and VMDKs made by hand), qm importdisk, qemu-img convert, a snapshot-mode backup and restore of the migrated guest, the content-type error and its fix, the fix-up commands, UEFI firmware set-up, NIC models, MAC address keeping, link_down, start order, and the final configuration. Not run: the ESXi import wizard (no ESXi host), exporting from vCenter or ESXi, OVA unpacking, real Windows or Linux guests booting after the move, VirtIO driver installation, the QEMU guest agent, VMware Tools removal, and clusters, live migration and high availability. Read Proxmox's documentation for those, and test each on a pilot VM first.

14. Tips

  1. Move one unimportant VM first and write down every step.
  2. Always look at qm config ID after an import and before the first start: the NIC, controller and firmware are yours to set.
  3. Windows: get the VirtIO drivers in before you switch the disk and NIC to VirtIO, or use SATA and e1000 for the first boot.
  4. Keep the old MAC address if anything depends on it, and bring the new NIC up only after the old VM is off.
  5. Give imported disks the right storage and format on purpose, and enable discard on thin storage.
  6. Install the QEMU guest agent in every migrated guest.
  7. Set up backups on Proxmox before you retire anything on VMware, and do one test restore.
  8. Keep the old VMs until the new ones have run for a while.