Proxmox su VPS: serve la virtualizzazione annidata?
Molti provider VPS nascondono il flag vmx. Verificalo con kvm-ok in un minuto e scopri gli errori esatti prima di usare KVM o guest Proxmox.
La risposta breve
La virtualizzazione annidata consiste nell'eseguire un hypervisor all'interno di una macchina virtuale: il VPS è già un guest e si vuole usarlo per ospitare a sua volta altri guest. Funziona soltanto se l'hypervisor del provider espone esplicitamente all'istanza le estensioni di virtualizzazione della CPU. Controllare /proc/cpuinfo per verificare la presenza del 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 punto: Docker non richiede nulla di tutto questo. I container condividono il kernel del VPS e non accedono mai a /dev/kvm. Se l'obiettivo reale è "eseguire diversi servizi in container sul server", si dispone già di tutto il necessario. La virtualizzazione annidata è utile quando serve un secondo kernel, un laboratorio Proxmox, un guest Windows, microVM Firecracker, un emulatore Android, un ambiente di test Kubernetes composto da vere VM oppure runner CI che avviano immagini di macchine virtuali.
Cosa viene effettivamente annidato
Tre livelli:
- L0, l'hypervisor del provider, sul server fisico. Non hai accesso a questo livello.
- L1, il tuo VPS. Per L0 è soltanto un guest.
- L2, la VM che vuoi eseguire all'interno del tuo VPS.
La virtualizzazione hardware usa VT-x (il flag vmx) e EPT su Intel, oppure AMD-V / SVM (svm) e RVI/NPT su AMD. Un hypervisor usa queste istruzioni per entrare nella modalità guest e consentire alla CPU di attraversare 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 come VMLAUNCH o VMRESUME, l'esecuzione passa a L0, che gestisce per conto di L1 le strutture shadow di L2. Sulle CPU che supportano il VMCS shadowing, le istruzioni VMREAD e VMWRITE di L1 possono essere gestite senza un'uscita, riducendo gran parte di questo traffico, ma non il resto. KVM lo gestisce bene, ma è L0 a svolgere lavoro aggiuntivo a ogni uscita. Per questo il provider deve abilitarlo esplicitamente.
Quando L0 usa KVM, per ottenere un L2 accelerato devono essere vere entrambe queste condizioni:
- Il modulo KVM di L0 è caricato con
nested=1. - L0 assegna al tuo VPS un modello di CPU che espone il flag:
<cpu mode='host-passthrough'/>in libvirt,cpu: hostin Proxmox,-cpu hostin QEMU senza wrapper. Un modello emulato generico (qemu64,kvm64) nascondevmxanche quando l'annidamento è abilitato globalmente.
Gli altri hypervisor usano opzioni proprie. Hyper-V, ad esempio, emula le estensioni di virtualizzazione per un hypervisor annidato all'interno delle proprie VM, ma solo nelle VM in cui l'annidamento è stato abilitato singolarmente.
Controlla 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 mostra vmx o svm, kvm-ok restituisce 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 questa domanda rispondono /proc/cpuinfo e kvm-ok. Il parametro nested è l'impostazione che devi configurare 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, quindi arresta prima i guest. Se la macchina è un host Proxmox, l'abilitazione della virtualizzazione annidata in Proxmox VE 9 descrive la stessa modifica a modprobe.d e l'impostazione cpu: host per VM che rende visibile il flag all'interno di un guest.
Perché la maggior parte dei provider VPS lo lascia disabilitato
- Migrazione live. Esporre
vmxsignifica fornire un modello di CPU che include quel flag. Una macchina virtuale che dipende da queste funzionalità della CPU non può essere migrata in sicurezza su un host con una CPU che ne è priva. Un provider che svuota i nodi migrando i clienti rinuncia a questa possibilità non appena abilita il nesting. - Superficie di attacco. I percorsi nested VMX/SVM sono tra i componenti più complessi del livello di virtualizzazione del kernel e hanno una cronologia di CVE coerente con tale complessità.
- L0 potrebbe non essere KVM. Se
systemd-detect-virtrestituiscevmware,xenomicrosoft, le regole del nesting dipendono da quello stack, non da KVM.
L'istanza non espone il flag? Chiedi al supporto, perché 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 serve una sessione grafica. L'installazione seriale richiede tempo, quindi avviatela all'interno di una shell persistente: lo stesso flusso di lavoro tmux che mantiene attive le sessioni di Claude Code su un VPS mantiene una console virt-install collegata anche se la connessione SSH cade. Se --os-variant debian13 viene rifiutato, il vostro osinfo-db è precedente a questa release; eseguite osinfo-query os e scegliete un nome disponibile. --cpu host-passthrough inoltra vmx verso L2, ma è necessario solo se L2 deve a sua volta eseguire la virtualizzazione. Rendete il guest sicuro al riavvio con virsh autostart guest1.
Il bus virtio per il disco e la scheda di rete non è un dettaglio trascurabile: i dispositivi IDE ed e1000 emulati causano più uscite verso l'hypervisor rispetto alle code virtio e, in un ambiente nested, un'uscita che L0 non può completare autonomamente viene propagata a L1, dove la sua gestione può causare ulteriori uscite.
Rete: la parte che i tutorial omettono
Il tuo VPS ha un solo indirizzo IP pubblico e si trova dietro un’infrastruttura che filtra gli indirizzi MAC sconosciuti. Ne derivano due conseguenze.
Collegare guest L2 alla rete pubblica in genere non funziona. Configura br0 sulla NIC pubblica, assegna al guest un MAC dedicato e vedrai le richieste ARP uscire senza ricevere risposta: lo switch del provider scarta i frame provenienti da un MAC che non ti ha mai assegnato in lease. Se questo è il sintomo, interrompi il troubleshooting del bridge: è il comportamento previsto dal meccanismo.
Usa invece la rete NAT. libvirt include default: virbr0, 192.168.122.0/24 e i lease di dnsmasq; il traffico in uscita è subito operativo. Per il traffico in ingresso, termina TLS su L1 e configura il proxy verso l’interno. I percorsi dei certificati riportati di seguito provengono da generazione di un certificato Let's Encrypt con Certbot su 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;
}
}Assegna prima al guest una lease statica (virsh net-edit default), in modo che l'indirizzo in proxy_pass non cambi.
Le interfacce di gestione non devono essere esposte a Internet: VNC sulla porta 5900 e l'interfaccia web di Proxmox sulla porta 8006 devono restare su loopback. Sono raggiungibili tramite un tunnel SSH (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) oppure attraverso una VPN WireGuard self-hosted verso il VPS, che colloca l'intero intervallo di guest 192.168.122.0/24 a un solo hop privato di distanza. Mantieni il firewall restrittivo: sudo ufw allow 22,80,443/tcp, nient'altro. Se i guest perdono la connettività in uscita subito dopo l'attivazione di ufw, la causa più comune è DEFAULT_FORWARD_POLICY="DROP" in /etc/default/ufw. Impostalo su ACCEPT e ricarica ufw.
Proxmox su un VPS
Proxmox VE 9 è basato su Debian 13, quindi si installa su un VPS Debian aggiungendo il repository pve-no-subscription e il pacchetto proxmox-ve. Recupera le righe relative al repository e al keyring dalla documentazione aggiornata di Proxmox. Un URL copiato da un vecchio articolo di blog può interrompere l'installazione. Prima di dedicare una serata alla configurazione di rete descritta di seguito, conviene stabilire se Proxmox sia adatto all'hardware noleggiato. Il confronto tra costi e funzionalità di un server Proxmox domestico e di un VPS noleggiato risponde a questa domanda includendo già i calcoli relativi a consumi elettrici e hardware.
I pacchetti non sono la parte più complessa. Proxmox si aspetta che vmbr0 sia collegato in bridge a una NIC fisica, ma questo porta direttamente al problema del filtro sugli indirizzi MAC descritto sopra. Su un VPS funziona una configurazione con vmbr0 in NAT o instradata, senza porte fisiche associate, 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 come frontend per più applicazioni da un unico file Docker Compose svolge la stessa funzione di routing con certificati automatici. Crea prima uno snapshot di /etc/network/interfaces: una definizione di bridge errata può impedirti di accedere a una macchina la cui console potrebbe non essere disponibile.
Prestazioni, descritte con onestà
La virtualizzazione annidata è più lenta di quella a un solo livello, e il meccanismo è specifico, non diffuso: il costo riguarda le uscite dalla modalità guest e la traduzione degli indirizzi, non le istruzioni ordinarie. Quando è presente EPT/NPT, L0 combina le tabelle delle pagine di L1 per L2 e le proprie in un'unica tabella shadow, quindi un hit nella TLB viene eseguito alla velocità dell'hardware. Un miss nella TLB costa di più: l'hardware percorre contemporaneamente la tabella delle pagine del guest e la tabella shadow, e ogni modifica apportata da L1 alle proprie tabelle forza un'uscita, in modo che L0 possa riallineare la tabella shadow. Il costo aumenta per ogni operazione che fa uscire dalla modalità guest: I/O, interrupt del timer, MMIO e interrupt interprocessore. Questo accade perché un'uscita da L2 viene gestita da L0 e può essere riflessa nuovamente attraverso L1. I carichi vincolati dalla CPU con un working set ridotto hanno prestazioni vicine a quelle native; i working set di grandi dimensioni risentono dei miss nella TLB, mentre qualsiasi carico dominato da syscall, pacchetti e I/O su disco risente dei vari livelli.
Quindi: dispositivi virtio ovunque. Inoltre, il file qcow2 risiede su un disco che il provider ha già virtualizzato: si sovrappongono due livelli di thin provisioning e 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 una VPS significa che L0 non espone le estensioni e che nessun comando eseguito nel guest può modificare la 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 utente a quel gruppo e avviare una nuova login shell, perché l'appartenenza al gruppo non si applica a una sessione già in esecuzione.
kvm: Device or resource busy all'avvio di QEMU. Un altro modulo hypervisor sta utilizzando la CPU: eseguire lsmod, cercare vboxdrv o i moduli VMware insieme a kvm_intel e rimuovere il modulo non desiderato.
/var/run/libvirt/libvirt-sock: No such file or directory da virsh. Il daemon non è in esecuzione: 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 del nesting 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 relativo al gruppo.
Nessun errore e prestazioni estremamente lente. QEMU, se non riceve un flag di accelerazione, esegue il fallback a TCG, il suo emulatore software. Il funzionamento è corretto, ma le prestazioni sono basse: un avvio che richiede pochi secondi può richiedere diversi minuti. Passare esplicitamente -accel kvm, in modo che QEMU si interrompa 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 gestisce come qualsiasi altro processo. La RAM di L2 viene sottratta all'allocazione fissa di L1; non può utilizzare memoria aggiuntiva dall'host.
Gestione: backup, aggiornamenti e limiti
Backup. Copiare il file qcow2 di un guest in esecuzione può produrre un'immagine incoerente, perché il guest continua a scrivere mentre il file viene letto. Eseguire virsh shutdown guest1, attendere che virsh domstate guest1 riporti shut off (il comando di arresto può restituire il controllo mentre il guest è ancora in fase di arresto), quindi copiare il file. In alternativa, creare uno snapshot esterno (virsh snapshot-create-as guest1 snap1 --disk-only --atomic): le scritture vengono reindirizzate verso un overlay mentre si copia la base ormai statica, che può poi essere riunita con virsh blockcommit guest1 vda --active --pivot. Trasferire le copie al di fuori del 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 fino al riavvio. Mantenere installato il kernel precedente ed eseguire di nuovo kvm-ok dopo ogni modifica al kernel: se l'host si avvia senza vmx, sarà sufficiente selezionare una voce di avvio alternativa per ripristinarne il funzionamento.
Dove questa soluzione non è più scalabile. Un unico 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 caso di contesa per la 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 di virtualizzazione annidata, ma usare una macchina dedicata in cui si opera a livello L0 e nessuno di questi vincoli si applica.
FAQ
È necessaria 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 è necessaria solo quando vuoi un secondo kernel: un ambiente di 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 stampa vmx (Intel) o 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 tuo modulo KVM, non ciò che l'hypervisor del provider ha esposto al tuo sistema.
Perché la maggior parte dei provider VPS disabilita la virtualizzazione annidata?
L'esposizione di vmx significa fornire al guest un modello CPU che include il flag. Un guest che dipende da queste funzionalità della CPU non può essere migrato live su una macchina la cui CPU ne è priva. Un provider che svuota i nodi spostando i clienti tra le macchine rinuncia quindi a questa possibilità. Anche i percorsi di codice VMX/SVM annidati hanno una lunga storia di CVE. Alcuni host lo abilitano comunque per singola VM su richiesta, mentre 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 alla NIC pubblica invia richieste ARP ma non riceve risposta. Smetti di eseguire il debug di br0. Usa 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 riguarda le uscite dalla VM e la traduzione degli indirizzi. Con EPT/NPT attivi, le istruzioni e gli hit della TLB all'interno di L2 vengono eseguiti alla velocità dell'hardware. Tuttavia, un TLB miss richiede la scansione di ulteriori tabelle delle pagine, mentre I/O, interrupt del timer, MMIO e IPI vengono gestiti da L0 e possono essere reindirizzati attraverso L1. I carichi vincolati alla CPU con un working set ridotto hanno prestazioni vicine a quelle native. I working set di grandi dimensioni residenti in memoria e i carichi intensivi per syscall, pacchetti o disco risentono di ogni livello. Usa dispositivi virtio ovunque e cache=none sui dischi guest, quindi misura il tuo carico di lavoro.