Skip to main content

Warm Migration Node Setup

Before the first warm migration to a Proxmox node, that node needs the VDDK runtime. The dialog probes the selected node and shows "Target node is not ready for warm migration" with the list of missing components until all of them are present. This is a one-time setup per node, and ProxCenter can carry it out for you.

Alert in the migrate dialog: Target node is not ready for warm migration, Missing on the node: vddk-plugin, vddk-lib, with the Prepare this node button and the link to the warm migration node setup guide.
A node without the VDDK: the dialog names what is missing and offers Prepare this node.

The warm path needs four components on the Proxmox node:

ComponentSourceNotes
nbdkitDebian mainAvailable on a stock Proxmox node.
nbd-clientDebian mainAvailable on a stock Proxmox node.
nbdkit-plugin-vddkDebian contrib / non-freeNot enabled by default on Proxmox. Enable the repositories first.
Broadcom VDDK (libvixDiskLib.so*)Installed by ProxCenterProprietary Broadcom SDK. Broadcom withdrew its public download in August 2026, so ProxCenter ships it to Enterprise subscribers and installs it on the node.
Network access to the ESXi hosts (TCP 443 and 902)

Warm migration copies disk data with the VMware VDDK in NBD transport mode, which uses the NFC (Network File Copy) protocol. The target Proxmox node must reach each source ESXi host on both TCP 443 (authentication and management) and TCP 902 (the NFC data channel that carries the disk blocks).

Port 443 alone is not enough. Authentication and the node readiness check will pass, the target disks will be allocated, and the migration will only fail later at the VixDiskLib_Open step against the ESXi host, when VDDK opens the NFC data channel. Open TCP 902 from the Proxmox node to every ESXi host before starting a warm migration.

Network diagram of a warm migration in three zones. ProxCenter calls vCenter on 443, calls the XCP-ng pool on 443 for XAPI, and reaches the target Proxmox node, which runs Proxmox VE 9, over SSH on 22. The Proxmox node signs in to vCenter on 443 for the VDDK and reads the disk blocks from each ESXi host on TCP 902, the NFC data channel, which is the port usually forgotten; with a standalone ESXi host there is no vCenter and the node reaches the host on 443 as well as 902. For an XCP-ng pool the node reads each pool host over NBD on TCP 10809, with TLS pinned to the host certificate. The node probes port 902 before anything is allocated and the run stops there when it is closed.Network diagram of a warm migration in three zones. ProxCenter calls vCenter on 443, calls the XCP-ng pool on 443 for XAPI, and reaches the target Proxmox node, which runs Proxmox VE 9, over SSH on 22. The Proxmox node signs in to vCenter on 443 for the VDDK and reads the disk blocks from each ESXi host on TCP 902, the NFC data channel, which is the port usually forgotten; with a standalone ESXi host there is no vCenter and the node reaches the host on 443 as well as 902. For an XCP-ng pool the node reads each pool host over NBD on TCP 10809, with TLS pinned to the host certificate. The node probes port 902 before anything is allocated and the run stops there when it is closed.
The connections of a warm migration. TCP 902 from the Proxmox node to every ESXi host is the one most often left closed; the node checks it before anything is allocated.

The Source vSphere Version the Node Can Read​

Broadcom supports each VDDK release against its own vSphere release and the two before it. The VDDK installed on the node therefore sets a floor on how old a source it can read, and the migrate dialog compares the two before the run starts.

VDDK generation on the nodeOldest vSphere it is supported against
7.xvSphere 6.5
8.xvSphere 6.7
9.xvSphere 7.0

Below vSphere 6.5 the warm path is refused whatever the node carries. VDDK 6.5 is the last release Broadcom tested against ESXi 5.5 and it does not run on Debian 13, while the nbdkit of Proxmox VE 9 loads the libvixDiskLib.so.8 interface that only VDDK 8 and later provide: there is no combination that works.

Three outcomes, because they call for different answers:

