This episode covers live migration: moving a VM between hosts without downtime using the expanded protocol, including page-faults served from the source in v53. You'll set up shared storage and networking, run a migration through the API, and understand version and device compatibility constraints.

The snapshot we learned in episode 10 does capture VM state, but there's a brief pause while the VM is stopped. To maintain full availability — a server serving requests must not stop for even a second — we need live migration: moving a VM from one host to another with no downtime perceived by the guest.
The best analogy is moving a busy shop to a new building: all goods are moved bit by bit while customers keep being served, and only when the move is nearly complete is there a final, instantaneous switch. In episode 11 we dissect how Cloud Hypervisor does this, what the prerequisites are, and the constraints you must respect in production.
Migration runs in several phases:
Migration success depends on how fast dirty pages are copied relative to the memory change rate — the slower the change rate, the shorter the stop-and-copy pause.
Since v53.0 (12 July 2026), live migration uses a post-copy approach with page-faults served from the source. In other words: instead of waiting for all memory to be copied (which can take a long time for VMs with large memory), the target starts running the VM right away and requests the pages it needs from the source as page faults occur. The effect: total migration time is much shorter, at the cost of depending on the source's availability during the transition.
Note
Post-copy sacrifices something: until all pages are copied, the target still depends on the source. If the source dies mid-transition, the VM can lose pages that weren't copied yet. Good infra design keeps the source alive until the migration is declared complete.
Migration moves machine state, not disk contents. That's why both hosts must see the same disk — shared storage (NFS, iSCSI, Ceph RBD, or distributed storage). In our practice, set up NFS:
sudo mkdir -p /srv/vms
sudo mount -t nfs storage.internal:/exports/vms /srv/vmsBoth hosts access ubuntu.raw and the snapshot files from the same location. Otherwise, the target can't read the disk when the VM is moved.
Source and target must be connected, and ideally on the same network bridge so the guest's MAC and IP remain valid without network reconfiguration:
sudo ip link add name br0 type bridge
sudo ip link set br0 up
sudo ip link set eth0 master br0If the networks differ, the guest must be reconfigured after migration — which defeats the "no downtime" advantage.
The destination host starts the VM in "receive" mode, waiting for the migration:
cloud-hypervisor \
--kernel kernel-vmlinux \
--disk path=/srv/vms/ubuntu.raw \
--cpus boot=2 \
--memory size=2G,shared=on \
--net tap=ch0,ip=192.168.100.1,mac=a8:21:95:80:35:e6 \
--api-socket /tmp/target.sockNote that this is a normal VM — the migration later "overwrites" its state. shared=on on both sides is mandatory (just like snapshot).
From the source host, call the migration endpoint via the API:
curl --unix-socket /tmp/source.sock -X PUT \
-H "Content-Type: application/json" \
--data '{
"receiver_url": "http://192.168.100.2:5000",
"protocol": "extended"
}' \
http://localhost/api/v1/vm.migratereceiver_url: the address the target opens to receive migration data.protocol: "extended": uses the expanded live migration protocol — including the post-copy page-faults served by the source in v53.The target listens on that port using its API socket:
curl --unix-socket /tmp/target.sock -X PUT \
-H "Content-Type: application/json" \
--data '{
"receiver_url": "http://192.168.100.2:5000",
"protocol": "extended"
}' \
http://localhost/api/v1/vm.migrateWhen the migration completes, the VM on the source stops automatically and execution continues fully on the target. From the guest's perspective, no process realizes it changed hosts.
Inside the guest, confirm there's no significant disruption:
uptime -s
cat /proc/uptimeuptime -s still shows the original boot time — if it shows the migration time, the VM was rebooted, not migrated. For a more convincing test, run a continuous ping from the host during migration and observe only millisecond gaps (not tens of seconds).
The same rule as snapshots applies: live migration is not supported between different Cloud Hypervisor versions. Both hosts must run an identical version (or within a guaranteed LTS compatibility window). This is a consequence of the state format being tied to a version. In production, separate your migration "release trains": upgrade all hosts in one wave, not gradually across major versions.
Not every device can be migrated easily:
Before migrating, check that both hosts' device configurations are truly aligned:
diff <(cat /srv/vms/guest.json) <(ssh target "cat /srv/vms/guest.json")Migrating Windows has additional challenges around timers (TSC) and devices — make sure both hosts use CPUs with identical features, because Windows guests are very sensitive to differences in exposed CPU features.
Warning
Don't assume "migration will always succeed" — a slow network or heavy write load keeps dirty pages growing and migration can fail in the stop-and-copy phase. Monitor the dirty memory rate (e.g., via perf kvm or VMM metrics) and run regular test migrations outside peak hours.
shared=on on only one side: the target fails to receive memory. Set it on both sides.Key takeaways:
In the next episode, episode 12, we'll dissect virtual I/O: virtio, IOMMU, and security — how virtio ring buffers and packed virtio work, virtio-iommu for paravirtualized IOMMU, and Landlock and seccomp sandboxing that protect the host from the VMM itself. VM security starts from the bottom.