Monitoring UniFi Devices with Prometheus and Grafana
I already run Prometheus and Grafana for the homelab. The missing piece was UniFi: I wanted controller-side metrics in the same place so I could troubleshoot Wi‑Fi and switching without bouncing between the controller UI and guesswork. I also wanted the community UniFi Poller Grafana dashboards to actually light up, which only happens if the exporter exposes the metric families those dashboards query.
Problem
Until I validated the full path (exporter configuration, Prometheus scrape, label shape), the imported dashboards were empty or half-broken. I needed to know what UniFi Poller expects for controller access, which port it listens on for Prometheus, and which unpoller_* series the dashboards filter on so labels like site_name and device names match what the panels expect.
What the docs and dashboards expect
UniFi Poller’s Docker and Compose docs spell out the usual environment variables: controller URL, credentials, UP_PROMETHEUS_HTTP_LISTEN, and the option to turn Influx off when Prometheus is the only sink. There is also a fuller up.conf path if you prefer a file over env vars.
On the Prometheus side, the pattern is a dedicated job (often called unifipoller) scraping the exporter on port 9130 on a 30s interval, or the /scrape path with relabeling if you run multiple controllers. Defaults line up with that, so the work is mostly a new job block and sane scrape interval.
I pulled three Grafana dashboards referenced in the upstream project to see what they actually query:
- UAP Insights (11314): radio utilization (
unpoller_device_radio_channel_utilization_{receive,transmit}_ratio), VAP stats (unpoller_device_vap_*), station counts (unpoller_device_stations). Panels use$Siteand$AP; those labels have to exist in Prometheus. - Client Insights (11315):
unpoller_client_*for bytes, rates, CCQ, satisfaction, roam counts; wired clients can cross-reference switch ports, so the exporter needs permission to read that inventory from the controller. - Network Sites (11311):
unpoller_site_*for latency, remote users, DPI categories, subsystem counts. Everything keys off per-site series, sosite_name(and friends) must be present.
Operational notes I kept in mind: on UniFi OS gateways and Cloud Keys Gen2+, you generally do not put :8443 on the controller URL for API access the way you might with older controller-only installs. If you only care about Prometheus, disable Influx output so you are not maintaining a second database for no reason.
Implementation
I added a unpoller service to the monitoring stack’s Compose file with Prometheus output enabled and Influx disabled. Credentials and controller URL come from environment variables so nothing sensitive sits in git; the runtime .env on the monitoring host supplies them when I run docker compose up.
The container exposes 9130 on the internal Docker network, with a health check hitting /metrics so a dead exporter fails fast.
Prometheus got a job_name: "unpoller" entry pointing at the service (e.g. unpoller:9130) with a 30s scrape interval. I added an alert group for things I actually care about: exporter up, device uptime that stops increasing (stale device), radios stuck above a high channel utilization threshold, switch ports reporting errors, and large swings in client counts versus a short baseline. After deploy, service metadata documents the three dashboards and the alert bundle so I do not have to rediscover the URLs later.
What went wrong first
Grafana stayed blank and the container logs showed authentication failures. Two fixes:
- Controller URL: I had the wrong base URL. For my setup the correct one was the controller’s HTTPS URL without appending
:8443. UniFi OS is picky here; getting it wrong looks like an auth failure even when the password is right. - Environment on the host: Variables were set locally but not in the
.envon the machine running Compose, so the container never saw them. After syncing URL, username, and password into the.envbeside the Compose file on the monitoring host,docker compose up -d unpollercame up clean.
After that, Prometheus showed series like unpoller_device_uptime_seconds and the Grafana dashboards populated with AP and client data.
Results
The dashboards immediately showed radio utilization, client roam behavior, and site-level DPI-style aggregates from the controller. Alert rules show up in Alertmanager with the expected labels, so exporter outages or an AP that stops incrementing uptime surface as real incidents instead of silent drift.
The practical win is troubleshooting UniFi from the same metrics stack I use for everything else, instead of treating the controller UI as a separate island.
Hardware
The access layer here is UniFi. The APs I run are the Ubiquiti UniFi U6 Pro and the Ubiquiti UniFi AC Pro.
Lessons learned
Match the controller URL to how UniFi OS expects to be reached; “auth failed” is often “wrong URL shape,” not a bad password.
Keep Compose secrets on the host that actually runs the stack; debugging locally while production never got the .env is a waste of an afternoon.
Before importing dashboards, skim what metrics and template variables they use so you know labels like site_name and device identifiers are coming from the exporter, not from Prometheus alone.
If you only want Prometheus, turn Influx off. One sink means one place to scrape, one retention story, and fewer moving parts.
Disclosure: This article contains affiliate links. If you purchase through these links, I may earn a commission at no extra cost to you.
Related reading
Prometheus and Grafana: Why Your Homelab Needs Monitoring
What Prometheus and Grafana are, why they're essential for homelab monitoring, and how they help you understand what's actually happening in your infrastructure.
Researching Node Exporter on macOS workstations for homelab monitoring
Why I looked at Prometheus Node Exporter on laptops, how macOS alternatives compare, and why I cancelled the project after the math stopped working.
Debugging 'No data' panels on a NUT UPS Grafana dashboard
When Grafana shows 'No data' on a NUT monitoring dashboard, the problem is not always your exporter or Prometheus. Sometimes the UPS hardware just does not report those metrics.
Ready to Transform Your Career?
Let's work together to unlock your potential and achieve your professional goals.