Source versionResult
Below vSphere 6.5Refused, under the heading "Warm migration cannot read this source": "The source runs vSphere X. Warm migration reads disks through the Broadcom VDDK, which on a Proxmox VE 9 node supports vSphere 6.5 and later, so the copy would fail with an I/O error after zero bytes.", followed by the generation the node carries
Between vSphere 6.5 and the node's own floorA warning, in the dialog and in the job log: "The source runs vSphere X, older than the vSphere Y this node's VDDK is supported against. The copy may fail on the first read; a cold migration is unaffected." Broadcom does not support the pair, but the copy has a real chance of working, so the run goes ahead
At or above the node's floorNothing is said

A cold migration is unaffected, which is what the refusal points at: it reads over HTTPS and never loads the VDDK, so it stays the answer for an old source. A source whose version cannot be read at all is let through: this check exists to explain a run that cannot work, never to become a second reason a reachable source is refused.

Two alerts: Warm migration cannot read this source for a vSphere 6.0 source, naming the VDDK 9 floor of the node and pointing to a cold migration; and a warning for a vSphere 6.7 source older than the vSphere 7.0 the node VDDK is supported against.
The source version check: a refusal below vSphere 6.5, a warning between 6.5 and the floor of the VDDK on the node.
Grid of the source vSphere version, 5.5 to 9.0, against the VDDK generation on the Proxmox node. vSphere 5.5 and 6.0 are refused for every VDDK, since below vSphere 6.5 no VDDK that runs on Proxmox VE 9 can read the source. With VDDK 7.x, whose floor is 6.5, nothing is said from 6.5 up. With VDDK 8.x, floor 6.7, 6.5 gets a warning and 6.7 and later nothing. With VDDK 9.x, floor 7.0, 6.5 and 6.7 get a warning and 7.0 and later nothing. Refused shows Warm migration cannot read this source, and a cold migration, which reads over HTTPS and never loads the VDDK, is the answer; the warning appears in the dialog and the job log, says the copy may fail on the first read, and the run goes ahead; nothing is said at or above the floor of the node's VDDK, and a version that cannot be read is let through.Grid of the source vSphere version, 5.5 to 9.0, against the VDDK generation on the Proxmox node. vSphere 5.5 and 6.0 are refused for every VDDK, since below vSphere 6.5 no VDDK that runs on Proxmox VE 9 can read the source. With VDDK 7.x, whose floor is 6.5, nothing is said from 6.5 up. With VDDK 8.x, floor 6.7, 6.5 gets a warning and 6.7 and later nothing. With VDDK 9.x, floor 7.0, 6.5 and 6.7 get a warning and 7.0 and later nothing. Refused shows Warm migration cannot read this source, and a cold migration, which reads over HTTPS and never loads the VDDK, is the answer; the warning appears in the dialog and the job log, says the copy may fail on the first read, and the run goes ahead; nothing is said at or above the floor of the node's VDDK, and a version that cannot be read is let through.
Below vSphere 6.5 a warm migration is refused whatever the node carries; between 6.5 and the floor of the node's VDDK it runs with a warning. A cold migration is never affected.
Why a version mismatch does not look like one, and how the node probe finds the VDDK generation

A VDDK too recent for its source opens the disk over SOAP on port 443 and reports the right capacity, so nbdkit comes up and nbd-client exports a device of the correct size. Only the NFC data channel on port 902 refuses, and the copy dies on dd: error reading '/dev/nbd0': Input/output error after zero bytes. Checking the version before the run saves the snapshot, the volume allocation and the thick zeroing that would come first.

The node probe resolves the libvixDiskLib.so.8 name that nbdkit actually loads down to the real library file, because both the unversioned libvixDiskLib.so symlink and the .so.8 compatibility symlink ProxCenter creates when it provisions a node point at that file whatever its generation, so neither says anything on its own.

A failed block apply names what failed. The apply step folds each dd's standard error into its output, so a warm copy that dies reports the reason it was given, Input/output error on the source side or No space left on device on the target, instead of the generic "command failed" wrapper of the transport underneath.

