[x86-64] LE 12 as a Proxmox VM with GPU pass-through

  • Goal:

    I have a GMKtec G3 plus mini pc, with an Intel N150 CPU. I wanted to run Proxmox on it to host my home virtual machines (VMs)/containers. The most crucial role that the system was bought for was serving as my bedroom LibreELEC to drive my TV. Output would be through the (looking from the back-side) left-side HDMI port (WARNING: the right-side HDMI port is prolly a DP port with an HDMI interface, possibly driven by buggy firmware!)

    In the following I'll use host, hypervisor and guest to refer the physical system, PVE and LE virtual machine, respectively,

    No attempts have, or will be, made to support eARC and stuff!

    Intended audience:

    You should probably feel at home with the hypervisor. It's an excellent one with a very friendly community. Plus. its latest versions have automated device passthrough to guests a lot.


    Initial setup:

    Make sure that on the system UEFI is enabled as well as all virtualization options (Intel VT, VT-d, IO-SRV if present).

    I will not cover the hypervisor initial installation procedure. I followed the defaults and that was it.

    You'll need a copy of a specially created LE build by sky42, see RE: LE 12.0 added lvm2, luks (dm-crypt, veracrypt), mdraid, ext4 encryption (NOTE: As of July 7th, LE12 nightly does not run with the N150 GPU (prolly due to the kernel used). OTOH, LE13 nightly runs just fine, but I selected sky42 's build since all my addons are basically for LE12 (and they work flawlessly. From the looks of it LE12 nightly will never play along with the N150, as long as it is based on the 6.8 kernel).

    From the link, download the img.gz version, and write it to a thumb drive using the LibreELEC USB Creator application.

    Create a guest, say libreelec, mostly with with the default settings. I configured it for 4 vCPUs, 4Gb of RAM and a 32Gb vHDD. Select the cpu type to be host. Do not change the GPU type. BIOS should be (by default) SeaBIOS, which is ok.

    Connect the thumb-drive to the host and from within the hypervisor add it as USB device, using the USB pass-through menu option. Boot from that and just do a LibreELEC install. Let it reboot after install, it will be stuck in the LE logo screen, that's ok. Power the guest down.

    The actual stuff:

    Now comes the hard part, to pass through the graphics adapter from the host to the guest. On the hypervisor from a command line (you can use the "shell" option in the web interface) first add some modules to /etc/modules, so the file looks like this (see [1]):

    Code
    # /etc/modules: kernel modules to load at boot time.
    #
    # This file contains the names of kernel modules that should be loaded
    # at boot time, one per line. Lines beginning with "#" are ignored.
    # Parameters can be specified after the module name.
    intelvfio
    vfio_iommu_type1
    vfio_pci

    Immediately afterwards run:

    Code
    update-initramfs -u -k all

    The kernel should also be started with an iommu=pt option (see also [1], plus how to do it in [2]). Basically, edit /etc/default/grub and set variable GRUB_CMDLINE_LINUX_DEFAULT to be "quiet iommu=pt" instead of "quiet". Save and do a:

    Code
    grub-update

    Reboot.

    Now you'll have to locate which is the PCI id of your graphics card. You do that by running a (sample output included):

    Code
    root@pve:~# lspci -nnv |grep -i vga
    00:02.0 VGA compatible controller [0300]: Intel Corporation Alder Lake-N [Intel Graphics] [8086:46d4] (prog-if 00 [VGA controller])

    So the id is the one ending in 00:02.0. In the hypervisor, go to the guest configuration and add a PCI device. Select Raw device and from the pull down menu select the device ending in the code corresponding to your VGA. Check the Primary GPU box. Do not touch anything else!

    Time to do the audio pass-through. The logic is the same, search for an audio device using lspci:

    Code
    root@pve:~# lspci -nnv |grep -i audio
    00:1f.3 Audio device [0403]: Intel Corporation Alder Lake-N PCH High Definition Audio Controller [8086:54c8]

    So the audio device is the one ending in 00:1f.3. Again, edit the guest configuration to add a PCI device. Select Raw device and from the pull down menu select the device ending in the code corresponding to your audio controller. Do not touch anything else!

    Note that audio passthrough at least on my G3 plus is not perfect. See the caveats section below.

    At this point, being optimists we'll expect that everything will work, so this is the type to connect a USB keyboard to the host (if you have disconnected it before) and pass through the USB device that corresponds to your keyboard (Add USB device -> Use USB Vendor/Device ID).

    Start your guest. If everything went fine, the console display of proxmox will be replaced with the librelec boot screen and, finally, with the LE configuration wizard.

    For the record this is how my vm.conf file looks like under /etc/pve/qemu-server:


    Waking the guest with WOL (wake-on-lan):

    There are two approaches to wake your VM from PVE. The obvious one is to have the LE VM start at boot from the VM settings. In this case you'd have to WOL the host/hypervisor itself. That is, when you would power down the guest you should somehow (via a SSH command for example from guest to hypervisor) shutdown the host itself. The problem is that in this case you would bring down all guests on the system, defeating the purpose of having a hypervisor in the first place.

    The second approach is extremely smart, credits go to the relevant authors at [3]. Note that the mechanism working by sending WOL packets to port 9 (Yatse uses a different port, so make sure you set the port to 9). You'll need also the MAC address of the guest.

    Follow the instruction in the first post in [3], with an important change: instead of creating file /root/scripts/wol_hack.sh, create it with the contents of post https://forum.proxmox.com/threads/wake-o…879/post-756125

    Apart from that, follow the instructions in the first post in [3].

    Now you can send a WOL from Yatse to the mac address of your LE VM and it will start happily, remembering to set port 9 in Yatse config.

    When you have to restart the entire thing:

    You might run into some sort of abnormal behaviour due to virtualization. In that case you would normally restart the VM, but due to the audio issue (see caveats) the system will be mute...

    What I have done (not running other guests atm, so no biggie) is to configure the guest on shutdown to send a shutdown command to the hypervisor, with a one minute countdown (should be enough for the guest to shutdown cleanly).

    LE provides a clean mechanism to do that, using the autostop.sh file (see https://wiki.libreelec.tv/configuration/startup-shutdown).

    Communication is over SSH, so in order for that to work you have to follow these instructions:

    1) You must first create SSH credentials on the guest. Use the command ssh-keygen

    2) Copy the contents of ~/.ssh/.ssh/id_ed25519.pub somewhere.

    3) While on the guest, connect to the hypervisor over SSH. Edit file ~/.ssh/authorized_keys to include the one-liner from step (2) above. Save the file

    4) Test this is ok: Logout from the SSH section and try to login again. This time it should not ask for a password

    5) Time to modify the guest, so that when shutdown starts it should send a shutdown command to the hypervisor. On the guest, edit file (it should not normally exist) /storage/.config/autostop.sh:

    Code
    systemctl stop kodi
    ssh ip.of.hypervisor.system 'shutdown -r +1'

    This instructs LE to ask the hypervisor to reboot after one minute.

    Note: if you want to shut it down instead, replace -r with -h

    The idea is that if the guest starts to act funny, I can select from Kodi power off, which will trigger a host reboot and audio will work fine again. I can then start the guest with Yatse with WOL (assuming you did the hypervisor changes above to enable WOL for VMs).


    Small niceties:

    1) Try to document the hyprevisor installation and modifications you did. If you have to rebuild it from scratch, you'll find that it will take minimal time to re-do your setup. Remember: every minute spending in documenting your setup is equivalent to much more time needed when disaster strikes.

    2) Once you have your guest up and running, do take a snapshot of it. But avoid snapshotting as a means of proper backup. The hypervisor allows to take you a full actual guest backup. Copy the backup elsewhere, or mount an NFS partition from your NAS (if you have one). These instructions are out of scope of this howto, just saying to avoid having to redo everything from scratch.

    3) Finally, for hypervisor installation on SSDs, you might find instructions in [4] useful.


    Caveats:

    • If you shutdown LE and try to start it again, audio does not work. This is due to the fact that after running once, the audio hardware can not be properly initialized. In any case, the HDMI audio hardware is gone on subsequent VM boots. Workaround: if you have to shut down your VM, do a hypervisor (PVE) reboot as well. First LE VM after a reboot will work just fine.


    Final thoughts:

    As this is WIP, I have not tested audio (currently connected to a computer monitor with no audio, but expect that it will work over HDMI). If not, the guide will be modified to reflect any changes.

    Hopefully, someone might provide a solution to the audio issue.

    Power optimization might be also something to look into.

    Additionally, I do want to have some smart hibernation of the VM. If I find anything, I'll update the howto as well.


    Changelog:

    • 2025-07-15: added audio passthrough, some details regarding which HDMI output to use on mini-PCs, wakeup/reboot management, consistent terminology (PVE/hypervisor/host)
    • 2025-07-14: added information for waking the VM after you've powered it down (yatse or other wake-on-lan utility needed).

    References:

    [1]: Proxmox PCI(e) Passthrough

    [2]: Proxmox Editing the Kernel Commandline

    [3]: Proxmox Forum: [TUTORIAL] Wake On LAN (WOL) for VMs and Containers

    [4]: If you boot Proxmox from an SSD, disable these two services to prevent wearing out your drive

    Edited 9 times, last by cosmos: Added compatibility info regarding LE12 nightly and LE13nightly. (July 15, 2025 at 1:09 PM).

  • Been super busy, so I have not proceeded with the project. Today is the big day: I'll put the system into production. In the meantime, I'll be updating the howto to include wake-on-lan of the VM (not the hypervisor).