Skip to main content

macOS VPS Installation Guide — Proxmox VE (Intel and AMD) | Sonoma, Sequoia and Tahoe

LEGAL DISCLAIMER: In accordance with Apple's End User License Agreement (EULA), macOS can only be run on Apple-branded hardware. This guide is published for educational and academic purposes. The responsibility of usage belongs entirely to the user.

This guide provides step-by-step instructions for installing a macOS virtual machine on Proxmox VE. It is a comprehensive resource for installing macOS Sonoma (14), Sequoia (15), and Tahoe (26) on Intel and AMD-based servers using the LongQT-sea/OpenCore-ISO project, hiding VM detection with VMHide, configuring SMBIOS, and applying performance optimizations.

If you don't want to deal with the installation process, you can use a ready-made macOS VPS: MacOS VPS


Requirements

  • Proxmox VE 8.x (8.4+ recommended)
  • Intel VT-x or AMD-V supported processor
  • At least 4 CPU Cores
  • At least 8 GB RAM (allocated for the VM)
  • At least 100 GB of free disk space
  • Internet access (macOS Recovery installation downloads ~15 GB from Apple servers)
  • A network running with DHCP or NAT configuration that can provide internet to the VM

What is LongQT-sea/OpenCore-ISO?

It is a pre-configured OpenCore EFI project used to run macOS in a virtual machine. It offers a clean ISO-based approach that works on Intel and AMD processors, containing pre-configured kexts and config.plist. It allows installing macOS Sonoma, Sequoia, and Tahoe directly on Proxmox without unnecessary steps like manual EFI editing, OCLP, or TPM.

Source: GitHub — LongQT-sea/OpenCore-ISO


A. File Preparation (Proxmox Shell)

1. Download OpenCore ISO

wget https://github.com/LongQT-sea/OpenCore-ISO/releases/download/v0.7/LongQT-OpenCore-v0.7.iso \
-O /var/lib/vz/template/iso/LongQT-OpenCore-v0.7.iso

2. Download macOS Recovery (OSX-KVM method)

SECURITY: The macOS Recovery image is downloaded directly from Apple's CDN servers (swcdn.apple.com). No third-party sources are used; the file is Apple's signed original image.

apt install -y dmg2img git python3
git clone --depth 1 https://github.com/kholia/OSX-KVM.git /tmp/OSX-KVM
cd /tmp/OSX-KVM
python3 fetch-macOS-v2.py

When the script runs, a version list will appear:

1. High Sierra (10.13)
2. Mojave (10.14)
3. Catalina (10.15)
4. Big Sur (11.7)
5. Monterey (12.6)
6. Ventura (13)
7. Sonoma (14) - RECOMMENDED
8. Sequoia (15)
9. Tahoe (26)
  • Type 7 for Sonoma
  • Type 8 for Sequoia
  • Type 9 for Tahoe
dmg2img -i /tmp/OSX-KVM/BaseSystem.dmg -o /var/lib/vz/template/iso/BaseSystem.img

B. Creating the VM (Proxmox Web UI)

  • VM ID: 900 (or any empty ID)
  • Name: macOS-VM
  • ISO Image: LongQT-OpenCore-v0.7.iso
  • Guest OS Type: Linux > version 6.x - 2.6 Kernel
  • Graphic Card: VMware compatible
  • Machine: q35
  • BIOS: OVMF (UEFI)
  • EFI Disk: Enabled
  • Pre-Enroll Keys: OFF
  • SCSI Controller: VirtIO SCSI
  • QEMU Guest Agent: Enabled
  • TPM: OFF
  • Hard Disk: VirtIO Block, 100GB, Cache: Write back (unsafe)
  • CPU Cores: 4 (assign the number of cores as 2, 4, or 8), Sockets: 1, Type: kvm64 (will be overridden with args)
  • RAM: 8192 MB, Ballooning: OFF
  • Network: VirtIO, Bridge: vmbr0

C. Mounting BaseSystem.img