1. Let ProxCenter prepare the node​

In the Migrate to Proxmox VE dialog, choose Warm Migration and select the target node. When the node is not ready, the readiness alert lists what is missing and offers Prepare the node. Confirm, and ProxCenter performs the whole preparation over SSH:

  • installs nbdkit and nbd-client from the Debian repositories
  • adds /etc/apt/sources.list.d/proxcenter-nonfree.list to enable the Debian contrib and non-free components, then installs nbdkit-plugin-vddk
  • downloads the VDDK into /usr/lib/vmware-vix-disklib (about 96 MB on disk) and creates the library symlink the Proxmox nbdkit expects
  • loads the nbd kernel module with max_part=0, now and at every boot

It takes a couple of minutes, and the alert turns green when it is done. Running it again on a prepared node is harmless: every step is skipped when it is already satisfied, and nothing is re-downloaded.

The readiness alert after Prepare this node: the confirmation text listing the apt packages, the Debian non-free apt source and the VDDK download, with Prepare the node and Cancel; then the running state, Preparing the node (apt packages plus a 33 MB VDDK download).
Prepare this node asks for a confirmation that lists what it installs, then reports its progress in the same alert.

The Proxmox node needs outbound HTTPS to ghcr.io for the download, the same requirement as the ProxCenter high-availability images. The registry credentials stay on the ProxCenter server, which hands the node a short-lived, download-only token; the Enterprise installer configures them, so there is nothing to type.

Prepare the node is missing from the dialog

Two distinct causes hide the automated action.

The node runs Proxmox VE 8. The readiness alert then states the requirement instead of listing missing components: warm migration needs Proxmox VE 9, and such a node cannot be prepared at all, since Debian 12 does not package the nbdkit VDDK plugin.

The ProxCenter container does not hold the registry token. The action appears only when GHCR_TOKEN reaches the frontend container. An installation upgraded by pulling the images alone may not have it: the compose file passes its environment through an explicit environment: list, and an older compose file has no line for the token. The readiness alert then lists what the node is missing and links to the manual path below, with no automated action offered. Re-run the standard Enterprise install command to fix it, as described in Updating ProxCenter: it refreshes the compose file, writes the token, and preserves your secrets, your customised URLs and your data.

Why ProxCenter ships the VDDK

The VDDK is a proprietary Broadcom SDK. Broadcom withdrew its public download in August 2026: the developer-portal link returns a 404 and the kit is no longer listed in the public SDK catalogue, so a new customer cannot obtain it there. ProxCenter therefore ships the runtime to Enterprise subscribers, unmodified and with its Broadcom license notice, and installs it on the nodes that need it.

2. Or prepare the node by hand​

Use this path when the Proxmox node has no outbound access to the registry, or when your policy requires you to place the runtime yourself. Run everything as root on each target node.

nbdkit and nbd-client, from the standard Debian repositories:

apt update
apt install nbdkit nbd-client

On a node without a Proxmox subscription, apt update exits with a 401 on the enterprise.proxmox.com repository. That is harmless here, since these packages come from the Debian repositories.

The nbdkit VDDK plugin, which lives in Debian non-free. Enable contrib and non-free in the node's apt sources, then install it:

. /etc/os-release
echo "deb http://deb.debian.org/debian ${VERSION_CODENAME} contrib non-free non-free-firmware" \
> /etc/apt/sources.list.d/proxcenter-nonfree.list
apt update
apt install nbdkit-plugin-vddk

The Broadcom VDDK. It is not in any package repository, and since August 2026 it is no longer a public download. Obtain the Linux x86_64 archive from Broadcom through your own entitlement: a support case opened with the account that carries your vSphere subscription, your backup software vendor, or a copy your organisation already holds. Any VDDK 9.x release works, and Broadcom supports 9.x against vSphere 7.0.x and 8.0.x.

