Beta

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.

Install reims-ctl

One script builds everything from a clone of the repository: the GPU library, a QEMU on top of it, and reims-ctl. It runs on macOS on Apple silicon and on x86-64 Linux.

Before you start

  • On a Mac: Xcode's command line tools (xcode-select --install) and Homebrew.
  • On Linux: Ubuntu or Debian, or Arch or CachyOS, where the script installs the packages it needs itself. On other distributions it prints the Ubuntu package list to match. You also need KVM and a Vulkan driver for your GPU; the Linux guide covers the host.
  • Rust, through rustup. If you don't have it, the script offers to install it.

Run the installer

Clone without --recursive: the script fetches the one submodule it needs, QEMU's source, without QEMU's own submodules.

$ git clone https://github.com/steelbrain/reims-vgpu
$ cd reims-vgpu
$ scripts/install-ctl.sh

It asks before it installs anything: Homebrew packages on a Mac, apt or pacman packages through sudo on Linux, Rust through rustup. --yes answers yes to all of them. Then it:

  1. fetches QEMU's source, at the commit the checkout pins (Cargo fetches metal2vulkan the same way);
  2. builds the library and QEMU on it, in ~/.cache/reims-ctl, and installs QEMU into ~/.local/share/reims-ctl/qemu;
  3. installs reims-ctl into ~/.cargo/bin, signed on a Mac with the virtualization entitlement that installing macOS from an IPSW needs;
  4. on Linux, installs reims-util beside it, which makes an x86-64 VM's OpenCore image and downloads its macOS installer from Apple.

The first build takes a while; later ones reuse it. If ~/.cargo/bin isn't on your PATH yet, the script says so: open a new terminal.

Check the host

reims-ctl doctor checks the host and the install, and says what to do about anything it finds.

$ reims-ctl doctor
zsh — M3 Max, macOS 27
$ reims-ctl doctor
ok   host: macOS on arm64, runs vmapple-arm64 VMs
ok   files: settings in ~/.config/reims-ctl, VMs and QEMU in ~/.local/share/reims-ctl
ok   qemu: ~/.local/share/reims-ctl/qemu/current/bin/qemu-system-aarch64 (QEMU emulator version 11.1.50)
ok   audio backends: none, coreaudio, dbus, wav (default coreaudio)
ok   checkout: ~/Projects/steelbrain/reims-vgpu at c03936edf, following the development channel (development)
ok   vmapple boot ROM: /System/Library/Frameworks/Virtualization.framework/Resources/AVPBooter.vmapple2.bin
ok   virtualization entitlement: present (installs from IPSWs)
On a Mac: QEMU, the boot ROM macOS's Virtualization.framework ships, and the entitlement IPSW installs need.
ssh — Linux, RTX 5080 laptop
$ reims-ctl doctor
ok   host: Linux on x86-64, runs q35-x86_64 VMs
ok   files: settings in ~/.config/reims-ctl, VMs and QEMU in ~/.local/share/reims-ctl
ok   qemu: ~/.local/share/reims-ctl/qemu/current/bin/qemu-system-x86_64 (QEMU emulator version 11.1.50)
ok   audio backends: none, alsa, jack, oss, pa, pipewire, sndio, spice, wav (default pipewire)
ok   checkout: ~/Projects/steelbrain/reims-vgpu at 9f2e1c2c, following the development channel (development)
ok   /dev/kvm: usable
FAIL vm.max_map_count: 1048576: a 16 GiB guest needs about 1130496: sudo sysctl -w vm.max_map_count=2097152, and a file in /etc/sysctl.d to keep it
ok   vulkan: NVIDIA GeForce RTX 5080 Laptop GPU (discrete, nvidia_icd.json); llvmpipe (LLVM 23.1.1, 256 bits) (cpu, lvp_icd.json)
FAIL desktop session: neither WAYLAND_DISPLAY nor DISPLAY is set: a VM's window needs a desktop session
ok   reims-util: ~/.cargo/bin/reims-util (reims-util 0.1.0)
On Linux, run over SSH. Two lines fail, and each says why. The guest's memory needs a higher vm.max_map_count (the Linux guide explains it). There's no desktop session over SSH, so a VM started from there gets no window, though the terminal viewer still shows it.

Updating

reims-ctl update pulls the checkout and runs the installer again. In the interface, it's u. A VM that's running keeps the QEMU it started with, and the three newest QEMU builds stay installed.

$ reims-ctl update
$ reims-ctl update --channel development  # switch to the development branch first

There are two channels: stable, the master branch, and development, which gets changes first. --channel switches the checkout, and later updates stay on that channel.

Where things live

PathWhat's there
~/.local/share/reims-ctl/vmsEach VM's directory: its disk, settings (vm.toml), logs and firmware. create --dir puts one elsewhere.
~/.local/share/reims-ctl/qemuQEMU builds; current links to the newest.
~/.local/share/reims-ctl/ipswIPSWs downloaded on a Mac, kept for the next VM.
~/.local/share/reims-ctl/installersmacOS installers downloaded on Linux, kept for the next VM.
~/.config/reims-ctlvms.toml, the VMs you have, each by name and directory, and install.toml, what the installer installed, which update reads.

XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_CACHE_HOME move these, on a Mac too.