Every virtual machine (VM) to be run using the macOS Virtualization framework is required to have a unique Machine Identifier (MID), generated when that VM is first created and installed. For macOS guests, that MID is used to determine the system Serial Number, Hardware UUID and Provisioning UUID. For most users this is of little impact, as this is all taken care of by the virtualising app and saved out of sight, inside the VM bundle.
Apple warns that trying to run two VMs with the same MID at the same time results in “undefined behaviour”, in other words it must be avoided, and could put both VMs at risk of damage or corruption.
One situation in which this could occur is when a VM is copied or duplicated, a tempting use of APFS’s ability to clone files efficiently. Currently, lightweight virtualisation has no specific means of making a ‘snapshot’ of a VM; a good workaround is to shut that VM down and duplicate its bundle, resulting in a clone with an identical MID. If the user were to try running both clones at the same time, that would result in “undefined behaviour”, and could put them both at risk. If you use VM cloning, you must ensure that doesn’t occur; if you only ever run one VM at a time, then it shouldn’t worry you.
Since I made my own free app Viable available, several people have asked whether it’s possible to create VMs with fixed MIDs, for various testing and deployment purposes. Following research into MIDs, I now offer a new version of Viable, beta 4 (1.0.4), which can do that. This article explains the limitations of MIDs, and how you can overcome them in Viable. I’m currently working on a new version of Liviable to do this with Linux VMs as well.
Changing existing VMs doesn’t work
As the MID is saved to a separate file inside both macOS and Linux VM bundles, the most obvious approach is to change that MachineIdentifier file. Unfortunately, that consistently causes that VM to freeze during boot. The only way to fix that is to restore the original MachineIdentifier file saved when that VM was first created and installed.
I next tried substituting a different MID when creating a VM Platform Configuration ready to boot an existing VM. This too caused the boot process to freeze. These confirm the warning in Apple’s documentation: “When you save a VM to disk and load it again, you must restore the hardwareModel, machineIdentifier and auxiliaryStorage properties to their original values.”
The conclusion is that the MID is baked into the rest of the VM when it’s created, and is (in macOS VMs at least) immutable. The only way to run a macOS VM with a known MID is to create it using a pre-existing MID.
The MID is opaque
Apple describes the MID as opaque data, and provides limited access to it, sufficient to save and retrieve it from the MachineIdentifier file on disk. MachineIdentifier files contain a binary property list in which the ECID key is paired with a very large integer. I’ve been unable to discover how macOS generates the Serial Number and UUIDs from that integer, so the data remains opaque: it can be created reliably by initialising a VZMacMachineIdentifier, either as a new unique MID or from its data representation. Other than those two methods, there doesn’t appear to be any reliable method for creating a custom MID.
Thus, the user can’t convert a predetermined system Serial Number and UUIDs into an MID, but macOS can generate MIDs for use in more than one VM, provided the user is careful never to run two VMs with the same MID concurrently.
As an aside, the HardwareModel saved to macOS VM bundles is another binary property list, this time containing the MinimumSupportedOS, given as three integers representing 12.0.0, and a PlatformVersion of 2. The AuxiliaryStorage file is more than 30 MB of almost entirely blank data, with small islands of binary data, including iBoot Stage 1. Among them are nvram contents, security certificates, nonce seeds and nonces, settings for auto-boot and bootdelay, volume UUIDs, and boot breadcrumbs, all needed when the VM boots.
In contrast, the MachineIdentifier file in Linux VMs is a binary property list containing a single UUID in data format, and there’s a small NVRAM file in addition to that.
By default, Viable beta 4 generates a new unique MID each time that it creates and installs a new VM, and that MID is loaded and used when that VM is booted. That is standard behaviour across all apps using lightweight virtualisation on macOS.
Viable also generates a MID to be retained in memory. A new checkbox allows you to Keep that Machine ID for use in all new VMs you create and install while that checkbox is ticked. When it is unticked again, behaviour reverts to the default, generating a new unique MID each time.
A new menu command, Load Machine ID… in the File menu, prompts you to select an existing MachineIdentifier file, for example within an existing VM bundle, which will then be loaded to replace the retained MID. For example, to create a series of new VMs with the same MID as one of your old VMs, simply use that command to load the MachineIdentifier from that old VM, tick the Keep Machine ID checkbox, then create the VMs you want to use the same MID.
You can copy MachineIdentifier files from VM bundles to make a library for creating new VMs using any of a range of existing MIDs, as you require.
Unfortunately, the only way to discover the system Serial Number and UUIDs for any given saved MID is to run one of the VMs created with that MID. However, all other VMs using the same MID will then have exactly the same system Serial Number, Hardware UUID and Provisioning UUID.
In this beta-release, Viable doesn’t check whether it’s being asked to run two VMs with the same MID concurrently, so it can’t help you avoid making that error. In addition to working on an implementation of a similar scheme for using known MIDs in Liviable, I’m also looking at a means of checking that the user doesn’t try running a VM with the same MID.
Viable beta 4 (1.0.4) is now available from here: viable1b4
and is listed in Downloads above. I will shortly be adding a new Product Page for Viable and Liviable.