My laptop does not have the best network card: it works only with 2.4GHz networks and it has poor signal. Therefore I decided to buy wifi dongle, and was looking for one that can work with Arch Linux. I found on the net that others got Alfa AWUS036ACH working on Arch so I went with it! Still, it took some effort to set everything up as I wanted, so I will describe the steps here.

Installing driver

Run ip link to see if your dongle is recognized (is there new entry when you connect it to your PC?). If not, we need to install driver. Btw, you can also check first if dongle is shown via lsusb, that should work even without driver, if not then there is some other problem also involved.

Alfa AWUS036ACH uses Realtek 8812au chipset so we need driver for that chipset.

There are multiple drivers out there:

  1. rtl8812au-dkms-git (AUR) as reasonable first choice.
  2. rtl88xxau-aircrack-dkms-git (AUR) as alternative choice since it is more general.
  3. rtl8812au (Github, gordboy) -> this one is just github, no package, has decent number of stars.
  4. rtl8812au (Github, gnab) -> also just github, also has decent number of stars.

There are even more drivers, but these ones seemed most prominent to me at the moment of writing.

Regardless of which driver we choose, installing/setup should go something like this:

  1. Make sure we have dmks installed (dkms ensure that driver is rebuilt when kernel is updated).
  2. Install driver.
  3. Make sure driver module loads on system boot (e.g. create file /etc/modules_load.d/alfa-wifi-dongle.conf with just one line: 8812au, if that is the name of installed driver.).

Finally, if driver is set up correctly, when we plug in the wifi adapter, we should see new entry for it when we run ip link.

The problem is, it takes some time for drivers to catch up with new kernels, and some of them get stale, so you might need to try out a few of them in order to find one that works. While driver #3 eventually worked for me, I would certainly recommend trying the other ones also, it is very likely they might be working for you when you try this.

Driver #1

I liked this one the best, it is specific for 8821au and is packaged on AUR. Installation went fine, however dongle was still not showing up via ip link, I believe that is due to the kernel I was using being relatively new.

Driver #2

In my case, it failed during installation due to Make errors. Maybe I got something wrong, but I moved on before trying more.

Driver #3

This one worked for me! I just followed instructions on the github repo README, which for me ended up going something like this:

  1. I cloned the git repo.
  2. I copied everything to specified location.
  3. I run dkms commands to set module up (add, build, install -> check the details in README).
  4. I also added 8812au to etc/modules_load.d/alfa-wifi-dongle.conf, as mentioned before, to make sure driver loads on boot. After this step I rebooted, to confirm this works + to get module loaded.
  5. I also added
    [device]
    wifi.scan-rand-mac-address=no
    

    to /etc/NetworkManager/NetworkManager.conf as suggested by the README.

This is it! I could see new interface show up via ip link, and I could connect to a wifi network via NetworkManager (I forgot to mention before that I am using NetworkManager, but that was not really important until now).

However, I now had interesting problem: both wifi card and wifi dongle were connected to the wifi networks at the same time (I have one 2.4Ghz network and another 5Ghz network) and my system was preferring using wifi card one instead of the wifi dongle one!

Ensuring that wifi dongle is preferred to wifi card

There are two main methods I figured out, I will explain both.

Method #1: Route metric

Network routes (which we can see via ip route) have property called “metric”. It is a number which says which route should be preferred when sending the internet traffic. Lower the number, more preffered the route.

For example, when I run ip route, one of the lines is default via 192.168.0.1 dev wlo1 proto dhcp metric 600, which means that interface wlo1 has metric 600.

In my case, wifi card was being assigned metric 600 while dongle was assigned metric 601, which was why wifi card was preferred.

The thing is, routes come and go -> if you disconnect the dongle, route will dissapear, and even if you set metric somehow, next time it appears it will have old metric. So it is important to figure out the way how to consistently make wifi dongle have lower metric than wifi card.

I am sure there are more ways to do this that I don’t know about, but I learned that I can set in NetworkManager (NM) which route metric is by default set for a connection when it is established (NM creates routes for a connection when it is established and removes them when it is disconnected). This means we need to set metric for each connection and not just one per interface, but still in practice it should not be a problem, we usually have only a couple of connections defined (work, home, …).

This went somehow like this:

  • nmcli con to list the connections and to remember the name of the connection I want to modify.
  • nmcli con edit <myConnection> which allowed me to interactively edit connection.
    • set ipv4.route-metric 100 (100 seemed like low enough number).
    • set ipv6.route-metric 100
    • save to persist the changes.
    • exit interactive mode

This is it! This set the metric to 100 and I verified that in most cases wifi dongle was preferred to wifi card. However, I also noticed that in some cases, wifi card was still preferred. I am not sure if that was some special, rare case - I should investigate more. Also, I was not completely happy with having to set this for every new connection that I define (although that happens rarely). Therefore, I decided to also try another method, which is simpler conceptually: automatically disconnect wifi card when wifi dongle is connected.

Method #2: Disconnecting the wifi card.

The idea is simple: when wifi dongle connects, disconnect wifi card, and when wifi dongle disconnects, reconnect wifi card. That way my system uses wifi dongle when available, and when not, uses wifi card.

Reasonable way of doing this is to write a script that toggles wifi card and then trigger that script on wifi dongle connection / disconnection events. One way to trigger the script could be via udev rules, but I learned that there is also a mechanism offered by NetworkManager (NM) so I went with that.

NM has “dispatcher” feature, which says that if we put a script in /etc/NetworkManager/dispatcher.d/ and make it executable, NM will run it any time there is a NM event, and will provide script with two arguments: name of the interface for which the event happened and the event type (e.g. “wlo1” as interface name and “up” as event type).

Therefore, I wrote a script /etc/NetworkManager/dispatcher.d/wifi-dongle.sh that disconnects wifi card when wifi dongle connects and connects it when wifi dongle disconnects. This worked fine!

NOTE: I did not cover the case when dongle is already connected to the laptop on boot and additionally it manages to connect before wifi card does, but I think that should be fine anyway since it is probably prioritized then due to the lower route metric by default. I will see how it goes and add handling of this case later if needed (probably smth like: if wifi card wants to come up, but wifi dongle is already connected, disconnect wifi card).

Which method is better?

At the end I feel both methods are good, none of them is perfect, but I somewhat prefer the second one, since with it I am sure there is no way wifi card is used when wifi dongle is connected.