SSD Nodes Learn
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-07-19

Virtualisation imbriquée sur VPS : KVM/Proxmox

Vérifiez si votre VPS expose VT-x ou AMD-V, activez le KVM imbriqué, puis lancez Proxmox ou Windows dans un hyperviseur invité, avec les erreurs fréquentes.

La réponse courte

La virtualisation imbriquée, c'est un hyperviseur qui tourne dans une machine virtuelle : votre VPS est déjà un invité, et vous voulez qu'il héberge à son tour ses propres invités. Cela ne fonctionne que si l'hyperviseur de votre hébergeur expose volontairement les extensions de virtualisation du processeur à votre instance. Vérifiez dans /proc/cpuinfo la présence du drapeau vmx (Intel) ou svm (AMD) ; si aucun n'apparaît, rien de ce que vous configurez dans le VPS n'y changera quoi que ce soit.

Une précision d'emblée : Docker n'a besoin de rien de tout cela. Les conteneurs partagent le noyau de votre VPS et ne touchent jamais à /dev/kvm. Si le vrai objectif est « faire tourner plusieurs services en conteneurs sur mon serveur », vous avez déjà tout ce qu'il faut. L'imbrication compte quand vous voulez un second noyau : un labo Proxmox, un invité Windows, des microVM Firecracker, un émulateur Android, un banc d'essai Kubernetes fait de vraies VM, ou des runners de CI qui démarrent des images de VM.

Ce qui est réellement imbriqué

Trois couches :

  • L0 : l'hyperviseur de l'hébergeur, sur la machine physique. Vous n'y avez aucun accès.
  • L1 : votre VPS. Pour L0, ce n'est qu'un invité.
  • L2 : la VM que vous voulez faire tourner dans votre VPS.

La virtualisation matérielle, c'est VT-x (le drapeau vmx) plus EPT sur Intel, AMD-V / SVM (svm) plus RVI/NPT sur AMD. Un hyperviseur utilise ces instructions pour entrer en mode invité et pour laisser le processeur parcourir deux tables de pages à la fois.

Ni l'une ni l'autre n'a été conçue pour être réentrante, donc l'imbrication est émulée : quand L1 exécute une instruction VMX, elle est déroutée vers L0, qui maintient les structures fantômes de L2 à la place de L1. KVM le fait bien, mais c'est L0 qui fournit un travail supplémentaire à chaque sortie (exit), ce qui explique pourquoi l'hébergeur doit l'activer explicitement.

Deux conditions doivent être réunies pour un L2 accéléré :

  1. Le module KVM de L0 est chargé avec nested=1.
  2. L0 donne à votre VPS un modèle de processeur qui porte le drapeau : <cpu mode='host-passthrough'/> avec libvirt, cpu: host avec Proxmox, -cpu host avec QEMU brut. Un modèle émulé générique (qemu64, kvm64) masque vmx même quand l'imbrication est activée globalement.

Vérifiez votre VPS en une 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/kvm

Une instance utilisable affiche vmx ou svm, kvm-ok indique KVM acceleration can be used, et /dev/kvm existe en root:kvm avec le mode 660. Si le drapeau est présent mais que le nœud de périphérique ne l'est pas, chargez le module à la main et lisez le journal du noyau :

sudo modprobe kvm_intel     # or kvm_amd
sudo dmesg | tail -n 20

Un fichier est cité en permanence et souvent mal interprété :

cat /sys/module/kvm_intel/parameters/nested   # Y or N

Dans votre VPS, il s'agit du réglage de votre module KVM, et il détermine si un invité L2 pourrait imbriquer un troisième niveau. Il ne dit rien sur le fait que L0 ait activé l'imbrication pour vous : ce sont /proc/cpuinfo et kvm-ok qui répondent à cette question. Le paramètre nested est le réglage que vous définissez sur une machine qui vous appartient entièrement :

echo 'options kvm_intel nested=1' | sudo tee /etc/modprobe.d/kvm-nested.conf
sudo modprobe -r kvm_intel && sudo modprobe kvm_intel

Le retrait du module est refusé tant qu'une VM tourne, donc arrêtez d'abord les invités.

