The Proxmox VE import wizard does its job: it brings the virtual machine over from ESXi without you touching a .vmdk by hand. Then you boot that Windows and get a blue screen. The wizard did nothing wrong. The mistake was made the day somebody wrote "migrate the Windows VMs" as one line in the plan for Saturday night.
There is a difference between copying a machine and moving it. Copying is a bandwidth problem: you solve it with more network, more disk and more patience, and it is boringly predictable. Moving also drags along a decision the guest operating system made when it was installed, years ago, about which disk controller it would find the next time it booted. That decision does not travel inside the virtual disk and cannot be changed from the hypervisor. It is changed inside Windows, with Windows running. And by the time the migration goes wrong, Windows no longer boots.
The wizard does its part well, and that is worth saying
Proxmox VE 8.2, released on 24 April 2024, added the ESXi importer as a storage plugin, integrated into the API and the web interface. You point it at the ESXi host as if it were one more datastore, the VMs appear, you pick them and import them with much of their configuration mapped onto Proxmox's model. It is not a third-party script or a qm importovf with forum notes attached: it is product functionality. Water has flowed under the bridge since — we are on the 9 branch now — and the importer has kept improving; what has not changed is what comes next.
Its limits are documented, and they are all there. The Proxmox wiki warns that importing "can be significantly slower if the VM has snapshots", that "importing a VM with disks backed by a VMware vSAN storage does not work", that "encrypted VM disks, for example via a Storage Policy, cannot be imported", that a datastore with special characters such as + in its name "might not work", and that while you can import through a vCenter instance, doing so "will dramatically reduce performance". It recommends powering down the VM on the source side for a consistent state, and states that importing was tested from ESXi 6.5 through 8.0.
Notice what those five warnings have in common: they are all about transport. How fast the disk arrives, and whether it arrives at all. The wiki does also have a whole section on preparing the guest, and it is a good one; we will come back to it. But it is a list of what: it does not say when each thing has to happen, or what each one costs if you leave it for Saturday night. That gap is not the documentation's job to fill, and it is what the rest of this article is about.
The line in the wiki that explains the loop
Proxmox's official documentation on paravirtualised Windows drivers puts it in a single sentence, and it is the most important sentence in this whole story: "To switch an existing Windows installation to use the VirtIO-SCSI drivers and boot from them, it needs to see a disk requiring the driver before". For an existing Windows installation to use the VirtIO SCSI drivers and boot from them, it needs to have seen a disk requiring that driver beforehand.
It is a circular dependency. That disk does not exist while the VM lives on ESXi, where the controller is usually an LSI Logic — Parallel or SAS — or a VMware Paravirtual, and on more recent installs may be NVMe. It exists on Proxmox, but by then Windows no longer boots and cannot see it. The before in that sentence falls at a moment when the machine is still on the hypervisor you are leaving, and that is the whole problem: this is not forum folklore or a quirk of one release, it is written in the vendor's own wiki.
The migration wiki itself offers the emergency exit, and it is the one almost everybody ends up using: when the guest is Windows, "the disk bus type needs to be switched from the default SCSI to IDE or SATA", because those drivers "should normally always be installed". Translated: you boot through an emulated, slower controller so you can get into the system. It works, the wiki says so and we have done it. What is also true is that by then the migration has become a repair job, and a repair job runs with the window ticking.
The official procedure is correct. It is not a plan
The documented recipe for breaking out of the loop is the decoy-disk trick, and it works: with the VM already booting via SATA, you insert the VirtIO driver ISO in the CD drive and add a temporary 1 GB disk with Bus Type SCSI and, under Options, the VM's SCSI Controller Type set to VirtIO — that is two settings, not one, and the second is the one everybody skips — or else VirtIO Block. The wiki hedges what many tutorials take for granted: "The disk should get hot plugged. If not, you need to reboot the VM". Windows detects it as an unknown device, you install the driver from the ISO's vioscsi folder, shut down, detach the decoy and the boot disk, and reattach the boot disk as VirtIO SCSI. Then comes the warning most often forgotten — "Adapt the Boot Order under the VM's Option tab. Make sure that the primary boot device is still the old boot disk" — and, just in case, the plan B: "If the VM does not boot, you can detach and re-attach the disk as IDE or SATA to redo the procedure with the dummy disk".
What comes next is our reading, not the wiki's: that procedure solves one machine, it does not solve a migration. Count what it costs per VM and the shape of the problem shows up. One extra clean shutdown and boot of a Windows Server — two and two if the disk does not hot-plug and you have to reboot, which is the case the wiki itself allows for. One manual step inside the guest, with a mouse: automating it through the Proxmox API requires the guest to already have the QEMU agent inside and running, which is exactly what a freshly imported ESXi VM does not have. A boot-order change that cannot be forgotten. And all of it, necessarily, after the disk has been copied.
The arithmetic that breaks the window
We are not going to give you minutes per machine, because we have not measured them in a way we could defend: they depend on disk size, on the destination storage, and on whether that Windows decides to install updates just as it shuts down, which is exactly when it decides to. What is fixed, and is all you need to see the problem, is the shape of the cost: it is per machine, it is sequential, and it falls inside the window.
With three Windows machines it fits. With forty it does not, and the bad part is how it does not fit: the plan does not blow up halfway and stop. At six in the morning somebody looks at the clock and decides to leave the last ten booting on SATA for now. That "for now" is what turns up months later in a performance ticket nobody connects to the migration, because by then the migration was signed off as finished and successful. It was finished: it is just that part of the work stayed open under a different name.
The one part of this work with a hard ordering constraint — it has to happen before, it cannot happen after — is precisely the part the standard plan puts afterwards. Everything else can be pushed with more network, more hands or more night, and that is why everything else gets planned well: because it accepts having resources thrown at it when it goes wrong.
The fix is not to go faster: it is to move the work to another date
The VirtIO driver can be placed into the Windows driver store while the VM is still alive and serving on ESXi, and flagged to load at boot. When the disk changes controller, Windows will not need to "have seen before" anything: the driver is already in and already flagged. The loop unwinds through the only place where unwinding it costs no window, which is the past. It can also be unwound at the destination — the wiki explains how and it works, and there are other routes done entirely on Proxmox — but all of them are paid for in shutdowns, boots and mouse clicks, with the night running.
There are public guides with scripts that do exactly this, and they describe the result plainly: "By injecting the driver into the Windows Driver Store and flagging it to load during initialization, you eliminate the hardware-toggling loop entirely". We have not audited that code and we are not going to tell you to run it blind on your domain controller; if you use it, read it first and try it on a machine that does not matter. What interests us here is not the specific tool, which might be a script, a manual preparation or whatever your supplier puts in front of you. What interests us is that the work moves to a different box in the calendar: out of Saturday small hours, with the VM off and rollback awkward, and into a Tuesday afternoon, with the VM running, the service up, and the option to undo without anybody noticing.
The driver is not the only thing that stays inside the guest
There is at least one more task with exactly the same shape, and it is also in the wiki: "On Windows, consider removing the static network configuration, if there is any. After the migration, the network adapter will change and Windows will show a warning if you configure the same IP address on another network adapter, even if the previous one is not present anymore". Same pattern: you touch it before, the symptom shows up after, and the symptom is confusing — Windows complaining about a duplicate IP on a network card that no longer exists. At four in the morning that is twenty minutes of looking in the wrong place.
And there is a third with the same shape that is worse than a blue screen, because the penalty is not failing to boot but failing to decrypt. The wiki says it without drama: "If full-disk encryption is used in the VM and the keys are stored in a virtual TPM device, consider disabling it. It is currently not possible to migrate the vTPM state to Proxmox VE from VMware. Make sure to have the manual keys to decrypt the VM available, just in case". Translated into what actually happens: BitLocker with the key in the vTPM, the vTPM does not travel, and the recovery key was somewhere somebody has to have gone looking for beforehand. The same beforehand again.
None of these tasks is a secret of ours: the wiki opens its preparation section asking you to "remove any guest tools specific to the old hypervisor, as it might be difficult to remove them after" — that is VMware Tools — and goes on to the network, DHCP reservations and the vTPM. They are all written down and they are all correct. What we add is one single thing, and this one is our own practice: installing the QEMU guest agent before moving rather than after, because that is what lets you handle the guest from outside once it is at the destination. And note that the machine's network is only half of it: the other half is the host's, which on Proxmox does not live in a central place but on each node, as we wrote in migrating to Proxmox: the network lives on each node.
This is not about VirtIO. It is about how plans get written
Every migration has a short list of tasks that can only be carried out on the system you are about to retire. They are the only ones with an ordering that cannot be negotiated, and they are exactly the ones that get lost. They get lost because plans are written backwards from the event: "on Saturday we do A, then B, then C". What has to happen the Tuesday before has no box in that table, so it does not exist, and because it does not exist nobody is assigned to it.
That VM's boot failure is predictable. It is documented, it has a name and it has been there for years. What is not inevitable is the outage: three hours of window burned, a service that does not come back on Monday, and a migration the committee will remember as "the one that went wrong". That part was a scheduling decision, taken two weeks earlier by somebody drawing up a table who did not notice it was missing a column on the left.
That is why this article's sibling is the one on the rollback plan, and it is worth not confusing the two. Preparing the guest beforehand lowers the probability of having to use the rollback; it does not lower one bit the need to have it written down. They are two different controls on the same risk, and anyone who swaps one for the other ends up with neither.
Three dates instead of one
Two weeks before. Guest preparation, on ESXi, during office hours and with the machines running: VirtIO driver in and flagged for boot, static network configuration written down and removed where appropriate, VMware Tools out. And the inventory, which is the part nobody does: a Windows Server 2012 R2 is not a 2022, and an LSI Logic controller is not a VMware Paravirtual or an NVMe. If you do not know how many of each you have, you do not have a plan, you have an intention.
One week before. One real machine actually migrated — the least important one you have — and left running on the new cluster for seven days. Not to check whether the wizard works: it works. To find out which of these steps your machines need and which they do not, and so the team runs the procedure once in daylight, unhurried, with room to get it wrong. A rehearsal that cannot go wrong is not a rehearsal.
The night itself. Copy. Nothing else. If on migration night somebody is installing drivers inside a Windows machine, the preparation was not done: it was postponed, and postponed all the way to the one moment when it can no longer be done properly.
When this is not about you
If all your machines are reasonably modern Linux, this is a lot of noise for very little: the virtio modules usually ship in the initramfs and the VM boots with no intervention. "Usually" is literal, and in the RHEL family — Rocky, Alma — nobody has to break it: dracut builds the initramfs in host-only mode by default, with the modules for the hardware it could see on the day it was built, which was VMware's. The symptom then is not a blue screen but a kernel panic, and it is the classic reason a Linux VM fails to boot after moving from VMware to KVM. You check it with the machine running, two weeks earlier, with one command: lsinitramfs /boot/initrd.img-$(uname -r) | grep virtio on Debian and Ubuntu, lsinitrd | grep virtio on RHEL and derivatives. If nothing comes back, you know what to do and when.
And if you have three Windows machines and a whole afternoon ahead of you, the official wiki route serves you perfectly and you need none of what we have described: do the decoy disk, install the driver, move on. This article is about scale, about the point where multiplying a manual procedure by the number of machines stops fitting into one night. And before all of this there is still the other question, the one that also deserves saying out loud: when not to migrate from VMware to Proxmox. Sometimes the right answer is to stay.
We have worked with Proxmox since the 3.x branches and with vSphere since fairly old versions, and we have done both: migrated companies from VMware to Proxmox and advised others to stay where they were. We cannot recall a migration that went badly because of the destination hypervisor. The ones that get complicated get complicated by the calendar.
How many of your Windows machines would boot tomorrow on a different controller?
We build the real inventory — which Windows, which controller, which static network config — prepare the guests with the VMs still running, and reduce migration night to copying: VMware to Proxmox migration with a rehearsal beforehand and a rollback plan in writing, on infrastructure somebody then has to operate. And if it turns out your case is to stay on VMware, we will say so: we are not resellers of either and we do not sell licences, so the recommendation does not change our invoice.
Talk to everyWANNote on sources
From the official Proxmox wiki Migrate to Proxmox VE come the ESXi importer limitations we quote (slowness with snapshots, vSAN unsupported, disks encrypted via Storage Policy, datastore names with special characters such as +, the performance drop when importing through vCenter), the recommendation to power down the VM at source for a consistent state, the tested version range (ESXi 6.5 to 8.0), the instruction to switch the disk bus from SCSI to IDE or SATA when the guest is Windows — because those drivers "should normally always be installed" — and its whole preparation section, from which we quote three bullets: removing guest tools specific to the old hypervisor (VMware Tools), the static network configuration and the adapter changing after migration, and full-disk encryption with keys held in a vTPM whose state cannot be migrated from VMware. That section also covers noting down the guest network configuration and adapting DHCP reservations to the new MAC, which we mention in passing. From the official wiki Paravirtualized Block Drivers for Windows come the key sentence we reproduce in its English original — "To switch an existing Windows installation to use the VirtIO-SCSI drivers and boot from them, it needs to see a disk requiring the driver before" — the 1 GB temporary disk procedure with Bus Type SCSI and the VirtIO SCSI controller under Options (or VirtIO Block) plus the driver ISO and its vioscsi folder, the caveat that the disk "should get hot plugged. If not, you need to reboot the VM", the warning about adapting the boot order, and the plan B of re-attaching the disk as IDE or SATA if the VM does not boot. That the ESXi importer arrived with Proxmox VE 8.2, released on 24 April 2024, and that it is implemented as a storage plugin integrated into the API and interface, comes from Proxmox's press release for that version. The quote about injecting the driver into the Windows Driver Store and flagging it to load during initialization comes from a public croit guide on migrating Windows VMs to Proxmox VE; we reproduce it and we have NOT audited the script it proposes, which we say in the text itself. Spanish and Catalan quotations are our own translations from the English originals. The reading that the official procedure is a per-machine repair rather than a migration plan, the analysis that its cost is per machine, sequential and inside the window, and the thesis that the only task with a hard ordering constraint is the one the standard plan puts last, are OURS and not from any source cited. We give no per-machine duration figures because we have not measured them defensibly, and we would rather say so than round. That we run Proxmox VE with Ceph in production, that we have worked with vSphere since old versions and with Proxmox since the 3.x branches, that we have migrated companies from VMware to Proxmox and also advised staying, and that we are not resellers of either platform, is everyWAN's own information. That dracut builds the initramfs in host-only mode by default in the RHEL family, and the commands for checking whether the virtio modules are in there, are standard behaviour of those distributions; check it on your own machine anyway before relying on it. The steps described do not replace checking in your own environment. The cover photograph is "Empty server rack — IMG 3677", by Jemimus, published on Wikimedia Commons under CC BY 2.0.