Then install the runtime libraries under /usr/lib/vmware-vix-disklib, so that libvixDiskLib.so* ends up in /usr/lib/vmware-vix-disklib/lib64/:

mkdir -p /usr/lib/vmware-vix-disklib
tar xzf VMware-vix-disklib-*.tar.gz -C /usr/lib/vmware-vix-disklib --strip-components=1
ldconfig
VDDK 9.x library name

The nbdkit shipped with Proxmox loads the libvixDiskLib.so.8 library name. With VDDK 9.x, create the matching symlink (VDDK 8.0.x ships .so.8 directly and needs none):

cd /usr/lib/vmware-vix-disklib/lib64
ln -sf libvixDiskLib.so.9 libvixDiskLib.so.8
ldconfig

The strongest single check that the plugin and the library agree:

nbdkit vddk libdir=/usr/lib/vmware-vix-disklib --dump-plugin

It prints the plugin's version block with no error. A complaint about a missing libvixDiskLib.so.8 means the symlink is absent.

3. Prevent LVM from auto-activating guest volume groups​

Relevant when migrating Linux guests that use LVM (most enterprise Linux templates). During a warm migration the guest disk is attached to the Proxmox node as an NBD device. When the node's LVM scans it, it auto-activates the guest's volume group on the host. ProxCenter releases those volumes itself before it detaches the device, so the migration completes and the device is freed, but two side effects remain for as long as the copy runs: the guest's logical volumes show up in lvs on the node, and a guest volume group that carries the same name as a host one (pve is common) makes Proxmox's own LVM operations fail with "Multiple VGs found with the same name".

Tell LVM to ignore NBD devices on the target node. The automated Prepare this node action does this for you. By hand, edit /etc/lvm/lvm.conf and add "r|/dev/nbd.*|" at the front of the global_filter list that Proxmox already ships in the devices { } section, keeping the existing entries:

global_filter = [ "r|/dev/nbd.*|", "r|/dev/zd.*|", "r|/dev/rbd.*|" ]

Check the result with lvmconfig --validate. No reboot is needed: LVM reads the file again on every device event. Do not replace the list, and never drop the zd and rbd entries, which keep LVM away from ZFS volumes and Ceph images.

Why the LVM filter is safe on Proxmox

Proxmox's own LVM and LVM-Thin storage lives on physical disks, never on /dev/nbd*, and warm migration reads the guest disk as a raw device rather than through LVM. The filter only stops LVM from touching the transient NBD devices used during migration.

4. Reselect the node​

Back in the Migrate to Proxmox VE dialog, reselect the target node. The readiness check runs again and, once every component is detected, shows "Target node is ready for warm migration" and enables the migration button.

Green alert: Target node is ready for warm migration (nbdkit, nbd-client and the VDDK are present).
Once every component is found, the readiness check turns green and the migration can start.
What the readiness check verifies

ProxCenter confirms nbdkit and nbd-client are on PATH, that nbdkit-vddk-plugin.so exists under /usr/lib or /usr/lib64, and that the VDDK library directory (/usr/lib/vmware-vix-disklib/lib64 by default) really carries the library. It follows the libvixDiskLib.so.8 name that nbdkit loads down to the file it resolves to, so it reports the VDDK generation rather than merely "something is installed", which is what makes the source version check possible.

Free space on the target storage​

The warm preflight reads the live free space of the selected storage on the target node and compares it with the source disks plus the 10 % margin the cold engine already applies. The dialog shows both figures and blocks the launch rather than letting the copy run out of room halfway: "Not enough free space on STORAGE: X GB available, Y GB needed for the source disks plus a 10% margin. Free up space on it or pick another storage." A storage whose free space cannot be read is reported as such. The same rule is applied by the engine at planning time, so it also covers a node chosen automatically and a migration started straight from the API.

Red alert in the migrate dialog: Not enough free space on CephStoragePool, 5.7 GB available, 16.0 GB needed for the source disks plus a 10% margin, free up space or pick another storage.
The warm preflight blocks a target storage that cannot hold the source disks.