UniFi-cation

19 October 2020

I recently moved to a new city for work, and our new home is about the same square footage but it's on fewer floors (only one loft upstairs, no basement, just a crawlspace) so our main level is quite a bit larger than our previous place in Ontario. I happen to have Fibre-to-the-home (FTTH) from Telus here, and the fibre line comes in from the street in the front corner of the house. That means, using the shitty Telus-provided wifi router, we couldn't get signal to the entire house and certainly not on the back patio where I want to be able to work when the weather is nice. This article documents some of the hurdles I had to overcome to take my wifi to the next level. Shout-out to my brother for invaluable assistance!

Backgrounder

In general, fibre networks require an Optical Network Terminal (ONT) to actually interface with the network, which is perhaps analogous to a modem for DSL or cable setups. Then you need a router and a switch. If you want wireless you need wifi access point(s). Most ISPs give you an all-in-one box that does a reasonable job of doing all these things. In my particular case the tech's only solution was to install a "wifi booster" that essentially didn't work at all.

My setup

The UniFi access points require a device to be running their Controller software. I happened to have an old PC Engines APU2 single-board computer lying around with OpenBSD on it. I'm pretty much done with OpenBSD these days so I replaced it with Debian instead, with the intention that this little machine will run the unifi controller and some other misc utilities like a local DNS server, a wireguard gateway, etc. I briefly toyed with buying an Ultimate Dream Machine Pro which can do routing, firewall, and run the controller, until I realized that you need a ubiquiti online account to use the UDM Pro! Fuck that. Since I feel quite strongly about privacy, it seems the UDM Pro is not an option for me.

Fortunately, Telus' all-in-one box isn't an ONT in and of itself—the optical line goes into a small SFP transceiver module and it's that little module that actually acts as the ONT. That means I was able to purchase the (much cheaper) EdgeRouter in lieu of a UDM Pro.

My final hardware list looks like this:

  1. Two UniFi AC Pro Access Points, they come with Power-Over-Ethernet injectors included
  2. Edgerouter X with SFP cage
  3. One metric shitload of ethernet cable, RJ45 connectors and a crimp tool
  4. PCEngines APU2 (to run the controller)

The fibre line coming from the street goes into the SFP+ module, into the EdgeRouter, and from there I ran Ethernet through my crawlspace and up through a hole the previous owner drilled into the floor to put one Access Point on each end of the house, which so far gives good coverage.

Obstacle 1

There's an allegedly-functional UniFi controller package in the OpenBSD ports tree but it appears to be broken, or at least I couldn't get it to install. I opted instead to switch to Debian which is pretty much the de facto standard Linux these days, and there are .deb packages for just about everything. Unfortunately Debian doesn't have a very ergonomic headless install procedure, and their website recommends with a straight face that you create a preseeded installer to automatically install the OS, boot it up with sshd running, and hope you can ssh in. Sheesh.

Thankfully the APU2 has a serial port, so with a handy USB-to-RS232 adapter and minicom running on my ThinkPad T70 I was able to get a serial console running to interact with the APU.

Some notes in case Google sends you here looking for help:

I had the following error come up when I tried to initiate the install procedure:

Undefined video mode number: 314 
Press <ENTER> to see video modes available, <SPACE> to continue, or wait 30 sec
Mode:  Resolution:  Type:
0 F00    80x25      CGA/MDA/HGC

Trying to continue kept resulting in the kernel crashing/freezing. In order to get the install to progress I had to edit the boot command (by pressing TAB). The original command (for Debian 10 Buster) was:

/install.amd/vmlinuz vga=788 initrd=/install.amd/initrd.gz --- quiet

And I changed it to:

/install.amd/vmlinuz vga=off initrd=/install.amd/initrd.gz --- quiet console=ttyS0,115200n8

Where setting vga=off disables the video driver and the console= command sets the output to the ttyS0 device at 115200 baud, no parity, 8 bits.

Obstacle 2

That let me actually get Debian onto the machine. It turns out that the unifi controller depends on Java 8, and MongoDB versions less than 4.0. Debian Stable is packaging mongo 4.4+ and Java 11.

MongoDB is provided by the vendor in their own 3rd-party repositories. I installed MongoDB 3.6 by just adding their "Stretch" (i.e. Debian 9, the previous release) repository and thankfully that Just Worked (tm).

Java was a little more involved. First it was necessary to purge Java from the system:

# apt purge openjdk-11*

Then, I had to find a suitable version of Java 8 to install. Most of the answers on StackOverflow are recommending that you basically just upgrade to sid, the unstable stream of Debian, in order to get Java 8 which is inexplicably packaged there but not in stable. I'm not going to upgrade 1500 packages and then deal with daily churn just to get Java 8. The good news, as it turns out, is that when Oracle started messing with the license in Java 11, a bunch of awesome Java Users' Group folks created AdoptOpenJDK which among other things has old versions available!

So I installed that as per the instructions on their webpage and had to resolve what appears to be a common issue when folks try to install unifi on Debian:

$JAVA_​HOME

netmon unifi.init[5223]: Starting Ubiquiti UniFi Controller: unifiCannot locate Java Home

The unifi init script doesn't know to look for AdoptOpenJDK installs, so it was necessary to patch the set_java_home() function by adding:

#adoptopenjdk
for a in i386 amd64 armhf arm64; do
    java_list=$(echo ${java_list} adoptopenjdk-8-openj9-jre-${a})
done

After that, the controller started and I was able to start provisioning APs!

EdgeRouter throughput

Speedtests were a little disappointing at first. Fast.com only reported some 300-400 Mbps. Troubling! Fortunately, someone on the ui.com forums had already found the solution, which is that hardware offloading is not enabled out of the box for reasons passing understanding.

The fix is to go into the EdgeRouter's control panel, open up the command-line interface, and issue the following:

# configure
# set system offload hwnat enable
# set system offload ipsec enable
# commit
# save

After enabling NAT and IPSec offloading I was getting download speeds in the 950 Mbps range!

February 2021 update: Connection Dropping

The final challenge was debugging a strange issue where the connection would seemingly drop. I'd lose all connectivity, but the Edgerouter would seem to be fine. It just seemed to stop routing outbound packets, inexplicably. There was nothing incriminating in the logs that I could find. It would happen usually when the Edgerouter was under load, but sometimes just randomly in the middle of the night. Some times it would happen twice in a day, other times it would go for a month without problem, but always the issue would return, and the only way to fix it was to power-cycle the edgerouter.

Eventually I gave in and installed a tp-link MC220L media converter to accept the SFP ONT and run ethernet out to the edgerouter's WAN port. At the time of writing it's been chugging along for about 2 months without issue now. Problem solved?