I stopped using IOS's to create VM's. I started using 'cloud images' I might expand on the resons to do this here... lets hope this feature request in the GUI virt-manager gets some traction: https://github.com/virt-manager/virt-manager/issues/143.


i'm going to show examples using virt-install and running it with my user account, which in turn, uses the qemu session connection. this gets around filesystem permission issues, etc. there is a difference between qemu:///session and qemu:///system. Just understand that there is a distingction. If you want to use something like virt-manager with this vm afterwards,you can simply connect virt-manager to qemu://session in addition to the default qemu:///system by selecting File-> Add Connection. You can read more about this subject at: https://blog.wikichoon.com/2016/01/qemusystem-vs-qemusession.html


if trying to connect to a bridge as i did below, you need to create a file to let qemu allow users (using the aforementioned qemu:///session) to connect to the system-level bridge. Edit the file /etc/qemu/bridge.conf and add a line that corresponds to tbe bridge you'd like to use. In my case, all it needs is "allow virbr0". edit to suit your machine.

  1. grab the image. Start here: http://cloud-images.ubuntu.com/. Navigate their complicated folder structure to download a specific version. I used https://cloud-images.ubuntu.com/daily/server/focal/20210720/focal-server-cloudimg-amd64.img.

I cant find documentation on what each of the different formats are other than the rather brief description column and making an inference on the file extention. For example, lets look at these two examples:

  • https://cloud-images.ubuntu.com/daily/server/focal/20210720/focal-server-cloudimg-amd64.img
  • https://cloud-images.ubuntu.com/daily/server/focal/20210720/focal-server-cloudimg-amd64-disk-kvm.img

so whats the difference? if you're going to run the image in kvm, you might be tempted by the -kvm image, but from what i can see, by looking at the .manifest files https://cloud-images.ubuntu.com/daily/server/focal/20210720/focal-server-cloudimg-amd64.manifest and https://cloud-images.ubuntu.com/daily/server/focal/20210720/focal-server-cloudimg-amd64-disk-kvm.manifest, it looks like the -kvm image has a kernel with kvm enabled, which would only be needed for a kvm hypervisor, not a guest.\</rant>

    wget https://cloud-images.ubuntu.com/daily/server/focal/20210720/focal-server-cloudimg-amd64.img
  1. Now create some cloud-init configurations documentation here: https://cloudinit.readthedocs.io/en/latest/. its complicated. in our simple environment, we're going to use 'datasource' of 'NoCloud'https://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html. which is just a .iso file with two files: meta-data and user-data. those two files define all of the configuration that will be dropped onto the vm at first boot.

  2. meta-data has the machine specific data like hostname and network configurations. For this use-case we're gonna let it default to dhcp, so lets keep it basic and only set and instance-id and local-hostname.

    instance-id: foo-tester
    local-hostname: foo-tester
  3. user-data is documented here: https://cloudinit.readthedocs.io/en/latest/topics/format.html# . here we'll set up a few things like our user and ssh key. I'm going to use docker on these hosts, so i'll install and enable docker and docker-compose.

      - name: foobar
          - ssh-rsa <<copy your ssh pubkey from ~/.ssh/id_rsa.pub>>
        sudo: ['ALL=(ALL) NOPASSWD:ALL']
        groups: sudo
    # runs apt-get update
    package_update: true
    # runs apt-get upgrade
    package_upgrade: true
    # installing additional packages
      - docker
      - docker-compose
    # run some commands on first boot
      - systemctl daemon-reload
      - systemctl enable docker
      - systemctl start --no-block docker
    # after system comes up first time. 
    final_message: "The system is finally up, after $UPTIME seconds"
  4. use virt-install to pull in the user and meta data files for first boot, start the vm, configure it.

    virt-install \
      --name foo-tester \
      --memory 4096 \
      --vcpus 4 \
      --os-type linux \
      --os-variant ubuntu20.04 \
      --network bridge=virbr0 \
      --nographics --disk size=10,backing_store=$PWD"/focal-server-cloudimg-amd64.img",bus=virtio \
      --cloud-init user-data=$PWD"/user-data",meta-data=${PWD}"/meta-data"
  5. Your terminal session will attach to the VM. let it boot for a little bit so that you can see the dhcp'ed address print out to the console. When you want, detach from the serial console hold down control, then press seven key followed by the ] key. ( ctrl+^])

  6. if anything goes wrong, you'll want to get rid of the machine that you created to start over:

    virsh destroy foo-tester || virsh undefine foo-tester --remove-all-storage

  7. you can scroll up in the output to find out the dhcp address your VM picked up:

    [    8.499751] cloud-init[652]: ci-info: +--------+------+----------------------------+---------------+--------+-------------------+
    [    8.501392] cloud-init[652]: ci-info: | Device |  Up  |          Address           |      Mask     | Scope  |     Hw-Address    |
    [    8.503118] cloud-init[652]: ci-info: +--------+------+----------------------------+---------------+--------+-------------------+
    [    8.504659] cloud-init[652]: ci-info: | enp1s0 | True |       | | global | 52:54:00:xx:xx:xx |
    1. log in over ssh and enjoy.

    ssh foobar@


comments powered by Disqus