Skip to content

NetBox

NetBox is your own source of truth for what an address is. The NetBox connector is a read-only source against its REST API: the device or virtual-machine name becomes the device name — directly after a manual one — and role, site, tenant, description and status appear in the inventory and in the device detail.

It is a Pro connector (connector.netbox), granted by the same connectors feature as UniFi. See Free vs Pro.

The older on-demand link lookup — the NetBox link in the head of a device detail, driven by NDR_NETBOX_URL and NDR_NETBOX_TOKEN — keeps working alongside it, and keeps its own netbox health line.

List Purpose
/api/dcim/devices/ Device names, roles, sites, tenants, primary addresses
/api/virtualization/virtual-machines/ The same for virtual machines
/api/ipam/ip-addresses/ Every address with its assigned object, dns_name, status, tenant, description
/api/status/ The NetBox version, for the test connection only

Devices and virtual machines are read first so that an address can be described by the object it is assigned to. Paging is limit/offset, 200 rows a page and at most 50 pages before the batch is marked truncated; one request is bounded at 5 s and one answer at 4 MiB; redirects are followed only to the same origin, at most three. The connector was shaped after NetBox 4.x (role, display_url); the 3.x spelling device_role is read as well.

The name precedence inside NetBox is the assigned object’s name over the address’s dns_name. A dns_name is a host name rather than a typed name, so it becomes a DNS label first (lower case, trailing dot and domain removed): Kamera-01.home.example. in NetBox and a DHCP host name kamera-01 are one name. A device or VM name is kept as typed. The link into NetBox is the object’s display_url when it points back at the configured origin, else its API URL — a foreign display_url is dropped, never handed on.

NetBox is a snapshot, not an event stream. An unchanged inventory produces an empty poll, which is still a successful sync: the last-success time moves and the counters update. Once a day the inventory is re-emitted in full so the identity anchors stay inside the identity job’s window.

In NetBox: Admin → API tokens → Add, for a dedicated user whose permissions are exactly three view rights:

  • ipam | ip address
  • dcim | device
  • virtualization | virtual machine

Leave Write enabled off. The connector proves those three rights at every test connection and refuses to poll with less; it never needs, and must never be given, anything more. /api/status/ is readable by any authenticated token.

An appliance that already has

Terminal window
NDR_NETBOX_URL=https://netbox.example.invalid
NDR_NETBOX_TOKEN=<token>

in /etc/ndr/ndr.env (root-only, mode 0600) needs nothing else. The service declares the connector from those two variables — one instance per tenant, named netbox on a single-tenant appliance and netbox-<tenant> for further tenants, with the secret env:NDR_NETBOX_TOKEN — and runs it without NDR_CONNECTORS_ENABLED and without connectors.yaml. The flag gates the file, not a connector the environment configured explicitly. Restart ndr-api after deploying; the first poll runs right after the start and every 15 minutes from then on.

The two variables must be set together; one without the other is a start error.

Declare it in the file when the connector should have its own interval, its own page size or a token file, or when the file already exists. A declared netbox instance takes precedence over the environment for every tenant:

connectors:
- id: netbox
instance: netbox
tenant: example
enabled: true
config:
url: https://netbox.example.invalid
poll_interval: 15m # floor 1m, default 15m
page_size: 200 # 10..1000; lower it only on a `too_large` failure
secrets:
token: file:/etc/ndr/secrets/netbox-token # or env:NDR_NETBOX_TOKEN

A token file follows the credential rules of UniFi, step 3 (0640 root:nyxtrace or 0600 nyxtrace). With the file path, NDR_CONNECTORS_ENABLED=true is required as for every other connector — see connectors.yaml.

Only for a file-declared instance; the CLI reads connectors.yaml and does not see an environment-declared one.

Terminal window
sudo -u nyxtrace env NDR_CONNECTORS_ENABLED=true ndr connectors validate
sudo -u nyxtrace env NDR_CONNECTORS_ENABLED=true ndr connectors test netbox --live
sudo -u nyxtrace env NDR_CONNECTORS_ENABLED=true ndr connectors collect netbox --once --live

test --live reports the NetBox version and one line per list with its row count, and proves the three view rights. collect --once --live prints how many addresses became items and how many anchors arrived, and stores nothing.

A failure names its class: auth (token rejected), forbidden (a missing view right, with the list named), unreachable, timeout, unexpected_shape (NetBox redirected the API elsewhere or answers no list envelope), too_large. A 429 honours Retry-After. The token never appears in an error or a health line.

The system view shows connector:netbox with its state, the time of the last sync and NetBox’s own counters — devices, virtual_machines, ips — which move even when a poll found nothing changed. The instance turns stale after three missed polls (45 minutes at the default interval). Without the interface:

Terminal window
journalctl -u ndr-api -g 'instance=netbox'

The hourly naming job logs netbox=N on its next run.

Every address inside the tenant’s own configured VLANs gets an inventory record in the state store and an authoritative_map identity anchor with source = connector:netbox. Addresses outside the configured networks are dropped and counted in the dropped= field of the poll’s log line. A device whose primary address the address list did not carry is emitted from the device. An address without any name is still a record — its description may be the only thing anybody wrote down — but proves no identity.

Nothing is deleted when an object disappears from NetBox: its last record stays until the operator removes it. It does expire: a record the connector has not re-emitted for three full snapshots (72 h) stops being shown and stops naming the device, and the name stays listed as a former name. The next emission that carries the address makes it live again with no other change.

Device name. The naming job ranks NetBox second, directly after a manual rename and above the UniFi controller map, DHCP, mDNS, reverse DNS and the address. A CMDB entry is a decision somebody made, not an observation; it still loses to a manual name, because the operator at the console knows things the CMDB may not yet. The interface labels such a name via NetBox (name_source: netbox). The full order is on device identity and naming.

Device list. A muted role line under the name. The list’s free-text search matches the NetBox device name and the dns_name of any of the device’s addresses, so a name maintained in NetBox finds the device even while a higher naming source shows a different one.

Device detail. A NetBox block in the identity panel with role, site, tenant, status and description, and the link into NetBox.

API. GET /api/v1/devices and GET /api/v1/devices/{id} return a netbox object — name, role, site, tenant, description, status, url, each nullable — or null when NetBox knows none of the device’s addresses. A device holding several addresses is described by the first one NetBox knows. The detail’s older netbox_url field falls back to that record’s link when the on-demand lookup found nothing.

On a free installation, or while the licence is not yet active, the instance is visible as unlicensed with the feature named; the link lookup keeps working and the naming job simply has no NetBox candidates. Nothing is deleted and no other source is affected. When the licence becomes active the instance starts without a restart — see licensing.

  • An environment-declared instance is not visible to ndr connectors list|test|collect; declare it in the file to try it from the CLI.
  • A record of an object removed from NetBox is kept in the store, but it stops being used after three full snapshots (72 h) without re-emission: the netbox object becomes null, the name stops matching the search and is shown as a former name.