Skip to content

Product docsVirtualization & VDS

Create KVM virtual machines with libvirt on a Linux VDS

Run KVM guests inside a Linux VDS: install libvirt, start the default NAT network, create an Ubuntu VM from a cloud image with cloud-init and connect over SSH.

  • Advanced
  • 30 min read
  • Updated
On this page
  1. Before you start
  2. Step 1: Install the tools
  3. Step 2: Start the default network
  4. Step 3: Download the cloud image
  5. Step 4: Create the guest's disk
  6. Step 5: Create and start the VM
  7. Step 6: Connect to the guest
  8. Step 7: Everyday management
  9. Troubleshooting
  10. Next steps

A Linux VDS with nested virtualization can run KVM virtual machines of its own, managed with libvirt. That is useful for isolated test environments, CI machines or labs. This guide creates an Ubuntu guest from Ubuntu's official cloud image; cloud-init puts your SSH key into it, so there is no installer to click through. It builds on the check and package installation in VDS and nested virtualization.

Before you start

  • An Ubuntu or Debian VDS, nested dedicated or dedicated server where kvm-ok (package cpu-checker) prints KVM acceleration can be used.
  • A user with sudo and an SSH key pair on your own computer; see SSH keys.
  • Free disk space for the guests under /var/lib/libvirt/images.

Step 1: Install the tools

Bash
sudo apt update
sudo apt install qemu-system-x86 qemu-utils libvirt-daemon-system virtinst
sudo usermod -aG libvirt $USER

Log out and in again so the group membership applies.

Verify: virsh list --all runs without a permission error.

Step 2: Start the default network

libvirt's default network gives guests addresses in 192.168.122.0/24 and NAT to the internet:

Bash
virsh net-list --all
sudo virsh net-start default
sudo virsh net-autostart default

Verify: virsh net-list shows default as active with autostart yes.

Step 3: Download the cloud image

Download Ubuntu 24.04's cloud image and its checksum list, and check the file:

Bash
cd /var/lib/libvirt/images
sudo wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
sudo wget https://cloud-images.ubuntu.com/noble/current/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing

Verify: the check prints noble-server-cloudimg-amd64.img: OK.

Step 4: Create the guest's disk

Copy the image for the new guest and give it room to grow; cloud-init grows the file system on first boot:

Bash
sudo cp noble-server-cloudimg-amd64.img vm1.qcow2
sudo qemu-img resize vm1.qcow2 20G

Step 5: Create and start the VM

Find the OS name libvirt knows for Ubuntu 24.04:

Bash
sudo apt install libosinfo-bin
osinfo-query os | grep -i ubuntu24

Create the guest, import the disk and pass your public SSH key to cloud-init. Copy your public key to the server first (for example to ~/id_ed25519.pub):

Bash
virt-install --name vm1 --memory 2048 --vcpus 2 --disk /var/lib/libvirt/images/vm1.qcow2 --import --osinfo ubuntu24.04 --network network=default --cloud-init clouduser-ssh-key=$HOME/id_ed25519.pub --graphics none --noautoconsole

--import builds the VM around the existing disk instead of running an installer, and clouduser-ssh-key lets you log in as the image's default user, ubuntu.

Verify: virsh list shows vm1 as running.

Step 6: Connect to the guest

Wait a minute for the first boot, then look up the guest's address and connect from the server:

Bash
virsh domifaddr vm1
ssh ubuntu@192.168.122.50

From your own computer, jump through the server in one command:

Bash
ssh -J you@203.0.113.10 ubuntu@192.168.122.50

If SSH does not work yet, open the serial console with virsh console vm1 and leave it with Ctrl + ].

Step 7: Everyday management

Bash
virsh list --all
virsh shutdown vm1
virsh start vm1
virsh autostart vm1

virsh autostart starts the guest whenever the server boots. To delete a guest and its disk, run virsh destroy vm1 and virsh undefine vm1 --remove-all-storage.

Troubleshooting

virt-install says KVM is not available or falls back to slow emulation. The virtualization extensions are not visible; see nested virtualization problems.

virt-install reports that an OS name is required, or does not know the name. Use a name that osinfo-query os lists on your server; older systems may only know older Ubuntu releases.

virsh domifaddr shows nothing. The guest is still booting, or cloud-init has not configured the network yet. Wait, or check the boot output with virsh console vm1.

Permission denied (publickey) when connecting. The key file given to clouduser-ssh-key was not your public key, or you connected as the wrong user. Recreate the guest with the right key and connect as ubuntu.

The guest has no internet. Check that the default network is active (virsh net-list) and that your host firewall allows forwarding for virbr0.

Next steps

Frequently asked questions

Do I need a graphical desktop to manage the VMs?

No. virsh and virt-install work over SSH. If you prefer a graphical tool, virt-manager on your own Linux computer can connect to the server over SSH.

How do guests reach the internet?

Through libvirt's default network, which gives guests private addresses with DHCP and NAT behind the server's public address.

How do I make a guest's web service public?

Run a reverse proxy such as Caddy or Nginx on the host and forward the site to the guest's private address. For other ports, forward them with firewall rules on the host.

Can I run Windows guests?

Yes, from an installation ISO with virt-install's --cdrom option and a graphical console such as VNC over an SSH tunnel. The steps in this guide use a Linux cloud image because it needs no installer.

Generate Password

Please confirm