BaseSystem.img is a raw disk image created with dmg2img.

ISSUE: If mounted as media=cdrom, OpenCore will not detect it as a bootable source.

SOLUTION: Import BaseSystem.img as a real disk. Choose the command according to your storage backend:

If using local-lvm:

qm importdisk 900 /var/lib/vz/template/iso/BaseSystem.img local-lvm
qm set 900 --ide2 local-lvm:vm-900-disk-2,cache=unsafe

If using local-zfs:

qm importdisk 900 /var/lib/vz/template/iso/BaseSystem.img local-zfs
qm set 900 --ide2 local-zfs:vm-900-disk-2,cache=unsafe

NOTE: To see which storage is available: pvesm status You must use the same storage name in both commands (importdisk and qm set must match). VM ID 900 is used in all commands in this guide. If you created a different ID, replace 900 in the commands with your own VM ID.

Adjust the boot order (ensure OpenCore ISO and BaseSystem disk appear at boot):

qm set 900 --boot order='ide0;virtio0;ide2;net0'

NOTE: The OpenCore ISO (ide0) MUST REMAIN as media=cdrom.


D. CPU Configuration (Intel and AMD)

Basic CPU and USB Settings

The following args line is used for both Intel and AMD:

qm set 900 --tablet 0
qm set 900 --args "-cpu Skylake-Client-v4,vendor=GenuineIntel,+invtsc,+hypervisor,kvm=on,vmware-cpuid-freq=on -device qemu-xhci,id=xhci -device usb-kbd,bus=xhci.0 -device usb-tablet,bus=xhci.0 -global nec-usb-xhci.msi=off -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off"

NOTE: We disable Proxmox's built-in tablet setting (--tablet 0) because we define USB input devices ourselves via QEMU args.

CPU flag explanations:

  • vendor=GenuineIntel — Reports CPUID as Intel. Mandatory on AMD, recommended for consistency on Intel.
  • +invtsc — Invariant TSC, critical for timing synchronization (without this, the kernel will hang).
  • +hypervisor — Reports that it is running in a VM.
  • kvm=on — KVM acceleration enabled.
  • vmware-cpuid-freq=on — Necessary for macOS to correctly read the CPU frequency.

USB and stability flag explanations:

  • -device qemu-xhci,id=xhci — Necessary USB 3.0 controller for macOS Tahoe and Sonoma 14.4+.
  • -device usb-kbd,bus=xhci.0 — Keyboard input via XHCI.
  • -device usb-tablet,bus=xhci.0 — Absolute positioning for the mouse to work properly in VNC.
  • -global nec-usb-xhci.msi=off — Solves the MSI interrupt issue of the macOS XHCI driver; without this, the mouse freezes.
  • -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off — Prevents ACPI hotplug conflicts on the Q35 chipset.

Special Warning for AMD

Proxmox automatically adds enforce,+kvm_pv_eoi,+kvm_pv_unhalt flags from the cpu: line. These flags prevent macOS boot on AMD.

Solution: Change cpu: kvm64 in the config file:

cpu: kvm64
args: -cpu Skylake-Client-v4,vendor=GenuineIntel,+invtsc,+hypervisor,kvm=on,vmware-cpuid-freq=on -device qemu-xhci,id=xhci -device usb-kbd,bus=xhci.0 -device usb-tablet,bus=xhci.0 -global nec-usb-xhci.msi=off -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off

This way, Proxmox defines a simple kvm64, and Skylake-Client-v4 in the args overrides it at the QEMU level.

TSC Issue with Multi-Core (Intel and AMD)

To avoid issues with multi-core support, allocate 2, 4, or 8 cores for the VM. If you still experience boot issues, change the GRUB setting on the Proxmox Main machine:

  1. Open the /etc/default/grub file.
  2. Find the GRUB_CMDLINE_LINUX_DEFAULT line (it usually says "quiet").
  3. Change the line to the following:
GRUB_CMDLINE_LINUX_DEFAULT="quiet tsc=reliable"
  1. Save and update GRUB, then restart the Proxmox host:
update-grub && reboot

E. Resolution Setting (Optional) (1920x1080)

Increasing the resolution will decrease graphics performance, so this is provided as an optional step.

Method 1 — OVMF UEFI Setup: During VM boot press ESC/F2 > Device Manager > OVMF Platform Configuration > 1920x1080

Method 2 — QEMU args (easier):

Add -global OVMF.Resolution=1920x1080 to the end of the args line:

args: -cpu Skylake-Client-v4,vendor=GenuineIntel,+invtsc,+hypervisor,kvm=on,vmware-cpuid-freq=on -device qemu-xhci,id=xhci -device usb-kbd,bus=xhci.0 -device usb-tablet,bus=xhci.0 -global nec-usb-xhci.msi=off -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off -global OVMF.Resolution=1920x1080

Set VGA memory to 256MB:

qm set 900 --vga vmware,memory=256

F. macOS Installation Steps

INTERNET REQUIRED: The macOS Recovery installation downloads the full OS from Apple servers. The VM needs to access the internet. If the VM is connected with bridge=vmbr0 in Proxmox and there is DHCP on the host network, it will automatically get an IP; otherwise, you need to install a simple DHCP server on Proxmox. Since LongQT's OpenCore EFI includes the VirtIO network kext, the network will work during the Recovery phase. Depending on the installation size, 10-20 GB will be downloaded, which may take a long time on slow connections.

  1. Start the VM, and select macOS Base System from the OpenCore boot menu.
  2. Select Disk Utility > Choose the VirtIO disk (labeled APPLE Inc. Virtio) > select Erase and name the disk as "macos" (APFS + GUID Partition Map).
  3. Close Disk Utility > select Reinstall macOS (Sonoma, Sequoia, or Tahoe).
  4. The VM will restart several times during the installation - it will automatically start each time.
  5. Once the installation is complete, follow the setup wizard.
  6. SKIP the iCloud login (until SMBIOS is configured).

G. Post-Install (Copy OpenCore to Disk)

Using Finder:

  1. Open the LongQT-OpenCore CD on the desktop.
  2. Run Mount_EFI.command > Select the macOS disk.
  3. Copy the EFI folder from LongQT-OpenCore > EFI_RELEASE to the mounted EFI volume.

If you want to use the Terminal, use these commands:

First, search for SSH in Settings, add the user you created in the remote login section, and enable the remote login switch.

sudo diskutil mount disk0s1
cp -R /Volumes/LongQT-OpenCore/EFI_RELEASE/EFI /Volumes/EFI/

Install Python 3:

Using Finder: Open the LongQT-OpenCore CD > Double-click the Install_Python3.command file > The Terminal will open and install it automatically.

If you want to use the Terminal:

/Volumes/LongQT-OpenCore/Install_Python3.command

If it gives a permission error:

chmod +x /Volumes/LongQT-OpenCore/Install_Python3.command
/Volumes/LongQT-OpenCore/Install_Python3.command

Remove ISOs:

  1. Shut down the VM.
  2. From Proxmox Hardware, detach and remove the OpenCore ISO and BaseSystem disk.
  3. Update the boot order: qm set 900 --boot order='virtio0;net0'
  4. Start the VM.

H. VMHide — Hiding VM Detection

VMHide is a Lilu plug-in used to trick services that detect macOS running in a virtual machine (especially iCloud and Apple ID).

Source: VMHide GitHub

Installation:

  1. Update Lilu.kext (at least v1.7.0 is required). It should already be included in the OpenCore EFI.
  2. Download VMHide.kext using Terminal:
cd ~/Downloads
curl -L -o VMHide-2.0.0.zip https://github.com/Carnations-Botanica/VMHide/releases/download/2.0.0/VMHide-2.0.0-RELEASE.zip
unzip VMHide-2.0.0.zip
  1. Mount the EFI:
sudo diskutil mount disk0s1
  1. Copy VMHide.kext to EFI:
cp -R ~/Downloads/VMHide.kext /Volumes/EFI/EFI/OC/Kexts/
  1. Add the VMHide.kext entry to the config.plist file:
plutil -insert Kernel.Add -json '{"MaxKernel":"","MinKernel":"","BundlePath":"VMHide.kext","Comment":"VMHide.kext","Enabled":true,"ExecutablePath":"Contents/MacOS/VMHide","PlistPath":"Contents/Info.plist","Arch":"Any"}' -append /Volumes/EFI/EFI/OC/config.plist

Verification — VMHide should appear in the list:

plutil -extract Kernel.Add json -o - /Volumes/EFI/EFI/OC/config.plist | grep -o '"VMHide.kext"'
  1. Add vmhState=enabled to the boot args. First, view the current boot-args value:
plutil -extract NVRAM.Add.7C436110-AB2A-4BBB-A880-FE41995C9F82.boot-args raw -o - /Volumes/EFI/EFI/OC/config.plist

The output of the previous command is your current boot-args value (for example, keepsyms=1). Add a space and then vmhState=enabled to the end of this value:

plutil -replace NVRAM.Add.7C436110-AB2A-4BBB-A880-FE41995C9F82.boot-args -string "keepsyms=1 vmhState=enabled" /Volumes/EFI/EFI/OC/config.plist

WARNING: The keepsyms=1 part above is an example. If you have a different value in your output, type that, and add vmhState=enabled to the end.

VMHide States:

  • enabled — Hides the VMM state (recommended)
  • disabled — VMHide is disabled
  • strict — Returns VMM 0 for all operations

I. SMBIOS Configuration (for iCloud / iMessage)

A unique SMBIOS must be defined for each macOS VM. If multiple machines connect to Apple servers with the same SMBIOS, the account may be locked.

Step 1 — Download and run GenSMBIOS (macOS Terminal):

cd ~/Downloads
curl -L -o GenSMBIOS.zip https://github.com/corpnewt/GenSMBIOS/archive/refs/heads/master.zip
unzip GenSMBIOS.zip
cd GenSMBIOS-master
chmod +x GenSMBIOS.command && ./GenSMBIOS.command

Step 2 — Install MacSerial:

When the menu opens, type 1 > Enter. MacSerial will be downloaded.

Step 3 — Select config.plist:

Type 2 > Enter. Paste the following line as the path:

/Volumes/EFI/EFI/OC/config.plist

NOTE: Instead of just mounting EFI, run this first: sudo diskutil mount disk0s1

Step 4 — Generate SMBIOS:

Type 3 > Enter. Type iMacPro1,1 as the model > Enter.

The script automatically generates a unique Serial, Board Serial, SmUUID, and ROM, and writes them to config.plist.

Step 5 — Verify the serial number:

Go to the Apple Check Coverage page and enter the generated Serial Number. The result should return "not valid" or "unable to check". This indicates that the serial number does not belong to a real Mac and is safe to use.

