Compare what NetBox says your network looks like against what your Cisco devices are actually running.
DRIFT REPORT: lab-sw1
--------------------------------------------------------------------
INTERFACE FIELD NETBOX DEVICE
--------------------------------------------------------------------
GigabitEthernet1/0/1 trunk vlans absent +[60, 70, 80, 90, 100]
GigabitEthernet1/0/2 access vlan 10 20
GigabitEthernet1/0/2 voice vlan None 200
GigabitEthernet1/0/3 admin state enabled shutdown
GigabitEthernet1/0/9 undocumented - on device only
5 difference(s) found.
Somebody SSH'd in at 3am, fixed something, and never updated NetBox. That
port is now carrying VLANs nobody documented. netdrift finds it.
pip install netdriftAgainst a live NetBox and a live device:
netdrift --netbox-url https://netbox.example.com \
--netbox-token $NETBOX_TOKEN \
--device sw1 --host 10.0.0.1 \
--username admin --password secretAgainst a saved config file (no SSH):
netdrift --netbox-url https://netbox.example.com \
--netbox-token $NETBOX_TOKEN \
--device sw1 --config-file sw1-running-config.txtMany devices in one run:
netdrift --netbox-url https://netbox.example.com \
--netbox-token $NETBOX_TOKEN \
--devices devices.txt \
--username admin --password secretdevices.txt is one device per line — name, then either an IP to SSH to
or a saved config file:
core-sw1 10.0.0.1
core-sw2 10.0.0.2
edge-sw1 saved/edge-sw1.txt
JSON works too. Each device gets its own report, followed by a summary. A device that's unreachable is reported and skipped, not fatal.
Trying it out with no NetBox at all:
netdrift --mock-netbox mock_netbox.json --device lab-sw1 \
--config-file messy_config.txtExit codes: 0 clean, 1 drift found, 2 one or more devices
couldn't be checked. Drops straight into CI or a cron job.
| Field | Compared |
|---|---|
| Interface mode | access vs trunk (NetBox tagged normalized to trunk) |
| Access VLAN | untagged VLAN assignment |
| Trunk VLANs | allowed lists, including add continuation lines and ranges |
| Voice VLAN | switchport voice vlan |
| Admin state | shutdown / no shutdown |
| Missing ports | in NetBox, absent on device |
| Undocumented ports | on device, absent from NetBox |
SVIs, port-channels, sub-interfaces and loopbacks are hidden by default
since NetBox often doesn't model them. Pass --show-logical to see them.
Pasted terminal sessions (with switch(config-if)# prompts) are detected
and stripped automatically, so a copied CLI transcript works as input too.
- IOS / IOS-XE and basic NX-OS. IOS-XR is not implemented.
- Read-only. It reports drift; it will never push config.
- No scheduling, history, or alerting.
--netbox-url URL NetBox base URL
--netbox-token TOKEN NetBox API token
--mock-netbox FILE JSON file instead of a live NetBox
--device NAME single device name as it appears in NetBox
--devices FILE inventory file: check many devices in one run
--host IP device address for SSH
--username / --password SSH credentials
--config-file FILE parse a saved running-config instead of SSH
--show-logical include SVIs/port-channels in undocumented list
--dry-run show NetBox intended state only
pip install -r requirements.txt
python -m pytest test_netdrift.py -v29 tests cover the parser and the diff engine. Please add one with any bug report — a config snippet that parses wrong is the most useful issue you can file.
Bug reports with a sanitized config snippet are very welcome. Please scrub hostnames, IPs, keys and passwords before pasting anything.
MIT