How well it runs can still depend on your host and its GPU. Metal, macOS are trademarks of Apple Inc. Reims vGPU is an independent project and is not affiliated with, sponsored by, or endorsed by Apple Inc.
A macOS VM on x86-64 Linux
On x86-64 Linux, a VM runs x86-64 macOS on QEMU's q35 machine under KVM, booted through OpenCore, with its GPU on Vulkan through metal2vulkan. macOS 26 Tahoe is the newest release, and the last for Intel Macs. reims-ctl downloads the installer from Apple and makes the VM's OpenCore image; you install macOS from Recovery, as on a Mac, then set one preference in the guest.
Prepare the host
- KVM.
/dev/kvmmust be usable by you: virtualization on in the firmware, and you in thekvmgroup (sudo usermod -aG kvm $USER, then log in again). - A Vulkan driver for your GPU.
reims-ctl gpuslists the GPUs a VM can be given; by default it takes the first discrete GPU, then the first integrated one. - A higher
vm.max_map_count. The library's views of guest memory take a kernel mapping for each run of guest pages, about 64 per MiB, so the stock limit of 65,530 is far too low. 2,097,152 covers a guest of up to 30 GiB.reims-ctland the installer warn when it's too low. - On an AMD GPU, guest memory reaches the GPU through
/dev/udmabuf, so you need to be in the group that owns it:kvmon Ubuntu, the same group as/dev/kvm. - A desktop session, Wayland or X11, for the VM's windows. Over SSH, the terminal viewer shows the screen instead.
$ sudo sysctl -w vm.max_map_count=2097152
$ echo vm.max_map_count=2097152 | sudo tee /etc/sysctl.d/90-reims-vgpu.conf # keep it
$ reims-ctl gpus$ reims-ctl gpus
By default the library takes the first discrete GPU, then the first integrated one.
1. NVIDIA GeForce RTX 5080 Laptop GPU [10de:2c19] /usr/share/vulkan/icd.d/nvidia_icd.json
2. llvmpipe (LLVM 23.1.1, 256 bits) [10005:0000] /usr/share/vulkan/icd.d/lvp_icd.json
Give a VM one with: reims-ctl set NAME --gpu NUMBERreims-ctl doctor checks all of it; Install shows its output on this laptop.
Create the VM
$ reims-ctl create mac --macos tahoereims-ctl asks Apple for Tahoe's recovery image, about 1 GB, and makes the VM's OpenCore image, its firmware and a new 128G disk. The OpenCore image presents the VM as a Mac with an identity of its own. Downloads are kept in ~/.local/share/reims-ctl/installers for your next VM, and an interrupted one picks up where it stopped. With the image already there, the create took 6 seconds:
$ reims-ctl create mac --macos tahoe
mac: asking Apple for the macOS Tahoe 26 recovery image
mac: Apple's product 140-93589
mac: checking what is already downloaded
mac: checking what is already downloaded: 1% of 961 MB
mac: checking what is already downloaded: 100% of 961 MB
mac: ~/.local/share/reims-ctl/installers/macOS-Tahoe-online-installer.dmg is already here and checks out
mac: creating the disk
mac: building the OpenCore 1.0.8 image
mac: Wrote ~/.local/share/reims-ctl/vms/mac/opencore.qcow2
mac: writing OVMF's code and variables
mac: Wrote ~/.local/share/reims-ctl/vms/mac/OVMF_CODE.fd and ~/.local/share/reims-ctl/vms/mac/OVMF_VARS.fd
mac: OpenCore presents the VM as an iMac20,1, serial C02•••••••••
mac: converting macOS-Tahoe-online-installer.dmg to a raw image
mac: done
created mac in ~/.local/share/reims-ctl/vms/mac
To install macOS, start mac: OpenCore boots its installer into macOS Recovery. If the VM's disk is new, open Disk Utility, erase it (QEMU HARDDISK Media) as APFS and quit Disk Utility. Then pick Reinstall macOS. Once macOS is installed, eject the installer (reims-ctl eject mac) and set Metal's error mode (README).Other ways to get macOS:
| Option | What it does |
|---|---|
--macos tahoe | Apple's recovery image for that release: a name (tahoe), a number (26) or latest. It downloads the newest build as it installs. |
--macos 26.6.2 --offline | One exact release (or a build, such as 25G83), 13 to 20 GB, which installs with no network. |
--installer FILE | An installer of your own, such as a BaseSystem.dmg; a DMG is converted to a raw image in the VM's directory. |
--disk FILE --opencore FILE | A disk that already has macOS, copied (a reflink where the file system can, or --disk-mode in-place), with the OpenCore image it booted from, OVMF_CODE.fd and OVMF_VARS.fd beside it. It keeps its Mac's identity. |
In the interface, n opens the same create as a form, with a list of the macOS versions to pick from.
Install macOS
reims-ctl start mac. OpenCore boots the installer into macOS Recovery.- Open Disk Utility, select the VM's disk (QEMU HARDDISK Media), erase it as APFS, and quit Disk Utility.
- Pick Reinstall macOS. With an offline installer, open Utilities › Terminal and run
sh /Volumes/Installer/install-macos.shinstead. - Once macOS is installed, take the installer out:
$ reims-ctl eject macTo get back the space installers take, delete them from ~/.local/share/reims-ctl/installers once your VMs' installers are ejected.
Set Metal's error mode, once
An x86-64 guest needs one setting before its desktop works. Without it, macOS's icon service crashes as soon as it starts, and a fresh install never gets a working desktop: it stays on its wallpaper with no menu bar and no Dock, or comes up gray with a menu bar but no Dock. Since you can't count on a desktop yet, set it from macOS Recovery:
- Turn on the VM's boot selection, so OpenCore shows its picker: in the interface, e on the VM, switch Boot selection on and save, or run:It's off by default, and then the VM boots straight into macOS. (If your
$ reims-ctl update-opencore mac --boot-selectionupdate-opencoredoesn't know--boot-selection, yourreims-ctlpredates it and the picker is always on: skip this step.) - Start the VM and pick the Recovery entry in OpenCore's picker before it boots macOS. It waits 5 seconds; any arrow key stops the countdown, and Space shows the entry if it's hidden.
- In Recovery, open Utilities › Terminal and type this as one line:
$ cd /Volumes/*Data/Library/Preferences && defaults write "$PWD/.GlobalPreferences" METAL_ERROR_MODE -int 5 && chmod 644 .GlobalPreferences.plist && reboot
The VM restarts only if every step worked. If it doesn't, read the error: the setting wasn't saved, and macOS keeps crashing until it is. Don't drop the chmod; without it, macOS can't read the setting. Then pick macOS in the picker, and the desktop comes up. Turn boot selection off again the same way if you like.
If you already have a desktop, run this in its Terminal instead, then restart:
$ sudo defaults write /Library/Preferences/.GlobalPreferences METAL_ERROR_MODE -int 5If a Dock icon stays blank afterwards, clear the Dock's icon cache:
$ rm -rf "$(getconf DARWIN_USER_CACHE_DIR)com.apple.dock.iconcache"; killall DockKeep the OpenCore image current
A VM's OpenCore image comes from the reims-util that made it, and a newer reims-util's image carries more. Notably, an older one lacks ReimsVgpu.kext, which macOS 26 needs for a display wider than 2048 pixels and for GPU-accelerated Chrome; the VM's details in the interface say when it's missing. update-opencore makes a new image presenting the same Mac, its model, serial number, MLB, UUID and ROM read from the old one, so macOS sees no new machine. The VM keeps its OVMF variables, which hold its boot entries, and its boot selection. Anything else you changed in the old image isn't carried over.
$ reims-ctl stop mac
$ reims-ctl update-opencore mac # or U on the VM in the interfacereims-ctl update installs the reims-util this reims-ctl needs, so run it first if you haven't lately.
What a VM looks like
$ reims-ctl show macos-26
macos-26
state running (pid 81348)
kind x86-64 macOS guest (q35 and OpenCore, KVM)
directory ~/.local/share/reims-ctl/vms/macos-26
cpus 8
memory 16G
disk disk.qcow2 (qcow2)
displays 1 x 3840x2400 HiDPI (looks like 1920x1200), borderless
gpu NVIDIA GeForce RTX 5080 Laptop GPU
opencore ~/.local/share/reims-ctl/vms/macos-26/opencore.qcow2
installer none
cpu model Skylake-Client-noTSX-IBRS
audio on
network user, mac 52:54:00:ed:2a:d9, ssh on 127.0.0.1:2222
logs on (info)
stop timeout 90 sOptions worth knowing
--gpupicks the GPU:auto, a number or name fromreims-ctl gpus, or a Vulkan ICD JSON file.--ssh-port 2222forwards port 2222 on 127.0.0.1 to the guest's SSH, once you turn on Remote Login in macOS.reims-ctl set mac --graphics vmware-svgaruns the VM on QEMU's VMware SVGA instead, one display with no GPU acceleration in QEMU's own window: a fallback for telling a host problem from a guest one.--graphics reims-vgpuswitches back.- Audio is on by default, as a USB audio device on the host's sound. Keep it on: without an output device, Safari's media players, YouTube's among them, fail.
Known differences on x86-64
- Finder shows a file's type icon instead of a thumbnail for images and videos: macOS's thumbnail extensions end when they first look for Metal's devices, and no setting in the guest avoids it.
- VMs have no ACPI sleep (a guest woken from S3 loses its display). macOS turns the display off instead, and input through the window turns it back on.