============================
== Keep Calm and Route On ==
============================
infra ramblings. all views are my own

Ubuntu/Libvirt Up and Running on Mac Mini (Part 2)

mac ubuntu virtualization kvm

Getting Ubuntu & KVM installed on a Mac mini for virtualization.

This is part 2 of a series for getting KVM/Libvirt up and running on a Mac mini. This part we will cover the configuration of a network bridge, and installing a Linux guest. Find Part 1 of our series here.

Configure the Network Bridge

Before we get started deploying VMs to our new KVM host, we need to get networking configured for our VMs. There are a ton of ways to go about this; we could create a local network, create network definitions via virsh, etc.

In our case, we are going to create a network bridge, that will allow us to “plug” our VMs directly into the same network our VM host is plugged into.

Ubuntu 20.04 (and 18.04) make this very very easy for us to do this, with something called Netplan. With Netplan, we are able to define networking on our host using YAML, which is awesome. Netplan can do a lot more than just build bridges for us, so definitely cehck out some of the examples on their site.

Below is the original Netplan file, generated by the initial Ubuntu install on our host. This file is /etc/netplan/00-installer-config.yaml

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp1s0f0:
      addresses:
      - 172.16.15.45/24
      gateway4: 172.16.15.1
      nameservers:
        addresses:
        - 172.16.15.2
        search:
        - ipa.contoso.local
        - contoso.local
  version: 2

If you configured your VM host to use DHCP, it may look closer to this:

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp1s0f0:
      dhcp4: yes
  version: 2

To create our bridge, we update this file to look like this:

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp1s0f0:
      dhcp4: no
  bridges:
    br15:
      dhcp4: no
      addresses:
        - 172.16.15.45/24
      gateway4: 172.16.15.1
      nameservers:
        addresses:
        - 172.16.15.2
        search:
        - ipa.contoso.local
        - contoso.local
      interfaces:
        - enp1s0f0
  version: 2

Or if we want to keep using DHCP:

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp1s0f0:
      dhcp4: no
  bridges:
    br15:
      dhcp4: no
      interfaces:
        - enp1s0f0
  version: 2

The name of the bridge, br15 is our choice, but we will want to use a name that makes sense.

To apply this configuration, we could run netplan apply

This command will apply the netplan config, unless there is a syntax error. The downside to this command is if your config is syntactically correct, but breaks networking, you’ll need to console into your Mac mini (read, more displays & keyboards) to fix this.

The command that works better for this, is netplay try which looks like this:

$ sudo netplan try
Warning: Stopping systemd-networkd.service, but it can still be activated by:
  systemd-networkd.socket
Do you want to keep these settings?


Press ENTER before the timeout to accept the new configuration


Changes will revert in 120 seconds

Here, I am given the ability to hit Enter to confirm the new configuration, but if the config breaks networking, in 120 seconds, the configuration will be rolled back.

We can use these same tools to change the host from using DHCP, or visa versa.

Pull Install Media

It is possible to install your VM directly from a web location, or to pull down a pre-built image for your VM. We aren’t going to do that, and instead install via an ISO file.

In our example, we are going to pull down the Ubuntu Server installation ISO, and create a VM from it.

To pull our ISO file,

$ cd /var/lib/libvirt/boot/
$ sudo wget https://releases.ubuntu.com/20.04.1/ubuntu-20.04.1-live-server-amd64.iso

Once wget is done, we should have the same ISO file we used to install Ubuntu on the VM host!

Start installation

$ sudo virt-install --name new-vm \
--vcpus=2 \
--ram=2048 \
--virt-type=kvm \
--hvm \
--os-type=generic \
--network=bridge=br15,model=virtio \
--cdrom=/var/lib/libvirt/boot/ubuntu-20.04.1-live-server-amd64.iso \
--disk path=/var/lib/libvirt/images/new-vm.qcow2,size=20,format=qcow2 \
--vnc

The above command will perform the necessary creation steps, create teh VM definition files, generate a qcow2 file for the hard disk, and then kick-off the installation. This specific command will also create a VNC console, which we can connect to to perform the installation.

VNC, Spice, Serial?

There are a lot of ways to connect to your VM. It is possible to use a “serial” console setting in the virt-install command, by removing the --vnc and adding

--graphics none \
 --console pty,target_type=serial \
 --extra-args 'console=ttyS0,115200n8

The above commands should work with most Linux distributions, though in some cases it may not. You can connect to that console using virsh console vmname

It is also possible to configure a Spice console instead of a VNC console. While you can do this, Spice doesn’t work fantastically on a Mac, so I’m using VNC.

Get Connected to the Console

In our case, we are going to use a VNC console, which we can connect to using port forwarding.

Before we do this, we need a VNC client to connect to our console port. On macOS, you can use Chicken, or you can use the built-in Screen Sharing app, which supports connecting to VNC. On Windows, there are a plethora or VNC tools, but I personally would use Virt-Viewer which will also allow you to connect to a Spice console if you wish.

To find our VNC port, connect back to our VM host using a secondary SSH connection. Once connected, run:

$ sudo virsh dumpxml new-vm | grep vnc
    <graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1'>

The output will provide the VNC port. In this case, it’s port 5900. At this point, we can now exit our second SSH session, so that we can connect back with the correct port forwarding.

On macOS or Linux, we can connect back with port forwarding easily using the -L argument, like below:

$ ssh user@host -L 5909:localhost:5900

Here we are forwarding the hosts port 5900 to our local machine’s port 5909. If you are on Windows, you can do this forwarding using something like PuTTY, which functions similarly.

Once you are connected, you should have a prompt like you tpically do in an SSH session. Make no mistake, the port has been forwarded, and we can now connect to localhost:5909 which will provide us the console to our VM.

From here, you can continue your installation in any fashion you choose. Once installed, you should be able to SSH into this VM just like you did with the host, since it is on the same network, thanks to our bridge adapter!

Keep it going with Part 3 of this series, where we install Windows as a guest, and with UEFI.