I have a Macbook Pro 2019 lying around and I want to use it's GPU for a service like Jellyfin.
This tutorial is provided for informational and educational purposes only. While every effort has been made to ensure the accuracy and completeness of the information, it is provided "as is" without any warranties, express or implied.
- Use at Your Own Risk: The instructions and code snippets presented in this Gist are intended for guidance and should be used at your own discretion and risk. The author assumes no responsibility for any damage, loss, or issues that may arise from following this tutorial.
- No Guarantee: There is no guarantee that the methods described will work flawlessly in all environments or for all specific use cases. Results may vary depending on your system configuration and other factors.
- Verification Recommended: Users are encouraged to verify information, test code in a safe environment, and consult official documentation or expert advice before implementing any solutions in a production environment.
- Disclaimer of Liability: The author shall not be held liable for any direct, indirect, incidental, consequential, or special damages arising out of or in any way connected with the use of this tutorial.
- Proxmox (bare-metal) on Macbook
- A linux VM running in Proxmox (Talos Linux)
- Jellyfin running inside a container on Talos
- Download Proxmox iso from their website.
- Burn that iso on the USB of your choice with at least 8 GB. I haven't tried 4GB but it should work as well.
Tips on how to create the USB
You can use Rufus or Balena Etcher or you can run the following commands to do it via terminal.diskutil umountDisk /dev/diskX
dd if=/proxmox.iso of=/dev/diskX status=progress bs=4M && sync
diskutil eject /dev/diskXNote:
- Please use block size of 4M because anything smaller would take very long to finish.
- It is a good practise to use sync after the dd command to ensure that all buffers are written to disk.
- Replace /dev/diskX with the identifier of your usb. You can use
diskutil listto find that out.
- Connect the usb to your laptop and boot it up. Go to the boot menu of your mac. I held the Option Key but your macbook may be different.
- Select EFI drive and follow the GUI to install proxmox on your laptop.
It is possible that when you bootup, you are unable to connect to internet even when you gave a static IP to your machine.
In my case, this was happening because networking service failed to start at boot.
If your laptop is also not connecting to internet because of networking service failing to start, you can follow these steps to resolve that.
Step 1. First verify that the cause of your failure is the same. Run the following command to see the status of the serivce.
systemctl status networkingIf this shows that it didn't succeed due to ifupdown2-pre.service then you have the same cause.
Digging further, you will see that ifupdown2-pre.service also failed due to a timeout on systemd-udev-settle.service.
Detailed diagnosis
I am also not 100% sure as to why this happens because there are too many variables. The only thing I know is that it times out wiating for all peripherals to be initialised.- For one,
systemd-udev-settleservice seemed to have been deprecated. - In my case, I also saw services like
zfs-import-scanandzfs-import-cachefailing. If the udev service was waiting on these to finalise it could be the cause of the failure.
My most prevailing guess is that it fails waiting for proxmox to claim the GPU. For some reason, the macbook's have locked down the internal gpu (in my case, Intel UHD 630) and proxmox is unable to use that. It then uses the external gpu which also was the cause of many headaches for me as I wanted to pass this to the VM.
But then again, in arch linux, I was able to see and use the internal graphics of the CPU. So, take it with a grain of salt.
In my case, the failure of networking service's during boot was due to its mandatory dependency on ifupdown2-pre service.
If you are able to see and use your networking interface by just restarting the service, you may also be able to resolve this issue in the same way.
- Verify that there is no IP address assigned to the interface of your choice.
ip a- Restart the networking service.
systemctl restart networking- Check the ip address again.
ip aIf you are seeing the ip address again, there most likely is no fundamental issues with your drivers or your hardware. You can move to the next step.
- To remove the strict dependency, go to
/lib/systemd/systemdirectory. - Open the the
networking.servicefile with your favourite editor and do the following:
Change
Requries=ifupdown2-pre.service
To
Wants=ifupdown2-pre.service
Notes
This is the directory where systemctl or systemd stores the configuration of the services it manages.All you are doing is changing the strict dependency of the networking service on the ifupdown2-pre service.
This makes it possible for the former to start even when the latter fails during boot.
So, you are not really resolving the cause of the failure but just looking away from it.
I am writing specifically for my use case (Macbook pro 2019 15inch) but the concept should apply generally.
Run the following command and look for the PCI device which is your gpu.
lspciIn my case, I saw the following output:
02:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (rev c2)
02:00.1 Audio device: Advanced Micro Devices, Inc. [AMD/ATI] Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X]
Note: Your PCI id may differ. You can run the following command to know more:
lspci -nnk | grep -A3 AMD
My output:
02:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] [1002:67ef] (rev c2)
Subsystem: Apple Inc. Radeon Pro 560X [106b:018f]
Kernel driver in use: vfio-pci
Kernel modules: amdgpu
02:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] [1002:aae0]
Subsystem: Advanced Micro Devices, Inc. [AMD/ATI] Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] [1002:aae0]
Kernel driver in use: vfio-pci
Kernel modules: snd_hda_intel
If the kernel driver in use is vfio-pci then you are already sorted out for the proxmox part and you can move to the next step.
Now, you have identified your GPU.
02:00.0PCI ID for video with device id:1002:67ef02:00.1PCI ID for audio with device id:1002:aae0
Notes
- The PCI id is the id of the PCI Lane your GPU is connected to the motherboard.
- The device id is the comabination of the vendor id and product id in hex form (excluding the 0x prefix)
- The audio and video devices are different (sort of) and claimed by different drivers as well.
In my case the gpu was claimed by the amdgpu driver instead of vfio-pci driver initially. I had to make the following changes so that this doesn't happen.
Notes
- We are doing this because if the gpu is claimed by the
amdgpudriver, then you will not be able to pass it through to the VM. Instead, running a VM with that PCI driver might just shut down the laptop. It happened with me. vfio-pciis the pci driver used by proxmox virtualisation. Any device claimed by it would be easy to pass through to a VM. That's all I know.
Now all we have to do is to make sure that your gpu is claimed by vfio-pci and not other drivers.
- Step 1: Blacklist any of the gpu related drivers.
- Step 2: Load your
vfio-pcidriver ahead of time and bind it to the ids of your gpu device. - Step 3: Turn
iommuON among other things in GRUB.
For step 1, create the following two files in the /etc/modprobe.d/ directory:
blacklist amdgpu
blacklist simple-framebuffer
blacklist efifb
blacklist fbcon
options vfio-pci ids=1002:67ef,1002:aae0
The former blacklists the relevant gpu drivers (or modules) from loading and thus preventing them from claiming the devices. The latter provides options for the vfio-pci to your devices. Please replace the ids with the relevant video and audio device ids.
For step 2, create the following file in the /etc/modules-load.d directory:
vfio
vfio_pci
vfio_iommu_type1
vfio_virqfd
This makes sure that the relevant modules are loaded.
Finally, make changes to the /etc/default/grub file and add intel_iommu=on amd_iommu=on iommu=pt vfio-pci.ids=1002:67ef,1002:aae0 pcie_acs_override=downstream,multifunction to the end of GRUB_CMDLINE_LINUX_DEFAULT value.
In my case it looks like,
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on amd_iommu=on iommu=pt vfio-pci.ids=1002:67ef,1002:aae0 pcie_acs_override=downstream,multifunction"
I haven't tested which one of these is redundant and which is truly required, but in my opinion, iommu=pt and pcie_acs_override are the most important changes to be made. If you test these, be sure to comment here.
Once, you have made all these changes, run the following commands to make sure it affects the next boot.
update-grub
update-initramfs -u -k $(uname -r)These update the final grub file as well as the initramfs image that is used during boot.
On the next reboot, you should see that your both gpu devices are being used by vfio-pci and not your the gpu drivers.
This is where things got super complicated for me. In essence, I followed the following instructions on proxmox for passing my gpu to the VM but it didnt' work.
For context, I am using Talos linux but that shouldn't be a problem as I had already loaded the amdgpu drivers in it. In essence, the issue was that somehow, talos linux's amdgpu driver had trouble locating and loading the vbios of the gpu and thus, wasn't able to initalise the device.
You can verify that by the following:
talosctl -n <NODE_IP> get devicestalosctl -n <NODE_IP> dmesg | grep -i amdtalosctl -n <NODE_IP> ls /dev/driNotes
Normally, what should happen is:- The
amdgpudriver claims the device. - The
/dev/dri/card*and the/dev/dri/render*character device files are created with relevant permissions. - And finally you are able to use the dri device files to use the gpu for whatever application inside the talos node.
However, even the first step is not succeeding.
If you see something like, amdgpu: BIOS not found or amdgpu init completed. exiting with -22 error code (this is not verbatim), we can resolve the issue by manually providing the vbios/bios/rom to the driver. For that, we need to:
- Extract the vbios of the gpu to a file.
- Provide the bios file to the VM.
- (Optional) Make sure that the
/dev/drifiles have the correct permission.
Notes
Normally, there is a simpler way to do it.- Find out, the device directory of your device and
cdinto it. Generally, it would be/sys/bus/pci/devices/0000<PCI_ID>/. - Then, run the following command to extract the rom.
echo 1 > rom
cat rom > /root/gpu.rom
echo 0 > romHowever, like always, things are not so straight-forward. For some reason, the rom is inaccessible.
- Either
amdgpudriver still claims it but releases it during boot forvfio-pcito claim it. This leads to it locking down the rom so that no other driver can access it. - OR the Macbook firmware has locked it down and
amdgpudriver in the proxmox doesn't need it but the driver implementation used by Talos does need it for initalisation, leaving me into this weird position where I am unable to extract the rom but it is needed by Talos to initialise the device.
I tried every possible way to prevent amdgpu from claiming it but unfortunately, it didn't work as rom kept saying "Input/Output error". For the initiated, this error might be decipherable but for me, it was just a blackbox. However, I found a very special post on reddit which helped me do what I wanted but in a different manner.
- First create a live usb for arch linux. I used this OS but other OSs could also work. Just download the ISO from their website and following the same steps when you created the proxmox usb.
- Once, you have the usb, boot using it as you had with the proxmox one. Just follow the default steps of installation and you will soon find yourself at the arch shell. Note that you may see black screen for more than 10s but this is init and should mostly be done within 30s. You will also have to wait for the
udev-settleservice to fail (around 3 minutes). - If you see color in your shell, it most likely means that it is using a gpu. You can run the following commands to verify the same.
lsmod | grep -i amdgpulspci -nnk | grep -A3 -i amdls /dev/driVerify which card is yours (in case there are many). You should see a symlink with your PCI device id pointing to one of the /dev/dri/card* character files.
ls -l /dev/dri/by-pathYou can now go the kernel debug directory to fetch the bios. Here replace 0 with the card number you found above.
cat /sys/kernel/debug/dri/0/amdgpu_vbios > vbios.romUse scp or the like to transfer this rom file to your computer when you are done. I recommend scp and not the usb drive because the latter might not be mountable on your personal device.
Notes
Just want to share what type of VM worked for me. I just need to change the machine type to `qm35`, provide an EFI disk and add the PCI device (only the video PCI device would do) with all functions and `PCIe or express enabled`.- Go to the VM conf file of your VM and add the following to the end of your PCI device configuration.
hostpci0: 0000:02:00,pcie=1,romfile=gpu.rom
Note that your bios rom file (named here gpu.rom) should reside in /usr/share/kvm/ as this is where the VM will look for if you use /gpu.rom path.
Now, the VM should be able to boot correctly and you can use the following command to verify.
ls /dev/driIn case you are like me and you don't want to run the container as root on the talos node, you can use the following talos node configuration to make sure that the conventional group (video) has access to the device.
machine:
udev:
rules:
- SUBSYSTEM=="drm", KERNEL=="renderD*", GROUP="44", MODE="0660"
- SUBSYSTEM=="drm", KERNEL=="card*", GROUP="44", MODE="0660"talosctl patch mc -n <NODE_IP> -p @patch.yaml --mode rebootVoila, you should now be able to provide your Macbook GPU to your application container running on Talos Node which is a VM on proxmox which is running bare metal on macbook. Convluted but...
I will add a few more things:
- I don't have much knowledge about Linux kernel and its subsystems. If there is any terminology that I have wrongly used, please don't hestiate to comment.
- I followed what worked for me and since, I spent almost 2 days on this, there might be redundant things that I did and my setup may have even worked without those. If this is the case and you have found a better and leaner method, please comment and I will make changes to the gist.
- Finally, although, this worked for me, it may not for you. Just in case, I will share the exact versions of different hardware/softwares I used:
- Laptop: Macbook Pro 2019 15inch with i7 processor and 4GB AMD Radeon graphics.
- Hypervisor OS: Proxmox VE 8.4.0
- Talos Linux (Worker node): Factory link
- Arch linux:
archlinux-2025.08.01-x86_64.iso