> ## Documentation Index
> Fetch the complete documentation index at: https://docs.internal.nscale.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Relationship: NetBox

> NetBox as the inventory source Fleet Manager observes: agents, cadence, contract and failure modes.

* **Kind:** Observation
* **Version:** 2
* **Fleet Manager owner:** Fleet Manager squad, #fleet-manager-chat (individual claimant pending)
* **Counterpart owner:** unassigned, SRE [NetBox](../start-here/glossary#netbox) operations under John Weber (Cody Kronaizl suggested as lead, to
  confirm), #netbox-ops
* **Last reviewed:** 2026-10-08

## What flows

NetBox is the inventory source of truth Fleet Manager materialises into its own store (ADR-0017). Two hub agents
read it:

* `netbox-agent` (`src/fleet_manager/agents/netbox/`) reads sites, locations, racks, [device](../start-here/glossary#node) types, device roles
  and devices. Devices are polled every 60 s on a `last_updated` delta, static objects every 30 min, a full
  resync every 15 min and a full refresh every 24 h; a PostgreSQL notify mode can replace that polling.
  Interfaces, IP addresses and MAC addresses are polled every 60 s on their own `last_updated` delta, which
  requeues the device each change belongs to; the device a moved or deleted interface, IP or MAC leaves
  waits for the resync. It writes
  Fleet Manager organisations, sites, locations, racks, device types, roles and devices, and caches firmware
  policy from config context.
* `netbox-inventory-agent` (`src/fleet_manager/agents/netbox_inventory/`) reads devices, interfaces, IP
  addresses and cables into `DeviceInventoryProjection` and `CableInventoryProjection`, polling every 15 s on a
  `last_updated` cursor with a 5 min resync and hourly full refresh; cable links poll every 120 s to hold the
  under-five-minute freshness the Matrix feed depends on. Device `updated` and `deleted` notifications on the
  6-segment subject grammar in `src/fleet_manager/core/events/subjects.py` are published only when the chart
  flag `netboxInventoryAgent.natsPublishEnabled` is true, and cable notifications only when `linkSiteFilter` is
  populated and `linkNatsPublishEnabled` is true; all three default off, so a deployment on defaults feeds the
  connectors through their polling backstops.

The field-level requirements for enrolment (site `syslog_server` and `ntp_server_1`, `oob_ip` assigned to a
management interface, `config_context.ironic_settings`, `expected_hw_description`, the [Ironic](../start-here/glossary#ironic) tag) are in
`docs/netbox-data-contract-full.md`. Fleet Manager writes back the NetBox device status, set to `active` when
enrolment completes and to `staged` on unenrolment. Once the site's
`platform_class_activity_ready` gate is on, enrollment also records the derived
`custom_fields.platform_class` when it is empty; a populated divergent value is retained and
warned about rather than overwritten by `EnrollmentActivities.record_platform_class_activity` in
`src/fleet_manager/temporal/activities/enrollment.py`. `fleetctl netbox
backfill-platform-class --apply` writes the same field for backfill and correction. Unenrolment
remains in `src/fleet_manager/temporal/activities/unenrollment.py`.

## What breaks if this changes

A missing or wrong record blocks enrolment for that device, and the node-swap workflow, which reads and updates
NetBox for the replaced tray, fails the same way: no `oob_ip` fails [DHCP](../start-here/glossary#dhcp), [BMC](../start-here/glossary#bmc) configuration and
Ironic enrolment; a missing site custom field fails BMC configuration for every device on the site. A NetBox
outage stops both agents; Fleet Manager keeps serving its last materialised view, and the Matrix and Borneo
feeds go stale with it. A schema or hostname change on the NetBox side surfaces as agent errors, not as a Fleet
Manager alert, until the agents are reconfigured. Renaming a device is safe: `netbox-agent` matches a device by
name, then by NetBox ID within its site, and renames the Fleet Manager device. A swap that exchanges two devices'
names keeps each Fleet Manager device with its name.

## Enforcement

* **Principal:** `netbox-agent` and `netbox-inventory-agent`.
* **Mechanism:** towards Fleet Manager, FM OAuth clients (private-key JWT) in the hub chart roster; towards NetBox,
  the NetBox API token read from [1Password](../start-here/glossary#1password) (`auth-token` field of the deployment's NetBox item,
  `src/fleet_manager/settings/clients/netbox.py`).
* Hub roster clients `netbox-agent` and `netbox-inventory-agent` in `deployment/charts/hub/values.yaml`.
* Contract: `docs/netbox-data-contract-full.md`; published summary in
  [NetBox Data Requirements](../operator-guide/netbox-data-requirements).
* Token permissions: [Create the NetBox API Token](../deployment-guide/new-site-deployment/deploy-fleet-manager-at-a-new-site#create-the-netbox-api-token)
  is the authoritative Object Permissions matrix for the shared runtime token.
* Settings: `src/fleet_manager/settings/agents/netbox.py`, `src/fleet_manager/settings/agents/netbox_inventory.py`.

## Gaps

* No agreed change-notice for NetBox migrations or version upgrades; the July 2026 Kubernetes migration was
  rolled back after a P2 and the two teams disagreed on the cause.
* Eleven components read or write NetBox; this file covers only Fleet Manager's two agents.

## Change log

* 2026-10-08 v2: a NetBox device rename renames the Fleet Manager device instead of failing its sync.
* 2026-09-09 v1: created; describes present behaviour.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.