If a valid device appears (belonging to someone else's Mac), return to GenSMBIOS and generate a new SMBIOS with 3.

Step 6 — Restart the VM:

If the SMBIOS has been saved correctly, you can now log in with iCloud and Apple ID.


J. Configuration for VPS (macOS Terminal)

# Enable SSH
sudo systemsetup -setremotelogin on

# Disable automatic updates
sudo softwareupdate --schedule off
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -bool false
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool false
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate CriticalUpdateInstall -bool false

# Disable sleep modes
sudo pmset -a sleep 0
sudo pmset -a displaysleep 0
sudo pmset -a disksleep 0

# Disable screensaver
defaults -currentHost write com.apple.screensaver idleTime 0

# Leave Firewall ON
sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1
  • Screen Sharing (VNC): System Settings > General > Sharing > Screen Sharing ON
  • Firewall: Do not disable, leave it ON — SSH and VNC will already pass through as signed applications

Since there is no real GPU in the virtual machine, macOS animations and visual effects consume unnecessary resources. The following commands disable animations, switch to software rendering, and lighten the system:

# Disable transparency and motion effects
defaults write com.apple.universalaccess reduceTransparency -bool true
defaults write com.apple.universalaccess reduceMotion -bool true

# Disable Dock animations
defaults write com.apple.dock launchanim -bool false
defaults write com.apple.dock autohide-delay -float 0
defaults write com.apple.dock autohide-time-modifier -float 0
defaults write com.apple.dock expose-animation-duration -float 0.1
defaults write com.apple.dock no-glass -bool true
defaults write com.apple.dock no-bouncing -bool true
defaults write com.apple.dock magnification -bool false
defaults write com.apple.dock show-recents -bool false
defaults write com.apple.dock mineffect -string "scale"
defaults write com.apple.dock springboard-show-duration -float 0
defaults write com.apple.dock springboard-hide-duration -float 0
defaults write com.apple.dock springboard-page-duration -float 0
defaults write com.apple.dock workspaces-swoosh-animation-off -bool true
defaults write com.apple.dock minimize-to-application -bool true
defaults write com.apple.dock slow-motion-allowed -bool false
defaults write com.apple.dock missioncontrol-animation-duration -float 0.1
defaults write com.apple.dock workspaces-edge-delay -float 0
defaults write com.apple.dock springboard-blur-radius -int 0

# Disable general window and system animations
defaults write NSGlobalDomain NSAutomaticWindowAnimationsEnabled -bool false
defaults write NSGlobalDomain NSWindowResizeTime -float 0.001
defaults write -g NSMenuAnimationDuration -float 0
defaults write -g NSPopUpMenuAnimationDuration -float 0
defaults write -g NSComboBoxAnimationDuration -float 0
defaults write -g NSToolbarAnimationDuration -float 0
defaults write -g NSToolbarFullScreenAnimationDuration -float 0
defaults write -g NSSheetAnimationEnabled -bool false
defaults write -g NSWindowAnimationsEnabled -bool false
defaults write -g NSViewAnimationsEnabled -bool false
defaults write -g NSScrollAnimationEnabled -bool false
defaults write -g NSUseAnimatedFocusRing -bool false
defaults write -g NSScrollViewRubberbanding -bool false
defaults write -g NSOverlayScrollerHideDelay -float 0
defaults write -g QLPanelAnimationDuration -float 0
defaults write -g NSWindowSupportsAutomaticFullScreen -bool false
defaults write -g NSFullScreenAnimationDuration -float 0
defaults write NSGlobalDomain com.apple.springing.enabled -bool false

# Disable Finder animations
defaults write com.apple.finder DisableAllAnimations -bool true
defaults write com.apple.finder AnimateInfoPanes -bool false
defaults write com.apple.finder AnimateSnapToGrid -bool false

# GPU / Rendering — Switch to software renderer
sudo defaults write /Library/Preferences/com.apple.windowserver UseMetal -bool false
sudo defaults write /Library/Preferences/com.apple.windowserver UseOpenGL -bool false
sudo defaults write /Library/Preferences/com.apple.windowserver HardwareAccelerated -bool false
sudo defaults write /Library/Preferences/com.apple.windowserver EnableShadows -bool false
sudo defaults write /Library/Preferences/com.apple.CoreDisplay useMetal -bool false
sudo defaults write /Library/Preferences/com.apple.CoreDisplay useIOP -bool false
defaults write com.apple.CoreAnimation useSoftwareRenderer -bool true
defaults write com.apple.opengl ForceSoftwareRenderer -bool true
defaults write com.apple.CoreImage CISoftwareRenderer -bool true
defaults write com.apple.screencapture disable-shadow -bool true
defaults write com.apple.GPU gpuSwitchingPolicy -int 0

# Disable Spotlight indexing
sudo mdutil -a -i off

# Disable crash reporter, auto update, Time Machine
defaults write com.apple.CrashReporter DialogType -string "none"
defaults write com.apple.SoftwareUpdate AutomaticCheckEnabled -bool false
defaults write com.apple.TimeMachine DoNotOfferNewDisksForBackup -bool true

# Disable Siri
defaults write com.apple.assistant.support "Assistant Enabled" -bool false

# Other optimizations
defaults write com.apple.spotlight AnimationDuration -float 0
defaults write -g CGFontRenderingFontSmoothingDisabled -bool true
defaults write com.apple.frameworks.diskimages skip-verify -bool true
defaults write com.apple.frameworks.diskimages skip-verify-locked -bool true
defaults write com.apple.frameworks.diskimages skip-verify-remote -bool true
defaults write com.apple.mail DisableReplyAnimations -bool true
defaults write com.apple.mail DisableSendAnimations -bool true
defaults write -g NSDocumentSaveNewDocumentsToCloud -bool false
defaults write com.apple.finder WarnOnEmptyTrash -bool false
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool true
defaults write -g userMenuExtraStyle -int 1

# Apply changes
killall Dock && killall Finder && killall SystemUIServer

L. Final Working VM Config File

For reference, a successfully working /etc/pve/qemu-server/900.conf:

NOTE: local-lvm is used in the example below. If your server has local-zfs, replace local-lvm with local-zfs in the disk lines.

agent: 1
args: -cpu Skylake-Client-v4,vendor=GenuineIntel,+invtsc,+hypervisor,kvm=on,vmware-cpuid-freq=on -device qemu-xhci,id=xhci -device usb-kbd,bus=xhci.0 -device usb-tablet,bus=xhci.0 -global nec-usb-xhci.msi=off -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off -global OVMF.Resolution=1920x1080
balloon: 0
tablet: 0
bios: ovmf
boot: order=virtio0;net0
cores: 4
cpu: kvm64
efidisk0: local-lvm:vm-900-disk-0,efitype=4m,size=4M
machine: q35
memory: 8192
name: macOS-VM
net0: virtio=XX:XX:XX:XX:XX:XX,bridge=vmbr0,firewall=1
numa: 0
ostype: l26
scsihw: virtio-scsi-pci
sockets: 1
vga: vmware,memory=256
virtio0: local-lvm:vm-900-disk-1,cache=unsafe,iothread=1,size=100G

M. Encountered Issues and Solutions

1. Only Reset NVRAM and Toggle SIP appear in the OpenCore menu

Cause: BaseSystem.img was mounted as media=cdrom. Solution: Import it as a real disk using qm importdisk.

2. Falling back to PXE boot (BdsDxe: failed to load Boot)

Cause: The OpenCore ISO is missing from the boot order or not connected as ide0. The VM cannot find any bootable source and falls back to the network (PXE). Solution: Ensure the OpenCore ISO is connected as ide0 with media=cdrom. Set the boot order:

qm set 900 --boot order='ide0;virtio0;ide2;net0'

Check the configuration: qm config 900 — The OpenCore ISO should appear in the ide0 line.

3. Hanging during kernel load (#[EB.LD.LKC|R.2] hang)

Cause: Missing CPU flags (+invtsc, vmware-cpuid-freq=on). Solution: Use the complete flag set.

4. Proxmox CPU flag conflict (AMD)

Cause: The kvm_pv_eoi/kvm_pv_unhalt flags automatically added by Proxmox prevent macOS from booting. Solution: Set cpu: kvm64 and define the real CPU model in the args: line.

5. White desktop

Cause: VMware VGA cannot render dynamic wallpapers. Solution: Choose a static image from System Settings > Wallpaper.

6. The 1280x720 resolution does not change

Solution: Add -global OVMF.Resolution=1920x1080 from the OVMF Setup or to the args. VGA memory must be 256MB.

7. Falling back to PXE boot after removing the ISO

Cause: EFI copying failed. Solution: Temporarily re-add the OpenCore ISO, and verify the EFI copying process.