How to run MAC OS VM under KVM /qemu
//DRAFT We will show how to runMAC OS Virtual Machine under KVM /native qemu / This is only in educational purposes.
We are using Cenots 8 OS . BUt this should also work for Cnetos7 (even easier as you can easily download dmg2img rpm for centos7 /rhel7 but at this moment you may only build it from sources for centos 8) For ubuntu there will be some differences but the overall process is similar.
Check if virtualization is supported:
lscpu | grep Virtualization sort -u <<<$(egrep -o -i --color "vmx|svm" /proc/cpuinfo)
First of all you need to build your qemu from sources. Even if you have qemu/libvirt already installed our custom build should not conflict with it.
Check qemu module:
lsmod | grep kvm
if not listed add:
modprobe kvm
If you installing on environment that already using qemu/libvirt yo uneed to know where is qemu located in order to do not affect it:
whereis qemu qemu: /usr/share/qemu
OK go to /opt and download qemu sources:
git clone git://git.qemu-project.org/qemu.git cd qemu git submodule init git submodule update --recursive git submodule status --recursive git checkout stable-4.2.50 #or check what stable version exist at this time
Make sure you enabled APPLESMC in Makefile. Add if not exists the next records in Makefile :
# Makefile for QEMU. CONFIG_NE2000_ISA=y CONFIG_HPET=y CONFIG_APPLESMC=y
You may also check all APPLE related settings like with search:
grep "APPLE" -r .
Install gcc if not exists:
yum install gcc
..And dev tools if not installed:
yum groupinstall "Development Tools"
Add depencies:
yum install glib2-devel glibc-utils zlib zlib-devel pixman-devel
OK next configure to build qemu to custom binary
- install python if not installed on your system:
#yum install python36 ./configure --prefix=/usr/bin/qemundi # no need: Not sure it need but I've created the target build dir: # mkdir /usr/bin/qemundi make
Next make install:
make install
OK your custom qemu build shoiuld be located at /usr/bin/qemundi/.. Check version:
/usr/bin/qemundi/bin/qemu-system-x86_64 --version QEMU emulator version 4.2.50 (v4.2.0-2711-g29e0855c5a-dirty) Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers
Next we will prepare MAC OS.
cd /opt git clone https://github.com/kholia/OSX-KVM.git cd OSX-KVM
Refer to the git README for actual steps https://github.com/kholia/OSX-KVM However we will show our way here.
fetch installer:
./fetch-macOS.py #if you got error like /usr/bin/env no such file or directory most likely you have only python3 installed then try: # python3 fetch-macOS.py # or install python2
Select the MACOS version desired:
# ProductID Version Build Post Date Title 1 061-26578 10.14.5 18F2059 2019-10-14 macOS Mojave 2 061-26589 10.14.6 18G103 2019-10-14 macOS Mojave 3 041-91758 10.13.6 17G66 2019-10-19 macOS High Sierra 4 041-88800 10.14.4 18E2034 2019-10-23 macOS Mojave 5 041-90855 10.13.5 17F66a 2019-10-23 Install macOS High Sierra Beta 6 061-86291 10.15.3 19D2064 2020-03-23 macOS Catalina 7 001-04366 10.15.4 19E2269 2020-05-04 macOS Catalina 8 001-15219 10.15.5 19F2200 2020-06-15 macOS Catalina 9 061-94403 10.15.6 19G73 2020-07-15 macOS Catalina 10 001-36735 10.15.6 19G2006 2020-08-06 macOS Catalina 11 001-36801 10.15.6 19G2021 2020-08-12 macOS Catalina Choose a product to download (1-11):
Choose 11 for example and it will download neccesary binaries.
Next you need to convert dmg to img with dmg2img tool which currently have no rpm/binaries for centos 8 so we will git clone it from sources and build. BUT you may give a try to use qemu-img utility if your qemu version is higher than 4.11:
qemu-img convert BaseSystem.dmg -O raw BaseSystem.img
In case of no luck try to use dmg2img Install depencies:
yum install bzip2-devel openssl-devel
cd /opt git clone https://github.com/Lekensteyn/dmg2img.git cd dmg2img make make install dmg2img -v dmg2img v1.6.5 (c) vu1tur (to@vu1tur.eu.org)
Go to OSX-KVM dir and convert dmg to img:
cd /opt/OSX-KVM dmg2img BaseSystem.dmg BaseSystem.img
Create a virtual HDD image where macOS will be installed. If you change the name of the disk image from mac_hdd.img to something else, the boot scripts will need updating to point to the new image name.
qemu-img create -f qcow2 mac_hdd_ng.img 128G
Check if libvirtd service is run and usual qemu from repositiries is installed:
systemctl enable libvirtd systemctl start libvirtd systemctl status libvirtd
Setup quick networking by running the following commands.
#you may add these lined into your /etc/rc.local to apply this net after reboot. sudo ip tuntap add dev tap0 mode tap sudo ip link set tap0 up promisc on sudo ip link set dev virbr0 up sudo ip link set dev tap0 master virbr0
Note: If virbr0 network interface is not present on your system try enabling it by using the following commands,
virsh net-start default virsh net-autostart default #If virsh is not installed - install it as well as qemu/libvirt from repositories. Our qemu build should not conflict with any existing as we build it into separate custom named folder.
Now you can install MACOS. You need to run the boot-macOS-Catalina.sh script to start the installation process. But first edit it a little.
#./boot-macOS-Catalina.sh
You need to change the qemu-system-x86_64 to our recently builded qemu . change it in boot-macOS-Catalina.sh
qemu-system-x86_64 -> /usr/bin/qemundi/bin/qemu-system-x86_64
If you are running on some dedicated server without GUI you need to edit this script and add vnc option. Edit the boot-macOS-Catalina lines near to the end:
-monitor stdio \ -vga std \ -vnc 0.0.0.0:99 \ -k en-us #vnc in this case will listen on port 5999.. weird but this happens on my build. but it should work like: # -vnc <your_public_server_ip>:<desired_port_number>,password \
Remember to allow the port on firewall Also most likely you need to copy OVMF_VARS-1024x768.fd to backup folder under OSX-KVM folder (as it configured in boot-macOS-Catalina.sh):
cp OVMF_VARS-1024x768.fd backup/
Ensure that ignore_msrs is enabled:
echo 1 > /sys/module/kvm/parameters/ignore_msrs
OK run now:
./boot-macOS-Catalina.sh
If you got error :
Could not access KVM kernel module: No such file or directory qemu-system-x86_64: failed to initialize KVM: No such file or directory
Make sure that kvm module loaded
lsomd | grep kvm modprobe kvm modprobe kvm-intel
Also maybe you need to install qemu from sources:
dnf module install virt
OK run now again:
./boot-macOS-Catalina.sh
You will got into qemu console. you may also run this script under screen instead and detach later. Set vnc password in qemu-console:
(qemu) change vnc password #enter password interactively. use short 7 symbol password.
Connect with any VNC client to <your_public_server_ip>:<desired_port_number> and isntall MAC OS with GUI.
- ADD-1
Here we provide modified "run-macOC-script.sh" which will set network and set VNC password. We call it "macos-vm-powercycle.sh": The script will assume that you are running only one MACOSVM. if you run it - it will hardly shutdown any existent qemundi processes, set network, set vnc password and run MACOS VM in screen.
#!/bin/bash echo "killing existing mac os VM if exisst.. find PID:" ps aux | grep /usr/bin/qemundi/bin/qemu-system-x86_64 | awk '{print $2}' ps aux | grep /usr/bin/qemundi/bin/qemu-system-x86_64 | awk '{print $2}' | xargs -n1 kill echo starting new instance in with log to /var/log/macosxkvm.log: cd /home/OSX-KVM/ echo "change dir to:" pwd ############################################################################ # NOTE: Tweak the "MY_OPTIONS" line in case you are having booting problems! ############################################################################ # This works for Catalina as well as Mojave. Tested with macOS 10.14.6 and macOS 10.15. #set proper net on host machine: #ip link delete dev tap0 ip tuntap add dev tap0 mode tap ip link set tap0 up promisc on ip link set dev virbr0 up ip link set dev tap0 master virbr0 MY_OPTIONS="+pcid,+ssse3,+sse4.2,+popcnt,+avx,+aes,+xsave,+xsaveopt,check" # OVMF=./firmware OVMF="./" # This causes high cpu usage on the *host* side # qemu-system-x86_64 -enable-kvm -m 3072 -cpu Penryn,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on,hypervisor=off,vmx=on,kvm=off,$MY_OPTIONS\ screen -d -m /usr/bin/qemundi/bin/qemu-system-x86_64 -enable-kvm -m 16562 -cpu Penryn,kvm=on,vendor=GenuineIntel,+invtsc,vmware-cpuid-freq=on,$MY_OPTIONS\ -machine q35 \ -smp 8,cores=8 \ -usb -device usb-kbd -device usb-mouse \ -device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" \ -drive if=pflash,format=raw,readonly,file=$OVMF/OVMF_CODE.fd \ -drive if=pflash,format=raw,file=$OVMF/OVMF_VARS-1024x768.fd \ -smbios type=2 \ -device ich9-intel-hda -device hda-duplex \ -device ich9-ahci,id=sata \ -drive id=Clover,if=none,snapshot=on,format=qcow2,file=./'Catalina/CloverNG.qcow2' \ -device ide-hd,bus=sata.2,drive=Clover \ -device ide-hd,bus=sata.3,drive=InstallMedia \ -drive id=InstallMedia,if=none,file=BaseSystem.img,format=raw \ -drive id=MacHDD,if=none,file=./MyDisk.qcow2,format=qcow2 \ -device ide-hd,bus=sata.4,drive=MacHDD \ -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -device vmxnet3,netdev=net0,id=net0,mac=52:54:00:c9:18:27 \ -monitor stdio \ -vga std \ -qmp unix:/tmp/qmp-sock,server \ -vnc 138.201.5x.1xx:5599,password \ -device qemu-xhci,id=xhci -device usb-tablet,bus=xhci.0 \ -k en-us #connect to monitor and set vnc passwd: sleep 3 #echo change vnc password vncp@ss |nc -n 127.0.0.1 55555 echo '{ "execute": "qmp_capabilities" } { "execute": "set_password", "arguments": { "protocol": "vnc","password": "vncp@ss" } }' | nc -U /tmp/qmp-sock
- ADD-2
Also you may create tiny WebUI for powercycle mac os . Setup nginx/httpd server configure basic authentication and put these files into your www-root:
index.html
< center> Push the button for MAC OS VM powercycle.
All unsaved data will be lost. < /br> < /br> <form action="runscript.php" method="post"> <input type="submit" name="someAction" value="Hard Reboot" /> </form> < /center>
runscript.php
<?php $result = exec('sudo /bin/bash /<path-to macos-vm-powercycle.sh>'); var_dump($result); ?>
You also need to add permission to www-user run as sudo the bash script specified in php. Better if you will run separate nginx/httpd apache server instance and configure it only for the webui usage. However it's neccessary to add the rule to sudoers.
Edit /etc/sudoers and add line:
macuser ALL=(ALL) NOPASSWD: /bin/bash /<path-to macos-vm-powercycle.sh> #replace macos user with user you've created or with default web server user like apache or nginx (not recommended)
- ADD-3
Apache VirtHost config example:
Listen 55666 <VirtualHost 0.0.0.0:55666> DocumentRoot "/var/www/handjob/" ServerName handjob.domain.net <Directory "/var/www/handjob"> AuthType Basic AuthName "Authentication Required" AuthUserFile "/etc/httpd/.htpasswd" Require valid-user Order allow,deny Allow from all </Directory> </VirtualHost>
Remember to create basic authentication pass:
htpasswd -c /etc/httpd/.htpasswd webUIUsername
Allow port if need in iptables:
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 55666-j ACCEPT