How I got Wi-fi working in Proxmox

2023/07/31

Pictures may be added later if there is any ambiguity - if you would like me to add pictures for clarity feel free to contact me, and I’ll clarify and add pictures.

tl;dr:

PCI-E passthrough to an OpenWRT virtual machine. Create a second vmbr to act as the output. Connect both vmbrs to the virtual machine in order to install drivers and configure. Alternatively, build an image with the drivers inside of it.

In principle, I am simply combining Proxmox PCI-E passthrough with an OpenWRT WWAN to LAN bridge configuration like this or this (depending on your needs), but there are a number of particularities, so read on for a more detailed tutorial.

Why wifi?

Wireless connections are generally not recommended for servers, and in fact, Proxmox explicitly does not support it, citing problems with bridges. However, I have no control over my home’s router (I live at my parents’ still) and my room is in an awkward spot to run a cable, unless I want to string it up on the ceiling. I also wanted something a little bit more reliable than the poor wifi card that I have in my desktop motherboard, and I had a PCI-E network card, a quad gigabit Intel NIC, and an HP SFF PC running Proxmox, and had a desire to make my life more complicated. I tried to configure the wi-fi card on the Proxmox host, but had many issues at that time, due to my relative lack of knowledge of Linux networking utilities.

This lead me onto the solution of passing through a Wi-Fi card to a virtual machine that could handle it a little bit better - in this case OpenWRT, since it’s small (the HDD image they provide for x86 systems is just 128mb, with most of that space unused), is meant to run on lean hardware, and has a networking webgui built in that I am well used to.

The how-to

You must have Proxmox fully installed with an existing network connection to start here, which would mean having a static IP allocated to Proxmox’s wired NIC. If you’re outright not able to do this, even temporarily, you can probably get around it by entering in the IP address that is allocated by DHCP at install-time; post-install, go into /etc/network/interfaces, find iface vmbr0 inet manual, change manual to dhcp, and comment out the IP and gateway. Reload networking or restart afterward, Proxmox should get an IP address from the device connected to the port bridged to vmbr0. You may also have to edit /etc/hosts to reflect the new IP.

Enable VT-d/IOMMU (if not already)

This needs to be checked in two places, the BIOS and the kernel.

These features should be present on nearly all modern hardware - it began showing up on higher end chipsets in Intel processors on LGA1150 platforms (Q87/Z87 and workstation chipsets) and became a pretty standard chipset feature after the hop to LGA1151. If you don’t directly see VT-d, enable any virtualization extensions that are present, and that should hopefully do it. AMD chips have pretty good support as well - I have the AMD equivalent of VT-d on my HP T730, though it doesn’t really work how I’d like due to IOMMU groups (see next section).

After you enable virtualization in your BIOS, you’ll need to enable some kernel parameters. For Intel processors, you’ll need to explicitly enable IOMMU: intel_iommu=on For AMD this is supposedly detected and enabled on its own when available - if you’re not sure try to run the script in the next section, if it works fine, you’re ready to go. For me, on an HP t730, it was. Most guides I’ve seen also recommend the iommu=pt parameter, though I’ve not seen any ill effects from leaving it out. You can also check by clicking ‘Add’ on a VM and seeing if PCI-E devices shows up as an option.

Check IOMMU groups

Before you start, you need to make sure that the PCI-E IOMMU groups are distributed in a way where passing through the Wi-Fi card will not cause problems. Once VT-d is enabled, you should be able to attempt to add a PCI-E device to a virtual machine in the web interface, which will also show you all of the different IOMMU groups that these devices are in. If not, or you prefer a command-line output, use the following script:

IOMMU groups script - from Arch Linux wiki

#!/bin/sh
shopt -s nullglob
for g in $(find /sys/kernel/iommu_groups/* -maxdepth 0 -type d | sort -V); do
    echo "IOMMU Group ${g##*/}:"
    for d in $g/devices/*; do
        echo -e "\t$(lspci -nns ${d##*/})"
    done;
done;

If this script does not successfully run, it’s likely that you don’t have IOMMU enabled or (less likely, but still possible) your hardware doesn’t support it.

As far as I know, you can basically only pass through full IOMMU groups, and not single devices. If the Wi-fi card is in an IOMMU group on its own, you are good to go. If it’s got other devices in the same group, you’ll need to determine on a case-by-case basis whether it will interfere or not. For example, the HP T730 has the M.2 A+E wifi card slot in the same IOMMU group as the onboard NIC, which means passing the wifi card through also passed through the NIC.

All of the devices in the IOMMU group will become inaccessible to the host (AFAIK).

Create VM output bridge

Create an extra bridge to act as the output - no other configuration is necessary at this point, you can just Create -> Linux Bridge -> Create. Label it if you like.

Create VM

OpenWRT for x86 platforms doesn’t use an installer, it comes as a ready-to-go image that you directly flash onto your target storage device. In this case, though, that’s our Proxmox LVM setup (or whatever you may use).

Get the image on your Proxmox server however you prefer. At time of writing, the most current stable version is 22.03.3, but there is a release candidate for out for the next stable version, which is 23.05.0-rc2. Simplest thing to do: wget https://downloads.openwrt.org/releases/$VERSION/targets/x86/64/openwrt-$VERSION-x86-64-generic-ext4-combined-efi.img.gz (replace $VERSION with your preferred version string). If you’d prefer to copy and paste the link you can start here and navigate to $VERSION/targets/x86. If you’ve found this some years down the line get the appropriate new stable version.

Note that it’s the EFI-bootable image - this is kind of just my preference; we’re going to be using Q35 chipset and OVMF. The Proxmox wiki suggests this mainly for GPU passthrough, but I’m assuming there are at least some other benefits, so I did it. Go ahead and extract the image, and feel free to rename it if you like.

Now, we’ll need to create the VM. For “OS”, choose ‘do not use any media’. For “System”, switch machine chipset to Q35 and BIOS to OVMF. You may uncheck ‘add EFI disk’ - the OpenWRT image comes with a bootloader included, so there is no need - errors will be thrown when the VM starts, but they are harmless here. For ‘disks’, remove all disks that may have been created by default, we will not use them. “CPU” and “Memory” can be what you prefer, you can get away with very little here, 256mb with a single core is plenty. For the network interface, add our new output bridge - by default the first network interface in OpenWRT will be a LAN output. Finish and create the VM.

Now, you’ll need to import the disk image: qm importdisk $VMID openwrt-22.03.3-x86-64-generic-ext4-combined-efi.img local-lvm in the shell, where $VMID is the OpenWRT virtual machine’s numerical ID in the Proxmox web interface. This will add it as ‘Unused disk 0’ in the Proxmox web interface. Navigate to that, click ’edit’ and change bus/device to SCSI if it is not set to that, then confirm. This will attach the disk. While we are here, you should also add the original network bridge that has a connection to the internet (probably your ‘vmbr0’) - this will be temporary.

Now, go into Options for this VM, and change the boot options and order - the new disk is not marked as bootable by default, so check that, and ensure that network boot is disabled or below it in the boot order.

You may also add the Wi-fi card to the VM at this point by clicking Add -> PCI Device. Check ‘All Functions’ (just to be safe) and ‘PCI-E device’.

Now, we are ready to boot the VM. By default, OpenWRT’s x86 image configures the first interface as LAN and the second interface as WAN, so your OpenWRT VM should get an IP address from your DHCP server. If not, you may need to edit /etc/config/network a little bit from the Proxmox web GUI. From here, you can install the drivers for your specific wifi card and the corresponding firmware - in this case, iwlwifi and the 8260c firmware. You also want to install wpa-supplicant, as this is necessary for encrypted neworks.

Note (rant, really) on iwlwifi

I mentioned ‘many reasons’ I switched to using a dedicated router. One of them: iwlwifi is honestly kinda trash. I was never able to get any sort of access point working. This was fine because it wasn’t my intention, and I knew I was unlikely to be able to get AP mode working in the first place. Over time though, the configuration developed many transient stability issues that I was never able to track down. It’s tolerable on desktops or anywhere where stability is not a primary concern, since it usually stabilizes itself somewhat quickly after having one of its fits, but isn’t really great on a networking device. This is an Intel 8260 I am discussing here, YMMV.

From here, you can establish a client/STA connection, remove the second temporary uplink bridge, and configure OpenWRT however suits your fancy for a wifi to ethernet bridge. I did a relay configuration as I wanted it to have a ’transparent’ connection to the upstream router, so I could connect things directly to my overall family home network if I wished to - with this sort of configuration, any VM or container I attach to vmbr1 gets an IP address from the upstream router.

If your goal is to make this your only source of internet for Proxmox, you can reconfigure the VM to make vmbr0 the OpenWRT output bridge. If you configured the OpenWRT VM as a same-subnet ‘relay’ and you don’t have control over the upstream DHCP server to allocate a static IP, you can force Proxmox to use DHCP as described earlier, by manually editing /etc/network/interfaces to change iface vmbr# inet manual to iface vmbr# inet dhcp. You also may need to edit /etc/hosts to reflect the new IP address(es). Proxmox may attempt to set this back to manual if you make changes to the bridge through the web interface in the future, so be aware.

If you set up the VM with a more traditional NAT-based WAN to LAN solution (like is configured in OpenWRT by default), you can have Proxmox get an IP address from the OpenWRT VM by allocating a static IP to the Proxmox vmbr’s MAC in OpenWRT and configuring the Proxmox bridge’s IP address to that.

Incidentally - so far as I can tell, Proxmox works totally fine without a static IP address. In my most recent config I’ve got all of the bridges getting IP addresses via DHCP, and haven’t even set up a static IP on the router end. I know it’s best practice and all, but I don’t know why Proxmox requires it for installation.. I’d rather manage all of my IP assignments from my router’s DHCP anyway - it just feels simpler to me..

>> Home