Pourquoi la plupart des hébergeurs VPS le laissent désactivé

  • La migration à chaud (live migration). Vous donner vmx implique d'exposer un modèle de processeur qui porte le drapeau, et un invité qui dépend de ces fonctions du processeur ne peut pas être migré en toute sécurité vers une machine dont le processeur en est dépourvu. Un hébergeur qui vide ses nœuds en migrant ses clients y renonce dès l'instant où il active l'imbrication.
  • La surface d'attaque. Les chemins de code VMX/SVM imbriqués comptent parmi les plus complexes de la couche de virtualisation du noyau, avec un historique de CVE (vulnérabilités connues répertoriées) à l'avenant.
  • L0 n'est peut-être pas KVM. Si systemd-detect-virt affiche vmware, xen ou microsoft, les règles d'imbrication sont celles de cette pile, pas celles de KVM.

Pas de drapeau sur votre instance ? Demandez au support (certains l'activent par VM), choisissez une offre qui documente l'imbrication, ou passez sur une machine dédiée. La suite suppose un accès root sur une machine qui affiche le drapeau.

Faire tourner un invité L2 avec 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'

Aucune session graphique n'est nécessaire. Une installation en série dure un moment, donc lancez-la dans un shell persistant : le même flux de travail tmux qui garde les sessions Claude Code actives sur un VPS maintient la console virt-install attachée malgré une connexion SSH interrompue. Si --os-variant debian13 est rejeté, votre osinfo-db est antérieur à cette version : lancez osinfo-query os et choisissez un nom qui existe. --cpu host-passthrough transmet vmx jusque dans L2, ce qui n'est utile que si L2 doit à son tour virtualiser. Rendez l'invité résistant au redémarrage avec virsh autostart guest1.

Le bus virtio sur le disque et la carte réseau n'est pas décoratif : les périphériques émulés IDE et e1000 se déroutent vers l'hyperviseur bien plus souvent que les files virtio, et sous imbrication chaque déroutement est payé deux fois.

Réseau : la partie que les tutoriels sautent

Votre VPS possède une seule IP publique et se trouve derrière une infrastructure qui filtre les adresses MAC inconnues. Deux conséquences en découlent.

Ponter des invités L2 sur le réseau public ne fonctionne généralement pas. Mettez br0 sur la carte réseau publique, donnez à l'invité sa propre adresse MAC, et vous verrez les requêtes ARP partir sans réponse : le commutateur de l'hébergeur rejette les trames venant d'une MAC qu'il ne vous a jamais attribuée. Si c'est votre symptôme, arrêtez de déboguer le pont ; c'est là le mécanisme.

Utilisez plutôt le réseau NAT. libvirt fournit default : virbr0, 192.168.122.0/24, des baux dnsmasq, et le trafic sortant fonctionne immédiatement. Pour le trafic entrant, terminez le TLS sur L1 et faites suivre via un proxy : les chemins de certificat ci-dessous proviennent de l'émission d'un certificat Let's Encrypt avec Certbot sur 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;
    }
}

Donnez d'abord un bail statique à l'invité (virsh net-edit default) pour que l'adresse dans ce proxy_pass reste fixe.

Les interfaces d'administration restent hors d'Internet : VNC sur le port 5900 et l'interface web de Proxmox sur le port 8006 doivent rester sur la boucle locale (loopback), accessibles via un tunnel SSH (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) ou à travers un VPN WireGuard auto-hébergé vers le VPS, qui place toute la plage d'invités 192.168.122.0/24 à un saut privé de distance. Gardez le pare-feu restreint : sudo ufw allow 22,80,443/tcp, rien d'autre. Si les invités perdent la connectivité sortante juste après l'activation d'ufw, le coupable habituel est DEFAULT_FORWARD_POLICY="DROP" dans /etc/default/ufw : passez-le à ACCEPT et rechargez ufw.

Proxmox sur un VPS

Proxmox VE 9 repose sur Debian 13, il s'installe donc sur un VPS Debian en ajoutant le dépôt pve-no-subscription et le paquet proxmox-ve. Reprenez les lignes de dépôt et de trousseau de clés depuis la documentation à jour de Proxmox : une URL copiée d'un vieil article de blog casse l'installation.

Les paquets ne sont pas le plus dur. Proxmox s'attend à un vmbr0 ponté sur une carte réseau physique, ce qui mène droit à l'impasse du filtrage MAC évoquée plus haut. La configuration qui fonctionne sur un VPS, c'est un vmbr0 en NAT ou routé, sans port physique rattaché, des invités sur une plage privée, et des règles DNAT ou un reverse proxy sur l'hôte pour tout ce qui est public. Lorsque les services exposés sont des conteneurs plutôt que des VM, Traefik en frontal de plusieurs applications depuis un seul fichier Docker Compose assure le même travail de routage avec des certificats automatiques. Faites d'abord une copie de /etc/network/interfaces : une mauvaise définition de pont vous verrouille hors d'une machine dont vous n'avez peut-être pas la console.

Performances, dites honnêtement

L'imbrication est plus lente qu'un seul niveau, et le mécanisme est précis plutôt que diffus : le coût ne se trouve pas dans l'accès mémoire, mais dans les sorties (exits). Avec EPT/NPT présents, L0 maintient des tables de pages fantômes pour L2 et les lectures mémoire ordinaires tournent à la vitesse du matériel. Ce qui devient coûteux, c'est chaque opération qui quitte le mode invité : E/S, interruptions d'horloge, MMIO, interruptions inter-processeurs, car une sortie de L2 est traitée par L0 et peut être répercutée à travers L1. Le travail limité par le processeur sur des données déjà en RAM reste proche du natif ; tout ce qui est dominé par les appels système, les paquets et les E/S disque ressent les couches.

Donc : des périphériques virtio partout. Et votre fichier qcow2 réside sur un disque que l'hébergeur a déjà virtualisé, soit deux couches de provisionnement fin empilées, où cache=none sur le disque de l'invité évite que les mêmes blocs occupent deux caches de pages à la fois. Pas de chiffres de benchmark ici : mesurez votre propre charge de travail sur votre propre instance.

Modes de défaillance, et les messages que vous verrez

INFO: /dev/kvm does not exist / KVM acceleration can NOT be used depuis kvm-ok. Soit le module n'est pas chargé, soit le drapeau n'est pas exposé. Vérifiez d'abord /proc/cpuinfo.

kvm: disabled by bios dans dmesg. Sur une machine physique, activez l'option VT-x/SVM dans le firmware. Dans un VPS, cela signifie que L0 ne vous transmet pas les extensions, et rien de ce que vous tapez dans l'invité n'y changera rien.

modprobe: ERROR: could not insert 'kvm_intel': Operation not supported. Le processeur que voit votre noyau n'a pas de vmx : là encore, une décision de L0.

Could not access KVM kernel module: Permission denied. Une question de permissions, pas de matériel. ls -l /dev/kvm doit afficher le groupe kvm, le mode 660 ; ajoutez-vous à ce groupe et ouvrez une nouvelle session de connexion, car l'appartenance à un groupe ne s'applique pas à une session déjà en cours.

kvm: Device or resource busy au démarrage de QEMU. Un autre module d'hyperviseur occupe le processeur : lancez lsmod, cherchez vboxdrv ou les modules VMware à côté de kvm_intel, et déchargez celui dont vous ne voulez pas.

/var/run/libvirt/libvirt-sock: No such file or directory depuis virsh. Le démon est arrêté : sudo systemctl enable --now libvirtd.

Proxmox : KVM virtualisation configured, but not available. Un invité a l'accélération KVM cochée sur un hôte qui ne peut pas la fournir. Corrigez l'imbrication, ou décochez-la et acceptez l'émulation.

Émulateur Android : x86_64 emulation currently requires hardware acceleration! Encore /dev/kvm : le plus souvent le cas du groupe.

Aucune erreur, et tout est glacial. QEMU sans drapeau d'accélérateur revient à TCG, son émulateur logiciel. C'est correct et c'est lent : un démarrage qui se comptait en secondes se compte désormais en minutes. Passez -accel kvm explicitement, pour que QEMU s'arrête avec une erreur au lieu d'émuler en silence.

Un invité disparaît en pleine exécution. Cherchez dans dmesg la ligne Out of memory: Killed process ... qemu-system-x86_64. Un invité L2 est un processus sur L1, et le tueur de mémoire (OOM killer) le traite comme n'importe quel autre. La RAM de L2 est prélevée sur l'allocation fixe de L1 : pas d'emprunt à l'hôte.

L'exploiter : sauvegardes, mises à jour, limites

