It's been two and a half years since I "built" my own router with NixOS. I haven't made a particularly good effort in keeping the original blog post up-to-date, so this is a low-effort attempt at a retrospect.

Send an email to contact@skogsbrus.xyz or a DM on Matrix if you have any specific questions you'd like to have answered.

In Brief

  • It's been a great project to get more hands-on experience with Nix and NixOS, and to learn more about home networking
  • I no longer reboot my router in anger and I have a consistently stable connection 🎉
  • I do not recommend configuring a NixOS router with WiFi unless you have an inherent interest in that technology - use an external access point instead.
  • Most issues are fixable and moderately easy to understand; some issues require lots of time to debug. While this blog post may make it seem like I've had a lot of issues, I think I've had very few considering the time I've been running this setup. Consider also that practically all that I have had have been fixable.

There's still a couple of things I would like to improve:

  • Isolate networks with VLANs (I currently rely on host isolation through hostapd)
  • Automated network health alerts
  • Continuous network speed monitoring
  • Better commit messages - I've been pretty bad at this and it's been particularly noticable when writing this blog post. It was difficult to understand the context of some changes.

Time sinks

This section describes a couple of things that I've had to spend a significant amount of time on, without much enjoyment. "Significant" can vary a lot here, but it's generally more than a weekend's worth of hacking.

Breaking changes in NixOS services

In order to keep my router up-to-date, benefiting from kernel upgrades, security patches, new application features, and keeping all of my Nix(OS) devices in sync, I generally try to use the latest release of nixpkgs.

In making that choice, keeping up-to-date, you sign up for some amount of maintenance work as applications or their NixOS services will change at some point or another. In general, I think that choice is worth it. But when you face regressions during OS upgrades, it can sometimes be hard to convince yourself that rolling your own custom router is worth it.

hostapd

After upgrading my router to 23.11, WiFi stopped working for three separate devices, but continued to work fine for everything else. While unexpected, it was not entirely out of the blue since hostapd had been heavily refactored in this released and required a breaking change.

Unlike some breaking changes, like dnsmasq in 24.11, this refactoring wasn't just a simple mapping between settings and extraConfig, but more complex due to an attempt to abstract some of the complexities exposed by hostapd.

Hostapd logs were not helpful in diagnosing the issue, so after some feeble guesswork I decided to dig into the refactoring and the hostapd configuration files from before and after the upgrade.

I was ultimately able to confirm that the issue was due to how the authentication mode was being set. In my original config I had the following lines:

wpa=2
wpa_pairwise=CCMP
wpa_key_mgmt=WPA-PSK

But in the new config, there was no option to set WPA2 and WPA-PSK in the new "authentication mode". The only authentication mode exposed for WPA2 was wpa2-sha256, which set wpa_key_mgmt to WPA-PSK-SHA256. And this is what broke WiFi for those devices - presumably they all had pretty old WiFi drivers that didn't support this setting.

I was able to work around this by disabling authentication and then overriding the options I needed:

              authentication = {
                wpaPasswordFile = config.age.secrets.wifi_pw.path;
                # tmp hack to allow setting WPA-PSK auth
                # TODO: contribute to nixpkgs (allow WPA-PSK)
                mode = "none";
              };
              settings = {
                wpa = 2;
                wpa_key_mgmt = "WPA-PSK";
                wpa_pairwise = "CCMP";
              };

This was later found and addressed independently by @tomfitzhenry who introduced an authentication mode for WPA-PSK in 24.11, reviewed by @oddlama. Thank you both for upstreaming this fix!

For the curious reader, the merge request for this change features a very good discussion on the change and helped me understand more than what I knew at the time when I made my patch.

The discussion also surfaced a much cleaner hack than what I came up with, using mkForce:

settings = {
  wpa_key_mgmt = mkForce "WPA-PSK";
}

To be clear, I have no issue with this refactoring being made nor with it being imperfect from the start. In fact, I could have reported this issue immediately once I hit it, but I did not and that's my fault. With this section I'm mainly trying to give a sense of what a real regression can be like when maintaining your own network stack with NixOS.

WiFi issues

2.4GHz vs 5GHz

When I first set up the router, I lived in a small house with five neighbors. So there was very little interference. In late 2023, I moved to large apartment building with many neighbors. WiFi speeds were abysmal due to the interference on 2.4GHz. Due to its longer range (passes walls more easily), 2.4GHz is much more prone to see interference from neighbors.

After some reading I was able to conclude that you could only configure one frequency band per NIC. So at first I tried to switch to use 5GHz only, but then our robot vacuum cleaner would not work (it only supports 2.4GHz). Luckily, the APU2 supports two network cards!

So in the end I was able to use both 2.4 and 5GHz on separate networks after having ordered an additional network card from TekLager.

Network Range

Even though my network speed is stable, I feel like the network range is slightly worse than on other consumer routers. At some point I'll try to draw a curve of the network range vs speed at different distances.

Why I don't recommend configuring WiFi on a NixOS router

It's really not an issue with NixOS, but rather hostapd. As a layman in wireless networking it is really hard to assemble a good hostapd configuration and being confident that it's appropriate for your setup.

If I were to do this all again, I would either solve WiFi with an external access point running OpenWRT or first flash my router with OpenWRT and copy its hostapd config, trying to recreate it in NixOS.

DFS issues

DFS is short for Dynamic Frequency Selection. It's a WiFi feature used by hostapd, to improve WiFi quality by switching to a less congested channel (I think).

Hard to debug and definitely a timesink. I haven't seen any issues with this in a long time now, so I think I managed to fix it? But I don't think I ended up understanding why this happened, what the issue was, or why it was fixed.

DHCP issues

This happened very seldomly and was therefore pretty hard to debug. I'm still not sure of the root cause, but I think I managed to fix the issue by setting an infinite DHCP lease time.

Recommendations

  • The router I use is no longer manufactured. TekLager recommends TLSense J6412 as a possible alternative.
  • In my experience, maintaining WiFi has been the most time consuming part of the maintenance I have done and also the most unrewarding. Even if it does work, determining whether you have an appropriate setup is also really difficult.
  • If you're willing to spend the initial time of configuring your initial network setup and then reserving two weekends a year (note: it takes less time than this; but you should at least anticipate this amount of downtime in case you face a difficult regression and don't want to reboot to a prior generation) for maintaining NixOS upgrades, then I definitely recommend rolling with your own router. There's something special about having complete control of a common household appliance like that.