Install Mac OS X on Linux in VirtualBox - lmmx/devnotes Wiki

Grab the DMG from here and create a new Mac OS X VM in VirtualBox (available on the Linux Software Manager or from the VB website if you have a poor internet connection

I got an error about the CPU ID, and a second error about hardware acceleration both of which are apparently to do with my BIOS settings

I opened the BIOS settings (for me, by selecting the "UEFI" option at the grub menu) and the closest sounding option was to enable "Intel VMX Virtualization Technology" (whereas VirtualBox suggested "VT-x" instead).

After changing this, the VirtualBox dialogue under Machine > Settings no longer showed an "invalid settings configuration" message at the bottom, and now allowed me to make changes to the settings.

Upon starting the VM, I got a console:

UEFI Interactive SHell v2.2
EDK II
UEFI v2.70 (EDK II, 0x00010000)
Mapping table
	BLK0 Alias(s):
		PciRoot(0x0)/Pci (0x1F,0x2)/Sata (0x0,0xFFFF,0x0)
	BLK1 Alias(s):
		PciRoot(0x0)/Pci (0x1F,0x2)/Sata (0x0,0xFFFF,0x0)
Press ESC in 1 seconds to skip startup.nsh or any other key to continue.
Shell>

I closed this and deleted the VM (as it shouldn't be doing that) and went once again to create a new VM. This time, the OS images from the DMG file had been loaded into the VirtualBox menu and I could now select various 64-bit macOS versions, from which I chose "macOS 10.13 High Sierra (64-bit)"

Once again, starting this VM took me to the same shell console

Apparently this isn't allowed in the sense of practicality more than legality, see discussion here

To check if you booted with (U)EFI you need to check if /sys/firmware/efi exists

[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS

When disabling EFI in the VM settings (as recommended here) I got the error "No bootable medium" and it halts


After some more searching around I found there is a "push-button installer" here, apparently also used for CI pipelines, macos-guest-virtualbox.sh

Tested on bash and zsh on Cygwin. Works on macOS, CentOS 7, and Windows. Should work on most modern Linux distros.

The dependencies are:

bash coreutils gzip unzip wget xxd dmg2img virtualbox

I only needed to run sudo apt install dmg2img to meet these.

The default config is:

vm_name="macOS"
macOS_release_name="Catalina"    # install "HighSierra" "Mojave" "Catalina"
storage_size=80000               # VM disk image size in MB, minimum 22000
storage_format="vdi"             # VM disk image file format, "vdi" or "vmdk"
cpu_count=2                      # VM CPU cores, minimum 2
memory_size=4096                 # VM RAM in MB, minimum 2048
gpu_vram=128                     # VM video RAM in MB, minimum 34, maximum 128
resolution="1280x800"            # VM display resolution

Note: I uploaded my modified script as a GitHub Gist here if you want to just copy that and run (or diff against the current version on the source repo).

The script interacted with VirtualBox (I think using VBoxManage), and took some time to download the Catalina DMG etc.

I was away from my machine when the downloads finished, and it had launched a VirtualBox window with the shell open, but was apparently waiting to reach a dialogue box (which was not reached). One of the lines of output included the letters "ERR" suggesting an error in the setup process, so I re-ran the script with a modification to avoid having to wait for the large installation files to download again.

Specifically, on line 497 I modified the script to add a condition to download if and only if the file does not exist.

Originally it was:

echo "Downloading macOS installation files from swcdn.apple.com"
for filename in "BaseSystem.chunklist" \
                "InstallInfo.plist" \
                "AppleDiagnostics.dmg" \
                "AppleDiagnostics.chunklist" \
                "BaseSystem.dmg" \
                "InstallESDDmg.pkg"; \
    do wget "${urlbase}${filename}" \
            ${wgetargs} \
            --output-document "${macOS_release_name}_${filename}"
done

...and I changed it to:

echo "Downloading macOS installation files from swcdn.apple.com"
for filename in "BaseSystem.chunklist" \
                "InstallInfo.plist" \
                "AppleDiagnostics.dmg" \
                "AppleDiagnostics.chunklist" \
                "BaseSystem.dmg" \
                "InstallESDDmg.pkg"; \
    do          
    if [ -f "${macOS_release_name}_${filename}" ]; then
        echo "Skipping download for $filename -- already exists"
    else
        wget "${urlbase}${filename}" \
          ${wgetargs} \
          --output-document "${macOS_release_name}_${filename}"
    fi
done

Upon running this again, the errors arise from System\Library\PrelinkedKernels\, which is documented in the README as an issue with "CPU compatibility".

CPU compatibility

macOS guests on VirtualBox are incompatible with some CPU models. If the guest macOS boot process hangs on “LoadKernelFromStream”, “EndRandomSeed”, or "EXITBS", see the documentation command regarding VirtualBox CPU profiles and CPUID settings. Some CPU models released in 2020 and later may fail to start or complete the installer, and may require manually adjusting the CPUID settings.

Running the script with the documentation argument shows the documentation including

    CPU profiles and CPUID settings (unsupported)

macOS does not supprort every CPU supported by VirtualBox. If the macOS Base System does not boot, try applying different CPU profiles to the virtual machine with the VBoxManage commands described below. First, while the VM is powered off, set the guest's CPU profile to the host's CPU profile, then try to boot the virtual machine: VBoxManage modifyvm "${vm_name}" --cpu-profile host VBoxManage modifyvm "${vm_name}" --cpuidremoveall If booting fails, try assigning each of the preconfigured CPU profiles while the VM is powered off with the following command: VBoxManage modifyvm "${vm_name}" --cpu-profile "${cpu_profile}" Available CPU profiles: "Intel Xeon X5482 3.20GHz" "Intel Core i7-2635QM" "Intel Core i7-3960X" "Intel Core i5-3570" "Intel Core i7-5600U" "Intel Core i7-6700K" If booting fails after trying each preconfigured CPU profile, the host's CPU requires specific macOS VirtualBox CPUID settings.

So (after exiting the script and 'powering off' the VM) I want to change the CPU profile to an Intel i9 (probably not supported), and first I'll try just setting it as the host:

VBoxManage modifyvm "macOS" --cpu-profile host
VBoxManage modifyvm "macOS" --cpuidremoveall

This didn't work, as expected, so I tried an i7 CPU ID:

VBoxManage modifyvm "macOS" --cpu-profile "Intel Core i7-6700K"

This time the installer proceeded to the GUI, however I'd already exited the script to run the VBoxManage command.

To incorporate the CPU ID edit into the script, I edited at line 842, specifically where the script starts the VM, to edit the VM CPU ID before it starts.

echo -e "\nStarting virtual machine \"${vm_name}\".

becomes

VBoxManage modifyvm "${vm_name}" --cpu-profile host
VBoxManage modifyvm "${vm_name}" --cpuidremoveall
VBoxManage modifyvm "${vm_name}" --cpu-profile "Intel Core i7-6700K"

echo -e "\nStarting virtual machine \"${vm_name}\".

What happens eventually is that 2 terminal windows open, one of them running startosinstall.sh (which seems to complete) and the other running nvram.sh (which hangs).

The hanging nvram.sh is not important, but the fact that it stays there indicates a failure of startosinstall.sh to finish successfully, as when it does so it initiates a (virtual) system reboot into the installed macOS VM, which does not happen.

In short, this is a symptom of CPU compatibility issues.

I tried again with the next-newest Intel CPU ID (since the docs are very clear that CPU 'teleporting' is not supported), "Intel Core i7-5600U" (but of course this gave the same result).

After retrying a couple of times more I decided to just try installing on an old laptop in the hope its i7 CPU would be compatible. It wasn't, and I then returned to trying to install on PC.

I finally got it to work by changing the OS from "Catalina" to "Mojave", in the config at the start of the script. Either way, the OS can be upgraded to Big Sur so it makes no difference what you start as.

Once it finishes, save a clone (I chose a "linked clone" snapshot) of the VM which you can roll back to if the upgrade to Big Sur has problems or crashes.


After this successfully ran (and in fact I forgot the password I'd set...) I had to re-run the entire process once more, so I used the larger screen size (since I want to use the VM for app development and the more screen space the better)

When installing the operating system, I clicked:

Once this finishes you will see the Mac OS X desktop.

At this point I recommend shutting down the machine (power off), then add the storage attachment optical drive for the guest additions, which for me would not work by simply clicking "Devices > Insert Guest Additions CD Image".

Once restarted, double click the DVD image icon on the desktop and run VBoxDarwinAdditions.pkg. When prompted, open the system preferences and permit the change to system extensions from this Oracle software (i.e. the VirtualBox Guest Additions, for USB passthrough from the host etc.)

Click the magnifying glass icon in the top right of the screen and search for "Software Update", then click 'Upgrade Now' next to the macOS Big Sur option (11.4 - 12.4 GB).

After the Big Sur update runs you'll eventually get to what looks like a hanging error message which ends with a log from unmount which appears to be for the / path, when everything stops at this point you can power off the machine, and when you restart it you have a working Big Sur macOS VM !

In the Big Sur setup screen:

Then done!


Further notes: