vkhitrin.com

Technology And Ramblings

Creating A UTM Virtual Machine From CLI



Tags: #UTM #virtualization

Tested on UTM version 4.4.3 and macOS 14.0 (Sonoma).

Warning: This method is not endorsed by UTM!

Note: Apple Virtualization backend with Linux virtual machine is used in this blog post.

Note: Network devices must be added via GUI.

Preface

In a previous blog post, we discussed modifying UTM virtual machine configuration using CLI.

In this post, we will create an Arch Linux virtual machine from CLI without GUI.
The virtual machine will boot from an external Linux kernel and an external intiramfs, and we will attach a single storage device.

This post only covers a particular configuration but can be referred to when required to build different configurations (QEMU, macOS, and so on).

Why

UTM is an excellent virtualization software but doesn’t offer a native way to automate virtual machine creation.

Users can export their existing virtual machine bundles and then re-import them.
Users are also able to clone existing virtual machines.

We are interested in creating new virtual machine bundles programmatically.

Prerequisites

Before creating the virtual machine, please make sure you have the following prerequisites:

Creating The Virtual Machine

Each virtual machine includes unique identifiers UTM uses to differentiate between virtual machines.

Most identifiers use uuid v4, while Apple-specific identifiers use VZMacMachineIdentifier.

Configuring Variables

Define a display name for the virtual machine:

UTM_VIRTUAL_MACHINE_DISPLAY_NAME="arch-linux-00"

Generating Unique Identifiers

Creating A Virtual Machine Bundle

Note: To learn more about UTM virtual machine bundle, refer to a blog post linked in the `preface` section.

Required config.plist Keys

Before creating config.plist, we can take a look at all keys defined in (my) other virtual machines:

# Retrieve all keys
/usr/libexec/PlistBuddy -c Print "../archlinux.utm/config.plist" | perl -lne 'print $1 if /^    (\S*) =/'
# Output
Serial # serial console devices
Backend # virtualization backend (QEMU/Apple)
System # virtual machine system information
Virtualization # virtualized devices/features
Information # UTM virtual machine metadata
Network # network devices
Drive # storage devices
Display # display device
ConfigurationVersion # UTM configuration version

An example of a configuration file may look like this:

/usr/libexec/PlistBuddy -c Print "../archlinux.utm/config.plist"
# Output
Dict {
    Serial = Array {
    }
    Backend = Apple
    System = Dict {
        CPUCount = 4
        Boot = Dict {
            LinuxCommandLine = console=hvc0 root=/dev/vda2
            LinuxKernelPath = Image-archboot-aarch64
            OperatingSystem = Linux
            UEFIBoot = false
        }
        GenericPlatform = Dict {
            machineIdentifier = bplist00—TUUIDOÊdëcÍH©r;≤ÛÊF#
        }
        Architecture = aarch64
        MemorySize = 8192
    }
    Virtualization = Dict {
        Pointer = true
        Trackpad = false
        Keyboard = true
        Audio = true
        Entropy = true
        Rosetta = true
        Balloon = true
        ClipboardSharing = true
    }
    Information = Dict {
        Icon = arch-linux
        Name = Arch Linux
        UUID = F7823A3D-5583-4CF8-BB56-59AD38D0C14A
        IconCustom = false
    }
    Network = Array {
        Dict {
            MacAddress = <MAC_ADDRESS>
            Mode = Shared
        }
    }
    Drive = Array {
        Dict {
            Identifier = 86BDC3C3-E94C-446F-A9E2-A323BAF582D1
            ImageName = 86BDC3C3-E94C-446F-A9E2-A323BAF582D1.img
            ReadOnly = false
        }
    }
    Display = Array {
        Dict {
            WidthPixels = 1920
            PixelsPerInch = 80
            HeightPixels = 1200
        }
    }
    ConfigurationVersion = 4
}

Creating A Bundle

Create a virtual machine bundle:

mkdir -p "$HOME/Library/Containers/com.utmapp.UTM/Data/Documents/$UTM_VIRTUAL_MACHINE_DISPLAY_NAME.utm/Data"

Creating config.plist

Create the configuration file:

/usr/libexec/PlistBuddy -c 'save' "$HOME/Library/Containers/com.utmapp.UTM/Data/Documents/$UTM_VIRTUAL_MACHINE_DISPLAY_NAME.utm/config.plist"

Populating Values For config.plist

Download External Dependencies

Configure Storage Devices

Importing The Virtual Machine

After generating a virtual machine bundle, we will import the virtual machine into UTM:

open "$HOME/Library/Containers/com.utmapp.UTM/Data/Documents/$UTM_VIRTUAL_MACHINE_DISPLAY_NAME.utm/"

Don’t forget to add a networking device using the UTM GUI before starting the installation.

If our configuration file is valid, we should be able to see the virtual machine in UTM: A picture of a newly created arch-linux-00 virtual machine in UTM

Final Notes

While there isn’t an official UTM capability to create virtual machines using CLI, this blog post can be used as a quick hack to create virtual machines programmatically.

Back To Top