Virtualizzazione annidata su VPS: puoi usare Proxmox?
Molti provider VPS nascondono il flag vmx. Verificalo con kvm-ok in un minuto e scopri se puoi usare KVM o Proxmox, inclusi gli errori esatti.
La risposta breve
La virtualizzazione annidata consiste nell'eseguire un hypervisor all'interno di una macchina virtuale: il tuo VPS è già un guest e vuoi che ospiti a sua volta altri guest. Funziona solo se l'hypervisor del provider espone esplicitamente alla tua istanza le estensioni di virtualizzazione della CPU. Controlla /proc/cpuinfo per il flag vmx (Intel) o svm (AMD). Se non compare nessuno dei due, nessuna configurazione eseguita all'interno del VPS può risolvere il problema.
Prima è importante chiarire un'aspettativa: Docker non richiede nulla di tutto questo. I container condividono il kernel del VPS e non usano mai /dev/kvm. Se l'obiettivo reale è "eseguire diversi servizi in container sul mio server", hai già tutto ciò che serve. La virtualizzazione annidata è utile quando vuoi un secondo kernel, un laboratorio Proxmox, un guest Windows, microVM Firecracker, un emulatore Android, un ambiente di test Kubernetes composto da VM reali oppure runner CI che avviano immagini di macchine virtuali.
Cosa viene effettivamente annidato
Tre livelli:
- L0, l'hypervisor del provider, sull'hardware fisico. Non hai accesso a questo livello.
- L1, il tuo VPS. Per L0 è semplicemente un guest.
- L2, la VM che vuoi eseguire all'interno del tuo VPS.
La virtualizzazione hardware usa VT-x (il flag vmx) più EPT sui processori Intel, oppure AMD-V / SVM (svm) più RVI/NPT sui processori AMD. Un hypervisor usa queste istruzioni per entrare nella modalità guest e consentire alla CPU di consultare contemporaneamente due tabelle delle pagine.
Nessuna delle due tecnologie è stata progettata per essere rientrante, quindi l'annidamento viene emulato: quando L1 esegue un'istruzione VMX, questa genera un trap verso L0, che gestisce per conto di L1 le strutture shadow per L2. KVM esegue bene questa operazione, ma è L0 a svolgere lavoro aggiuntivo a ogni exit. Per questo il provider deve abilitare esplicitamente la funzionalità.
Per una L2 accelerata devono essere vere entrambe le condizioni:
- Il modulo KVM di L0 deve essere caricato con
nested=1. - L0 deve fornire al tuo VPS un modello di CPU che esponga il flag:
<cpu mode='host-passthrough'/>in libvirt,cpu: hostin Proxmox,-cpu hostin QEMU puro. Un modello emulato generico (qemu64,kvm64) nascondevmxanche quando l'annidamento è abilitato globalmente.
Verifica il tuo VPS in un minuto
# 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/kvmUn'istanza utilizzabile restituisce vmx o svm, kvm-ok indica KVM acceleration can be used e /dev/kvm esiste con modalità root:kvm 660. Se il flag è presente ma il nodo del dispositivo non esiste, carica manualmente il modulo e leggi il log del kernel:
sudo modprobe kvm_intel # or kvm_amd
sudo dmesg | tail -n 20Un file viene citato continuamente e spesso interpretato in modo errato:
cat /sys/module/kvm_intel/parameters/nested # Y or NNel tuo VPS, questa è l'impostazione del tuo modulo KVM e determina se un guest L2 può annidare un terzo livello. Non indica se L0 ha abilitato il nesting per te: a questo rispondono /proc/cpuinfo e kvm-ok. Il parametro nested è quello che imposti su una macchina di tua proprietà:
echo 'options kvm_intel nested=1' | sudo tee /etc/modprobe.d/kvm-nested.conf
sudo modprobe -r kvm_intel && sudo modprobe kvm_intelLa rimozione del modulo viene rifiutata mentre è in esecuzione una VM; arresta quindi prima i guest.
Perché la maggior parte degli host VPS lo lascia disabilitato
- Live migration. Fornirti
vmxsignifica esporre un modello CPU che include il flag. Un guest che dipende da queste funzionalità della CPU non può essere migrato in sicurezza su una macchina la cui CPU ne è priva. Un host che svuota i nodi migrando i clienti rinuncia a questa possibilità nel momento in cui abilita il nesting. - Superficie di attacco. I percorsi VMX/SVM annidati sono tra i componenti più complessi del livello di virtualizzazione del kernel, come dimostra anche la relativa cronologia delle CVE.
- L0 potrebbe non essere KVM. Se
systemd-detect-virtrestituiscevmware,xenomicrosoft, le regole del nesting sono quelle dello stack in uso, non quelle di KVM.
Se l'istanza non mostra il flag, chiedi al supporto (alcuni provider lo abilitano per singola VM), scegli un piano che documenti il supporto al nesting oppure passa a un server dedicato. Il resto della procedura presuppone un accesso root a una macchina che mostra il flag.
Eseguire un guest L2 con 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'Non è necessaria una sessione grafica. L’installazione tramite console seriale richiede tempo, quindi avviala all’interno di una shell persistente: lo stesso flusso di lavoro tmux che mantiene attive le sessioni di Claude Code su un VPS mantiene collegata una console virt-install anche dopo l’interruzione della connessione SSH. Se --os-variant debian13 viene rifiutato, la versione di osinfo-db è precedente alla release che lo supporta: esegui osinfo-query os e scegli un nome esistente. --cpu host-passthrough inoltra vmx verso L2, ed è necessario solo se L2 deve a sua volta eseguire la virtualizzazione. Rendi il guest sicuro al boot con virsh autostart guest1.
Il bus virtio per il disco e la NIC non è un dettaglio: i dispositivi IDE ed e1000 emulati causano un’uscita verso l’hypervisor molto più spesso delle code virtio e, con il nesting, ogni uscita viene gestita due volte.
Networking: the part tutorials skip
Your VPS has one public IP and sits behind a fabric that filters unknown MAC addresses. Two consequences follow.
Bridging L2 guests onto the public network usually will not work. Put br0 on the public NIC, give the guest its own MAC, and you will watch ARP go out and nothing come back, the provider's switch drops frames from a MAC it never leased you. If that is your symptom, stop debugging the bridge; this is the mechanism.
Use the NAT network instead. libvirt ships default: virbr0, 192.168.122.0/24, dnsmasq leases, outbound working immediately. For inbound, terminate TLS on L1 and proxy in, 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 a static lease first (virsh net-edit default) so the address in that proxy_pass stays put.
Management interfaces stay off the internet: VNC on 5900 and the Proxmox web UI on 8006 belong on loopback, reached over an SSH tunnel (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) or across a self-hosted WireGuard VPN into the VPS, which puts 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 right after you enable ufw, the usual culprit is DEFAULT_FORWARD_POLICY="DROP" in /etc/default/ufw, set it to ACCEPT and reload ufw.
Proxmox su un VPS
Proxmox VE 9 si basa su Debian 13, quindi può essere installato su un VPS Debian aggiungendo il repository pve-no-subscription e il pacchetto proxmox-ve. Usa le righe relative al repository e al keyring della documentazione ufficiale aggiornata di Proxmox. Un URL copiato da un vecchio articolo di blog interrompe l'installazione. Prima di dedicare un'intera serata alla configurazione di rete descritta di seguito, conviene stabilire se Proxmox sia adatto all'hardware noleggiato. Il confronto tra costi e caratteristiche di un server Proxmox domestico e di un VPS noleggiato fornisce una risposta considerando già consumi energetici e dotazione hardware.
I pacchetti non sono l'aspetto più complesso. Proxmox si aspetta che vmbr0 sia collegato a una NIC fisica, ma questo porta direttamente al problema del filtro MAC descritto sopra. Su un VPS funziona invece una vmbr0 con NAT o routing, senza alcuna porta fisica associata, con i guest su una rete privata e regole DNAT o un reverse proxy sull'host per i servizi pubblici. Quando i servizi esposti pubblicamente sono container anziché VM, Traefik per pubblicare più applicazioni da un unico file Docker Compose svolge lo stesso compito di routing e gestisce automaticamente i certificati. Crea prima uno snapshot /etc/network/interfaces: una definizione errata del bridge può impedirti di accedere a una macchina la cui console potrebbe non essere disponibile.
Prestazioni, senza semplificazioni
Il nesting è più lento rispetto a un solo livello, e il meccanismo è specifico, non generalizzato: il costo non ricade sull'accesso alla memoria, ma sulle exit. Quando EPT/NPT è disponibile, L0 mantiene le shadow page table per L2 e le normali letture dalla memoria vengono eseguite alla velocità dell'hardware. Diventa costosa ogni operazione che fa uscire dalla modalità guest: I/O, interrupt del timer, MMIO e interrupt interprocessore, perché una exit di L2 viene gestita da L0 e può essere riflessa nuovamente attraverso L1. Le elaborazioni CPU-bound sui dati già presenti nella RAM hanno prestazioni vicine a quelle native; le operazioni dominate da syscall, pacchetti e I/O del disco risentono dei livelli di virtualizzazione.
Quindi: dispositivi virtio ovunque. Inoltre, il file qcow2 risiede su un disco che il provider ha già virtualizzato. Si accumulano due livelli di thin provisioning, mentre cache=none sul disco guest impedisce che gli stessi blocchi rimangano contemporaneamente in due page cache. Qui non riportiamo numeri di benchmark: misura il tuo carico di lavoro sulla tua istanza.
Modalità di errore e stringhe visualizzate
INFO: /dev/kvm does not exist / KVM acceleration can NOT be used da kvm-ok. Il modulo non è caricato oppure il flag non è esposto. Controllare prima /proc/cpuinfo.
kvm: disabled by bios in dmesg. Su bare metal, attivare l'opzione VT-x/SVM nel firmware. All'interno di un VPS, significa che L0 non espone le estensioni; nessun comando eseguito nel guest può modificare questa situazione.
modprobe: ERROR: could not insert 'kvm_intel': Operation not supported. La CPU rilevata dal kernel non dispone di vmx. Anche in questo caso, la decisione spetta a L0.
Could not access KVM kernel module: Permission denied. Il problema riguarda i permessi, non l'hardware. ls -l /dev/kvm dovrebbe mostrare il gruppo kvm e la modalità 660; aggiungere il proprio account a quel gruppo e avviare una nuova shell di login, perché l'appartenenza al gruppo non viene applicata a una sessione già in esecuzione.
kvm: Device or resource busy all'avvio di QEMU. Un altro modulo di virtualizzazione sta utilizzando la CPU: eseguire lsmod, cercare vboxdrv o i moduli VMware insieme a kvm_intel e scaricare il modulo non desiderato.
/var/run/libvirt/libvirt-sock: No such file or directory da virsh. Il demone è arrestato: sudo systemctl enable --now libvirtd.
Proxmox: KVM virtualisation configured, but not available. Un guest ha l'accelerazione KVM attivata su un host che non può fornirla. Correggere la configurazione della virtualizzazione annidata oppure disattivare l'opzione e accettare l'emulazione.
Emulatore Android: x86_64 emulation currently requires hardware acceleration! Anche in questo caso, /dev/kvm, di solito per un problema di gruppo.
Nessun errore e prestazioni estremamente lente. QEMU, se non riceve alcun flag di accelerazione, passa a TCG, il suo emulatore software. Il funzionamento è corretto, ma lento: un avvio che normalmente richiede secondi può richiedere minuti. Passare esplicitamente -accel kvm, in modo che QEMU termini con un errore invece di eseguire l'emulazione senza segnalarlo.
Un guest scompare durante l'esecuzione. Cercare in dmesg la presenza di Out of memory: Killed process ... qemu-system-x86_64. Un guest L2 è un processo su L1 e l'OOM killer lo tratta come qualsiasi altro processo. La RAM di L2 viene sottratta all'allocazione fissa di L1; non può essere presa in prestito dall'host.
Gestione: backup, aggiornamenti e limiti
Backup. Copiare il file qcow2 di un guest in esecuzione produce un'immagine corrotta. Arresta il guest con virsh shutdown guest1 e copialo, oppure crea uno snapshot esterno (virsh snapshot-create-as guest1 snap1 --disk-only --atomic), in modo che le scritture vengano reindirizzate a un overlay mentre copi la base ormai statica, quindi incorporalo nuovamente con virsh blockcommit. Trasferisci le copie fuori dal VPS: uno snapshot sullo stesso disco non protegge da alcun guasto del disco.
Aggiornamenti. apt full-upgrade installa nuovi moduli kvm_intel/kvm_amd, ma il kernel in esecuzione continua a usare quelli precedenti finché non riavvii il sistema. Mantieni installato il kernel precedente ed esegui nuovamente kvm-ok dopo ogni modifica al kernel: se un host si riavvia senza vmx, basta un'opzione di avvio per ripristinarne il funzionamento.
Dove questa soluzione non è più scalabile. Un singolo IP pubblico significa che ogni servizio L2 raggiunge Internet tramite un proxy o una regola DNAT su L1. La migrazione a caldo non è disponibile. In condizioni di contesa sulla CPU, il percorso di uscita annidato è il primo a risentirne. Inoltre, un hypervisor con più guest è una macchina la cui RAM è già stata allocata: le VM annidate non possono superare il limite di un'allocazione fissa. Quando un laboratorio supera questi limiti, la soluzione non è aggiungere un altro livello alla struttura annidata, ma usare un server dedicato in cui sei L0 e nessuna di queste limitazioni si applica.
FAQ
Devo usare la virtualizzazione annidata per eseguire Docker su un VPS?
No. I container condividono il kernel del VPS e non aprono mai /dev/kvm, quindi un'istanza standard senza il flag vmx o svm esegue correttamente Docker e Docker Compose. La virtualizzazione annidata serve solo quando è necessario un secondo kernel: per un laboratorio Proxmox, un guest Windows, microVM Firecracker, un emulatore Android o runner CI che avviano immagini VM.
Come verifico se il mio VPS supporta la virtualizzazione annidata?
Esegui grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u, quindi kvm-ok dal pacchetto cpu-checker. Un'istanza utilizzabile mostra vmx (Intel) oppure svm (AMD); kvm-ok restituisce KVM acceleration can be used e /dev/kvm esiste con il gruppo kvm e la modalità 660. Ignora /sys/module/kvm_intel/parameters/nested per questa verifica: quel file descrive il modulo KVM del sistema, non ciò che l'hypervisor del provider ha esposto al guest.
Perché la maggior parte dei provider VPS disabilita la virtualizzazione annidata?
L'esposizione di vmx richiede di fornire al guest un modello CPU che include quel flag. Un guest che dipende da queste funzionalità CPU non può essere migrato a caldo su una macchina il cui processore ne è privo. Un provider che svuota i nodi spostando i clienti da una macchina all'altra deve quindi rinunciare a questa possibilità. Anche i percorsi di codice VMX/SVM annidati hanno una lunga storia di CVE. Alcuni host la abilitano comunque per singola VM su richiesta; altri documentano la virtualizzazione annidata come funzionalità del piano.
La mia VM annidata non ha rete sul bridge pubblico. Qual è il problema?
Lo switch del provider scarta i frame provenienti da un indirizzo MAC che non ti ha assegnato. Di conseguenza, un guest L2 collegato in bridge alla NIC pubblica invia richieste ARP ma non riceve risposta. Smetti di eseguire il troubleshooting di br0. Usa invece la rete NAT di libvirt default (virbr0, 192.168.122.0/24), assegna al guest una lease statica e pubblica i servizi tramite un reverse proxy o una regola DNAT direttamente sul VPS.
Quanto è più lenta una VM annidata?
Il costo si manifesta nelle uscite dalla VM, non negli accessi alla memoria. Con EPT/NPT attivo, le normali operazioni di lettura e scrittura all'interno di L2 vengono eseguite alla velocità dell'hardware. Le operazioni di I/O, gli interrupt del timer, le operazioni MMIO e gli IPI vengono invece gestiti da L0 e possono essere reinviati attraverso L1. I carichi CPU che lavorano su dati già presenti in RAM hanno prestazioni vicine a quelle native. I carichi intensivi di syscall, pacchetti o disco risentono di ogni livello. Usa dispositivi virtio ovunque e cache=none sui dischi guest, quindi misura il comportamento del tuo carico di lavoro.