Sauvegardes. Copier le qcow2 d'un invité en cours d'exécution vous donne une image corrompue. Soit virsh shutdown guest1 puis copiez, soit prenez un instantané externe (virsh snapshot-create-as guest1 snap1 --disk-only --atomic) pour que les écritures soient détournées vers un overlay pendant que vous copiez la base désormais figée, puis réintégrez-le avec virsh blockcommit. Envoyez les copies hors du VPS : un instantané sur le même disque ne protège de rien.

Mises à jour. apt full-upgrade installe de nouveaux modules kvm_intel/kvm_amd, mais le noyau en cours d'exécution garde les anciens jusqu'au redémarrage. Gardez le noyau précédent installé et relancez kvm-ok après chaque changement de noyau : un hôte qui revient sans vmx n'est alors qu'à une entrée de démarrage de fonctionner à nouveau.

Là où cela cesse de passer à l'échelle. Une seule IP publique signifie que chaque service L2 atteint le monde à travers un proxy ou une règle DNAT sur L1. La migration à chaud n'est pas au menu. En cas de contention du processeur, le chemin de sortie imbriqué est le premier à en souffrir. Et un hyperviseur avec plusieurs invités est une machine dont vous avez déjà dépensé la RAM : les VM imbriquées ne peuvent pas se sortir d'une allocation fixe par surallocation. Quand un labo dépasse ces limites, la réponse n'est pas une pile imbriquée plus haute ; c'est une machine dédiée où vous êtes L0 et où rien de tout cela ne s'applique.

FAQ

Ai-je besoin de la virtualisation imbriquée pour faire tourner Docker sur un VPS ?

Non. Les conteneurs partagent le noyau de votre VPS et n'ouvrent jamais /dev/kvm, donc une instance ordinaire sans drapeau vmx ni svm fait tourner Docker et Docker Compose sans problème. L'imbrication ne compte que lorsque vous voulez un second noyau : un labo Proxmox, un invité Windows, des microVM Firecracker, un émulateur Android, ou des runners de CI qui démarrent des images de VM.

Comment vérifier si mon VPS prend en charge la virtualisation imbriquée ?

Lancez grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u, puis kvm-ok du paquet cpu-checker. Une instance utilisable affiche vmx (Intel) ou svm (AMD), kvm-ok indique KVM acceleration can be used, et /dev/kvm existe avec le groupe kvm et le mode 660. Ignorez /sys/module/kvm_intel/parameters/nested pour cette question : ce fichier décrit votre propre module KVM, pas ce que l'hyperviseur de l'hébergeur vous a exposé.

Pourquoi la plupart des hébergeurs VPS désactivent-ils la virtualisation imbriquée ?

Exposer vmx implique de donner à l'invité un modèle de processeur qui porte le drapeau, et un invité qui dépend de ces fonctions du processeur ne peut pas être migré à chaud vers une machine dont le processeur en est dépourvu : un hébergeur qui vide ses nœuds en déplaçant ses clients y renonce. Les chemins de code VMX/SVM imbriqués portent aussi un long historique de CVE. Certains hébergeurs l'activent tout de même par VM sur demande, et d'autres documentent l'imbrication comme une fonction de l'offre.

Ma VM imbriquée n'a pas de réseau sur le pont public. Quel est le problème ?

Le commutateur de l'hébergeur rejette les trames venant d'une adresse MAC qu'il ne vous a jamais attribuée, donc un invité L2 ponté sur la carte réseau publique envoie des requêtes ARP et n'entend rien en retour. Arrêtez de déboguer br0 : utilisez le réseau NAT default de libvirt (virbr0, 192.168.122.0/24), donnez un bail statique à l'invité, et publiez tout ce qui est public via un reverse proxy ou une règle DNAT sur le VPS lui-même.

À quel point une VM imbriquée est-elle plus lente ?

Le coût se porte sur les sorties de VM, pas sur l'accès mémoire. Avec EPT/NPT actifs, les lectures et écritures ordinaires dans L2 tournent à la vitesse du matériel, tandis que les E/S, les interruptions d'horloge, le MMIO et les IPI sont traités par L0 et peuvent être renvoyés à travers L1. Le travail limité par le processeur sur des données déjà en RAM reste proche du natif ; les charges lourdes en appels système, en paquets et en E/S disque ressentent chaque couche. Utilisez des périphériques virtio partout et cache=none sur les disques des invités, puis mesurez votre propre charge de travail.

#nested-virtualization#kvm#proxmox#vps#qemu#libvirt