homelabnetworking

An SNMP shim for UniFi switches

The gateway already has the port counters. A shim asks it, then answers SNMP so LibreNMS can graph the switches that do not speak it.

27 September 20264 min read

LibreNMS graphs a switch by asking it SNMP questions. The Flex Mini and the Ultra have nothing listening. They show ports, traffic, and health in the UniFi controller, and that is the end of it. The Lite 8 PoE does answer, but the firmware introduces itself as a generic Linux box and leaves out CPU, memory, and PoE. The numbers are on the gateway. They are just not on the path LibreNMS already walks.

The shim stands in for each of those switches. It polls the gateway, turns one switch into an SNMP snapshot, and answers SNMPv2c. LibreNMS already has a stock profile for Ubiquiti EdgeSwitch gear, so the snapshot is shaped to match that. Nothing custom has to be copied into the LibreNMS image. Those files would vanish on the next image update.

Asking the gateway

Each poll talks to the UniFi Network API on the gateway. There are two surfaces, because one of them is missing the counters.

The Integration API is the supported one. A poll lists the devices, then fetches that switch and its latest statistics:

  • GET /proxy/network/integration/v1/sites/{id}/devices
  • GET /proxy/network/integration/v1/sites/{id}/devices/{id}
  • GET /proxy/network/integration/v1/sites/{id}/devices/{id}/statistics/latest

That covers inventory, firmware, online state, CPU, memory, uptime, and per-port link state and speed. It does not include per-port byte counters. They are not in the OpenAPI spec for this controller.

Traffic graphs need those counters. They still live on the older device statistics call, GET /proxy/network/api/s/default/stat/device. That one is undocumented and can change. It is an extra. If it fails, everything else keeps working and the counters are left out of the snapshot. A zero would look like a quiet port and draw a misleading graph.

The same legacy payload carries the gateway’s WAN row. The official WAN call only returns names, so latency and whether the WAN is up come from that older row.

The API key can hit the gateway on the LAN, or go through the cloud Site Manager and back to the same console. The calls in the picture are the cloud path. A poll builds a snapshot, and the agent answers SNMP from the last good one. A slow gateway stays off that path, so LibreNMS does not time the switch out while it waits. After several failed polls in a row the snapshot is withdrawn, and then LibreNMS does see the device as down.

UniFi API call log showing the legacy stat/device request and the three Integration API device calls, all returning 200 over the cloud transport
One poll, four calls. The legacy statistics request is the one with the byte counters.

What comes back as OIDs

The snapshot is walked out as the OIDs LibreNMS already reads for an EdgeSwitch. sysObjectID sits under Ubiquiti’s enterprise number, and sysDescr starts with the USW model and the firmware, which is what the stock detection rule matches. Port names, link state, speed, and the byte counters land on the usual IF-MIB objects. CPU and memory use the EdgeSwitch scalars that profile graphs. The host-resources processor object is served as well, and that profile ignores it.

Memory is the awkward field. The controller reports a percentage, not a total. The shim assumes a total for the model so the graph can show a size, and derives free memory from that percentage. The utilisation LibreNMS plots is the percentage UniFi reported.

A few values have no standard home: PoE draw, whether a firmware update is waiting, a simple online flag, and the WAN figures. Those go on the experimental OID arc, .1.3.6.1.3, rather than inside Ubiquiti’s tree. LibreNMS reads them as custom sensors. A MIB browser does not then mistake them for official objects.

Live OID table for the Flex Mini, starting with sysDescr, sysObjectID, and the first interface names
The top of the live table. LibreNMS walks this the same way it would walk a real switch.

One container per switch

Each switch is its own container, with its own address on the LAN, answering SNMP on UDP 161. LibreNMS polls them as separate devices. One shared process would make every reply come from the same place, and they would collapse into a single device.

A console sits in front of the three. It does not speak SNMP. It scrapes each shim’s HTTP API on an internal network and shows whether that instance is answering, how many SNMP requests and controller calls it has handled, and the live OID table. The displayed name, location, and contact can be edited there. The listen address and the API key stay in the stack configuration.

Dashboard with three shim instances, Flex Mini, Ultra, and Lite 8 PoE, each serving SNMP from its own address
Three switches, three listeners. LibreNMS polls each one on its own.

The Flex Mini, the Ultra, and the Lite 8 PoE show up in LibreNMS with port traffic and the usual health graphs. The gateway was already collecting the numbers. The shim is the SNMP front they were missing.