Posted on

No blog entry since 2019 🙈🙈🙈

So let me share something small yet hopefully helpful. Mostly I try to do everything in containers but now I am in a project that uses ansible to deploy software to machines so I thought it might be better to spin up a VM. As it is 2022 I thought I should do it without using VMWare, Virtualbox etc. Instead I wanted to work with libvirt and start a cloud-init capable image to not have to click through some installation process.

Unfortunately this is not as easy as one would think and took me quite a while to figure out. There are many references where this takes many steps. I hope this quick post gets you started faster.

Prerequisites

On an arch linux (btw I use Arch) you need to have the following packages installed:

sudo pacman -S libvirt qemu-system-x86 virt-install

And libvirtd must be started:

sudo systemctl start libvirtd

Then make sure your user is in group libvirt so it is allowed to manage VMs.

Download the image

First of all download the appropriate generic for the image here: https://cloud.debian.org/images/cloud/

In case you want bullseye on amd64 here is the direct link: https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.qcow2

DO NOT DOWNLOAD THE GENERICCLOUD IMAGE (explanation later)

Put it here: /var/lib/libvirt/images/

Preparing a cloud init file

The debian image doesn't have a default user (contrary to for example ubuntu) so we need to create one during bootup.

Create a cloud-init.yaml config:

#cloud-config

users:
  # whatever username you like
  - name: mop
    # so our user can just sudo without any password
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    # content from $HOME/.ssh/id_rsa.pub on your host system
    ssh_authorized_keys:
      - ssh-rsa AAAA[...]

Cloud init supports pulling keys from github directly. Unfortunately that didn't work for me in the debian cloud image (ubuntu worked 🤔). Probably debian just has an old version.

Starting the VM

virt-install --name debian --memory 2048 --vcpus 4 --disk=size=10,backing_store=/var/lib/libvirt/images/debian-11-generic-amd64.qcow2 --cloud-init user-data=./cloud-init.yaml,disable=on --network bridge=virbr0 --osinfo=debian11

This starts a new VM and a console will come up showing the boot process and the IP that the VM is using in bridge mode. (or just issue a ip neigh on your host system). If you want to leave the console press Ctrl+] (there is also an --noautoconsole option for virt-install if you want it to boot in the background). You should now be able to login using the console and you should be able to ssh to the VM.

The --disk option is quite interesting. This uses an overlay filesystem much like docker. So the general image is shared across all future debian VMs but the changes per VM will be saved in a separate images in this directory:

$HOME/.local/share/libvirt/images

Obviously there are many things here that you can change/adjust but this is just the most simple command line that worked for me. Details can be found in the man page of virt-install

Getting rid of the VM

This is also non-intuitive.

First you have to stop the machine:

virsh destroy --domain debian

And then delete it using undefine.

virsh undefine --domain debian --remove-all-storage

This will remove the overlay filesystem containing all your changes to your VM but keep the base image.

I like how libvirtd uses special terms for everything. destroy instead of kill, domain instead of vm and undefine instead of delete. 🙈

The genericcloud debian image

genericcloud: Similar to generic. Should run in any virtualised environment. Is smaller than generic by excluding drivers for physical hardware.

Obviously this sounds like the right image. Unfortunately it is not. It doesn't contain the SATA AHCI drivers which are needed because of the way the cloud-init stuff is being injected into the VM (as a cdrom drive).

This took me a quite a while to figure out. After finding out what was the culprit I was finally able to google for the problem and found this: https://groups.google.com/g/linux.debian.bugs.dist/c/fpGNuIC7GZc