VPS fit run Proxmox with nested virtualization?
Most VPS providers hide the vmx flag. Run kvm-ok in one minute, then see whether your VPS fit host KVM or Proxmox guests and the exact errors to expect.
Di short answer
Nested virtualization na when hypervisor dey run inside virtual machine: your VPS don already be guest, and you want make e host im own guests. E go work only when your provider hypervisor deliberately expose CPU virtualization extensions to your instance. Check /proc/cpuinfo for vmx flag (Intel) or svm (AMD). If none of dem show, nothing wey you configure inside VPS go fix am.
Make we set one expectation first: Docker no need any of dis things. Containers dey share your VPS kernel and dem no ever touch /dev/kvm. If di real goal na "run several services inside containers for my server", you already get wetin you need. Nesting matter when you want second kernel, Proxmox lab, Windows guest, Firecracker microVMs, Android emulator, Kubernetes testbed of real VMs, or CI runners wey boot VM images.
Wetin dem actually dey nest
Three layers:
- L0, provider hypervisor wey dey on the physical machine. You no get access to am.
- L1, your VPS. To L0, na just guest e be.
- L2, the VM wey you wan run inside your VPS.
Hardware virtualization na VT-x (the vmx flag) plus EPT for Intel, and AMD-V / SVM (svm) plus RVI/NPT for AMD. Hypervisor dey use those instructions enter guest mode and make CPU walk through two page tables at the same time.
Dem no design either one to run recursively, so nesting dey get emulation: when L1 execute VMX instruction like VMLAUNCH or VMRESUME, e trap go L0. L0 then maintain the shadow structures for L2 on behalf of L1. For CPUs wey support VMCS shadowing, L1 VMREAD and VMWRITE fit work without exit. This remove plenty of that traffic, but no remove all of am. KVM dey handle this well, but na L0 dey do extra work for every exit. Na why provider need enable am.
When L0 na KVM, two conditions must hold before accelerated L2 fit work:
- L0 KVM module must load with
nested=1. - L0 must give your VPS CPU model wey carry the flag:
<cpu mode='host-passthrough'/>for libvirt,cpu: hostfor Proxmox, and-cpu hostfor raw QEMU. Generic emulated model (qemu64,kvm64) dey hidevmxeven when nesting don enable globally.
Other hypervisors get their own switch. Hyper-V, for example, dey emulate virtualization extensions for nested hypervisor inside its VMs, but na only VMs wey nesting don enable one by one fit use am.
Check your VPS for one minute
# 1. Are you in a VM, and under what?
systemd-detect-virt # kvm, vmware, xen, microsoft, or "none" on metal
# 2. Does the CPU expose the extensions to you?
grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u
lscpu | grep -i -E 'virtual|hypervisor'
# 3. The definitive check
sudo apt update && sudo apt install -y cpu-checker
kvm-ok
# 4. The device node the whole stack depends on
ls -l /dev/kvmA usable instance suppose e print vmx or svm, kvm-ok dey show KVM acceleration can be used, and /dev/kvm dey exist with root:kvm mode 660. If the flag dey but device node no dey, load the module by hand and read kernel log:
sudo modprobe kvm_intel # or kvm_amd
sudo dmesg | tail -n 20One file dey get quoted plenty times, and people dey often misread am:
cat /sys/module/kvm_intel/parameters/nested # Y or NInside your VPS, na setting for your KVM module be that. E control whether an L2 guest fit nest one third level. E no talk anything about whether L0 enable nesting for you. /proc/cpuinfo and kvm-ok answer that question. The nested parameter na the setting wey you fit change for machine wey belong to you completely:
echo 'options kvm_intel nested=1' | sudo tee /etc/modprobe.d/kvm-nested.conf
sudo modprobe -r kvm_intel && sudo modprobe kvm_intelDem go refuse remove module while VM dey run, so shut down guests first. If that machine na Proxmox host, enable nested virtualization for Proxmox VE 9 cover the same modprobe.d change plus the per-VM cpu: host setting wey make the flag show inside guest.
Why most VPS hosts dey leave am off
- Live migration. To give you
vmxmean say dem expose CPU model wey carry the flag. Guest wey depend on those CPU features no fit migrate safely go machine wey CPU no get dem. Host wey dey drain nodes by migrating customers go lose that option once e enable nesting. - Attack surface. The nested VMX/SVM paths dey among the most complex code for kernel virtualization layer, and CVE history dey show the risk.
- L0 fit no be KVM. If
systemd-detect-virtprintsvmware,xenormicrosoft, na that stack own nesting rules, no be KVM own.
Your instance no get the flag? Ask support, because some providers dey enable am per-VM. You fit choose plan wey document nesting, or move go dedicated box. The remaining steps assume say you get root for machine wey dey show the flag.
Running an L2 guest with libvirt
sudo apt install -y qemu-system-x86 libvirt-daemon-system virtinst ovmf
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt,kvm "$USER" # log out and back in
virt-install \
--name guest1 \
--memory 2048 \
--vcpus 2 \
--cpu host-passthrough \
--disk path=/var/lib/libvirt/images/guest1.qcow2,size=20,format=qcow2,bus=virtio \
--network network=default,model=virtio \
--os-variant debian13 \
--location https://deb.debian.org/debian/dists/trixie/main/installer-amd64/ \
--graphics none \
--console pty,target_type=serial \
--extra-args 'console=ttyS0,115200n8'You no need graphical session. Serial installation fit take some time, so start am inside a persistent shell: the same tmux workflow wey dey keep Claude Code sessions alive for VPS dey keep a virt-install console attached even if SSH connection drop. If --os-variant debian13 reject, your osinfo-db old pass the release, run osinfo-query os and choose a name wey exist. --cpu host-passthrough forward vmx down into L2, but na only when L2 need virtualize another guest. Use virsh autostart guest1 make the guest fit boot safely.
The virtio bus for disk and NIC no be decoration: emulated IDE and e1000 devices dey trap into the hypervisor much more often than virtio queues. Under nesting, if L0 no fit finish an exit by itself, e go reflect am up to L1. Handling am there fit trigger more exits for L1 too.
Networking: di part wey tutorials dey skip
Your VPS get one public IP and e dey behind one network fabric wey dey filter unknown MAC addresses. Two things go follow.
Bridging L2 guests go public network usually no go work. Put br0 for the public NIC, give the guest im own MAC, and you go see ARP go out but nothing come back. Provider switch dey drop frames from MAC wey e never lease give you. If na this you dey see, stop debugging the bridge; na so the mechanism dey work.
Use the NAT network instead. libvirt ships default: virbr0, 192.168.122.0/24, dnsmasq leases, and outbound connectivity dey work immediately. For inbound traffic, terminate TLS for L1 and proxy am inside. The certificate paths below come from issuing a Let's Encrypt certificate with Certbot on Nginx:
server {
listen 443 ssl;
server_name lab.example.com;
ssl_certificate /etc/letsencrypt/live/lab.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/lab.example.com/privkey.pem;
location / {
proxy_pass http://192.168.122.50:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Give the guest static lease first (virsh net-edit default), so the address inside that proxy_pass no go change.
Keep management interfaces off the internet: VNC for 5900 and the Proxmox web UI for 8006 suppose dey on loopback. Reach dem through SSH tunnel (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) or through a self-hosted WireGuard VPN into the VPS, wey go put the whole 192.168.122.0/24 guest range one private hop away. Keep the firewall narrow, sudo ufw allow 22,80,443/tcp, nothing else. If guests lose outbound connectivity immediately after you enable ufw, the usual cause na DEFAULT_FORWARD_POLICY="DROP" inside /etc/default/ufw. Set am to ACCEPT and reload ufw.
Proxmox for VPS
Proxmox VE 9 na Debian 13 underneath, so e dey install for Debian VPS by adding pve-no-subscription repository and proxmox-ve package. Use the repository and keyring lines from Proxmox current documentation. URL wey you copy from old blog post fit make the installation fail. Before you spend evening on the networking wey dey below, decide whether Proxmox make sense at all for rented hardware. the cost and capability comparison between Proxmox box for house and rented VPS na the version of this question wey don already do the power and hardware calculation.
The packages no be the hard part. Proxmox expect vmbr0 to bridge to physical NIC, and this enter the MAC-filtering problem wey we mention above. The setup wey dey work for VPS na NAT'd or routed vmbr0 without physical port attached. Guests dey for private range, while DNAT rules or reverse proxy for the host handle anything wey public. If the public-facing services na containers instead of VMs, Traefik wey dey front multiple apps from one Docker Compose file handle the same routing work with automatic certificates. Take snapshot of /etc/network/interfaces first. Bad bridge definition fit lock you out of machine wey you fit no get console access to.
Performance, wey talk true
Nested dey slower pass single-level, and the reason specific, no be general: the cost dey for exits and address translation, no be for normal instructions. When EPT/NPT dey available, L0 dey combine L1 page tables for L2 and im own page tables into one shadow table, so TLB hit dey run at hardware speed. TLB miss cost more: hardware go walk through the guest page table and shadow table together, and every change wey L1 make to im own tables dey force an exit make L0 fit sync the shadow table again. The expensive part na every operation wey comot guest mode, like I/O, timer interrupts, MMIO, and inter-processor interrupts, because L0 dey handle L2 exit and e fit reflect am back through L1. CPU-bound work with small working set dey look almost like native speed; large in-memory working sets dey pay for TLB misses, while anything wey depend mainly on syscalls, packets, and disk I/O go feel the layers.
So: use virtio devices everywhere. And your qcow2 file dey live for disk wey provider don already virtualize, with two thin-provisioning layers stacked. For this setup, cache=none for the guest disk stops the same blocks from dey inside two page caches at the same time. No benchmark numbers dey here: measure your own workload for your own instance.
Wahala wey fit happen, and strings wey you go see
INFO: /dev/kvm does not exist / KVM acceleration can NOT be used from kvm-ok. Either module no load, or flag no dey exposed. Check /proc/cpuinfo first.
kvm: disabled by bios for dmesg. For bare metal, change VT-x/SVM toggle for firmware. Inside VPS, e mean say L0 no dey give you the extensions, and nothing wey you type for guest go change that.
modprobe: ERROR: could not insert 'kvm_intel': Operation not supported. CPU wey your kernel dey see no get vmx, and na L0 decision again.
Could not access KVM kernel module: Permission denied. Na permissions cause am, no be hardware. ls -l /dev/kvm suppose show group kvm, mode 660; add yourself to that group and start fresh login shell, because group membership no apply to session wey don already dey run.
kvm: Device or resource busy when QEMU start. Another hypervisor module dey hold CPU: run lsmod, look for vboxdrv or VMware modules together with kvm_intel, then unload the one wey you no want.
/var/run/libvirt/libvirt-sock: No such file or directory from virsh. Daemon don stop: sudo systemctl enable --now libvirtd.
Proxmox: KVM virtualisation configured, but not available. Guest get KVM acceleration enabled for host wey no fit provide am. Fix nesting, or disable am and accept emulation.
Android emulator: x86_64 emulation currently requires hardware acceleration! /dev/kvm again, usually na group issue.
No error at all, and everything is glacial. QEMU wey no get accelerator flag go fall back to TCG, wey be software emulator. E correct, but e slow; boot wey suppose take seconds fit take minutes. Pass -accel kvm explicitly, so QEMU go stop with error instead of quietly doing emulation.
A guest vanishes mid-run. Check dmesg for Out of memory: Killed process ... qemu-system-x86_64. L2 guest na process for L1, and OOM killer dey treat am like any other process. L2 RAM dey come from L1 fixed allocation; e no fit borrow from host.
How to run am: backups, upgrades, limits
Backups. If you copy qcow2 file wey guest still dey use, image fit no consistent, because guest still dey write while you dey read. You fit either run virsh shutdown guest1, wait until virsh domstate guest1 reports shut off (shutdown command fit return while guest still dey stop), then copy am; or take external snapshot (virsh snapshot-create-as guest1 snap1 --disk-only --atomic), so writes go enter overlay while you copy the base wey no dey change, then merge am back with virsh blockcommit guest1 vda --active --pivot. Move the copies go outside the VPS. Snapshot wey dey the same disk no protect against anything.
Upgrades. apt full-upgrade installs new kvm_intel/kvm_amd modules, but kernel wey dey run still dey use the old ones until you reboot. Keep the previous kernel installed, and run kvm-ok again after every kernel change. If host come back without vmx, you fit restore am with just one boot entry.
Where this stops scaling. One public IP mean say every L2 service dey reach internet through proxy or DNAT rule for L1. Live migration no dey available. When CPU contention happen, nested exit path na the first place wey go feel am. Hypervisor wey get several guests na machine wey you don already use up its RAM. Nested VMs no fit use overcommit to escape fixed allocation. When lab pass this size, no be taller nested stack be the answer. Use dedicated box instead, where you be L0 and none of these limits apply.
FAQ
I need nested virtualization to run Docker on a VPS?
No. Containers dey share your VPS kernel and dem no ever open /dev/kvm, so ordinary instance wey no get vmx or svm flag fit run Docker and Docker Compose well. Nesting only matter when you want second kernel: Proxmox lab, Windows guest, Firecracker microVMs, Android emulator, or CI runners wey dey boot VM images.
How I fit check whether my VPS support nested virtualization?
Run grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u, then kvm-ok from cpu-checker package. Usable instance go print vmx (Intel) or svm (AMD), kvm-ok go report KVM acceleration can be used, and /dev/kvm go dey with group kvm and mode 660. Ignore /sys/module/kvm_intel/parameters/nested for this question, because that file describe your own KVM module, no be wetin provider hypervisor expose to you.
Why most VPS providers dey disable nested virtualization?
Exposing vmx mean say provider dey give guest CPU model wey carry the flag. Guest wey depend on those CPU features no fit live-migrate go machine wey CPU no get dem. Provider wey dey drain nodes by moving customers around go lose that flexibility. The nested VMX/SVM code paths still get long CVE history. Some hosts dey enable am per-VM when you request am, while others document nesting as plan feature.
My nested VM no get network for public bridge. Wetin dey wrong?
Provider switch dey drop frames from MAC address wey e never lease to you. So L2 guest wey bridge onto public NIC dey send ARP, but e no dey hear any reply. Stop debugging br0. Use libvirt NAT default network (virbr0, 192.168.122.0/24), give guest static lease, then publish anything public through reverse proxy or DNAT rule for the VPS itself.
How much slower nested VM dey?
The cost dey show for VM exits and address translation. When EPT/NPT dey active, instructions and TLB hits inside L2 dey run at hardware speed. But TLB miss go walk through extra page tables, while I/O, timer interrupts, MMIO and IPIs dey handled by L0 and fit bounce back through L1. CPU-bound work wey get small working set fit near native speed. Large in-memory working sets and workloads wey heavy on syscalls, packets, or disk go feel every layer. Use virtio devices everywhere and cache=none for guest disks, then measure your own workload.