Skip to main content

Command Palette

Search for a command to run...

Source of Truth with NetBox

Building Your Network Source of Truth — Click by Click

Updated
15 min read
Source of Truth with NetBox

Networks in modern enterprises and service providers are becoming more complex. Network teams handle Cisco IOS, Juniper Junos, Nokia SR OS, firewalls, wireless networks, cloud connectivity, and virtual infrastructure.

Traditional documentation methods, like spreadsheets and static diagrams, are no longer effective at scaling.

This is why modern network automation depends heavily on a Source of Truth.

What is source of truth ?

A Source of Truth is a centralized platform that stores authoritative infrastructure information.

Instead of using:

  • spreadsheets

  • text files

  • Visio diagrams

  • disconnected databases

All infrastructure data is stored centrally. This includes:

  • Devices

  • IP addresses

  • VLANs

  • Interfaces

  • Sites

  • Racks

  • VRFs

The Source of Truth serves as the reliable inventory for monitoring systems, automation tools, CI/CD pipelines, and validation frameworks.

Why is a Source of Truth Required?

  1. Manual Documentation Fails - Spreadsheets and manually maintained inventories quickly become outdated.

  2. Automation Requires Reliable Data - Automation frameworks such as Ansible, Nornir , pyATS and Terraform depend on accurate infrastructure information.

  3. Multivendor Environments Increase Complexity - A Source of Truth normalizes infrastructure information across vendors.

  4. Better Operational Visibility - Network teams can quickly identify Device Locations , Interface usage , IP allocations and VLAN assignments to name a few

What is Netbox ?

NetBox is a purpose-built "source of truth" (SoT) for network and infrastructure inventory, intended to be the definitive system for DCIM (data center infrastructure management) and IPAM (IP address management). It provides a structured data model, a REST + GraphQL API, change logging, webhooks, and a rich UI — all of which make it ideal as the authoritative dataset driving automation and operational workflows.

What Makes NetBox Unique?

  1. API-First Design - NetBox was designed for automation from the beginning. Everything in NetBox can be accessed using APIs.

  2. Excellent IPAM Capabilities - NetBox provides IPv4 management , IPv6 management, VRFs , VLAN tracking and Prefix management. This reduces IP conflicts , Duplicate allocations and poor subnet tracking.

  3. Powerful Infrastructure Modeling - NetBox models real infrastructure relationships.

  4. Dynamic Inventory Generation - NetBox allows dynamic inventory generation automatically. New devices become available immediately to automation frameworks.

Why Should Network Teams Use NetBox?

  1. Better Documentation - NetBox replaces spreadsheets, disconnected inventories and static diagrams with centralized live documentation.

  2. Improved Automation - NetBox enables Dynamic inventories , Configuration generation , Compliance validation and Automated provisioning

  3. Faster Troubleshooting - Engineers can quickly identify Device ownership , Interface mappings , VLAN relationships and Rack locations

  4. Scalable Operations - As networks grow, manual tracking becomes impossible. NetBox enables scalable operational workflows.

Populating Data in NetBox

Method Description
Manual Object Creation The easiest and most straightforward method to populate data in NetBox is by using the object creation forms available in the user interface (UI).
Bulk Import (CSV/YAML) NetBox supports the bulk import and updating of objects using CSV-formatted data. This method is ideal for importing spreadsheet data, which can be easily converted to CSV. You can import CSV data either as raw text in the form field or by uploading a correctly formatted CSV file.
Scripting You will find that data you need to populate in NetBox can be easily reduced to a pattern. A simple custom script to automatically populate this information can be created
REST API The REST API can also be used to populate data in NetBox, providing full programmatic control over object creation while adhering to the same validation rules as the UI forms. Furthermore, it supports the bulk creation of multiple objects with a single request.

Rather than jumping straight into code, we start where every network team should — with the NetBox GUI. Getting your data model right in the UI first means your automation scripts will query clean, consistent, well-structured data.

The principle of "garbage in, garbage out" is especially relevant to network automation.

Lab Topology

Device Vendor Os Site Mgmt IP Loopback
core-rtr-01 Cisco IOS-XR DC-Auckland 192.168.10.1 10.10.10.3/32
core-rtr-02 Juniper Junos DC-Sydney 192.168.20.1 10.10.10.4/32
pe-rtr-01 Nokia SR OS DC-Queenstown 192.168.30.1 10.10.10.2/32
pe-rtr-02 Nokia SR OS DC-Queenstown 192.168.30.2 10.10.10.1/32

Install NetBox and Access the GUI

NetBox operates as a web application supported by PostgreSQL and Redis. The quickest method to obtain a fully functional instance is by using netbox-docker, an officially maintained Docker Compose stack that automatically manages all dependencies.

Installation

Clone netbox-docker and Configure Environment

# Clone the official netbox-docker repo — always use the release branch
git clone -b release https://github.com/netbox-community/netbox-docker.git
cd netbox-docker

Create docker-compose.override.yml to set port and credentials:

cat > docker-compose.override.yml << 'EOF'
services:
  netbox:
    ports:
      - "8080:8080"
    environment:
      - SUPERUSER_NAME=admin
      - SUPERUSER_EMAIL=devplayground.gmail.com
      - SUPERUSER_PASSWORD=CodedNetbox2026!
      - ALLOWED_HOSTS=*
EOF

Pull Images and Start NetBox

# Pull all required images (netbox, postgres, redis, nginx)
docker compose pull

# Start all services in detached mode
docker compose up -d

# Watch startup logs — wait for 'Listening at: http://0.0.0.0:8080'
docker compose logs -f netbox

# Check all containers are healthy
docker compose ps

Expected output of docker compose ps :

NAME                          STATUS          PORTS
netbox-docker-netbox-1        Up (healthy)    0.0.0.0:8080->8080/tcp
netbox-docker-postgres-1      Up (healthy)    5432/tcp
netbox-docker-redis-1         Up (healthy)    6379/tcp
netbox-docker-worker-1        Up (healthy)
netbox-docker-housekeeping-1  Up (healthy)
💡
The initial startup takes 3-5 minutes as Docker pulls images and NetBox performs database migrations. Later startups take less than 30 seconds. If 'netbox' remains in 'starting' status for more than 5 minutes, execute 'docker compose logs netbox' to identify any errors.

Access the NetBox GUI

Open your browser and navigate to:

http://localhost:8080

# If running on a remote server, replace localhost with the server IP:
http://<host-ip>:8080
💡
Note : port 8080 must be opened on the host machine

You will see the NetBox login page

What You See After Logging In

The NetBox dashboard displays a summary of all object counts, including devices, IPs, prefixes, and VLANs. Upon first login, all values will be zero, which is normal. The top navigation bar features six main menus:

Menu What Lives Here
Organization Sites, racks, tenants, contacts, locations
Devices Devices, device types, manufacturers, roles, platforms, cables
IPAM IP addresses, prefixes, VLANs, RIRs, aggregates, services
Circuits Providers, circuits, circuit terminations
Virtualization Clusters, virtual machines, VM interfaces
Operations Webhooks, event rules, scripts, reports, changelog
Customization Custom fields, custom links, export templates, tags
Admin Users, groups, API tokens, object permissions

Generate an API Token (Required for Later Automation)

GUI : Admin → API Tokens → + Add

Although this post emphasizes the GUI, creating a token now will set you up for future automation

Field Value
User admin (your superuser)
Key (leave blank — auto-generated)
Write Enabled ✓ Checked
Expires (leave blank for lab, set expiry for production)
Description Lab automation token

Click Save. The token will be displayed only once, so make sure to copy and store it securely.

# Quick API test

curl -X GET \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "Accept: application/json; indent=4" \
http://<local-host>:8080/api/status/

# Successful response 

{
    "django-version": "6.0.5",
    "hostname": "4ba0dd1e9137",
    "installed_apps": {
        "django_filters": "25.2",
        "django_prometheus": "2.4.0",
        "django_rq": "4.1.0",
        "django_tables2": "2.8.0",
        "drf_spectacular": "0.29.0",
        "drf_spectacular_sidecar": "2026.5.1",
        "mptt": "0.18.0",
        "rest_framework": "3.17.1",
        "social_django": "5.9.0",
        "taggit": "6.1.0",
        "timezone_field": "7.2.1"
    },
    "netbox-version": "4.6.1",
    "netbox-full-version": "4.6.1-Docker-5.0.1",
    "plugins": {},
    "python-version": "3.14.4",
    "rq-workers-running": 1

Useful Docker Management Commands

Task Command
Stop NetBox docker compose down
Start NetBox docker compose up -d
View live logs docker compose logs -f netbox
Check container health docker compose ps
Restart a single service docker compose restart netbox
Access the NetBox shell docker compose exec netbox /bin/bash
Backup the database docker compose exec postgres pg_dump -U netbox netbox > netbox_backup.sql

Organization - Sites , Racks and Location

Create Sites

GUI : Organization → Sites → + Add

Fill in the form for DC-Auckland :

Field Value
Name DC-Auckland
Slug dc-auckland (auto-fills)
Status Active
ASN 65000
Time Zone Pacific/Auckland
Description Primary data centre — Auckland
Physical Address Auckland, New Zealand

Click Save . Repeat the same process for other sites

💡
Tip : The ASN field on the site is useful for BGP automation. Your scripts can retrieve the correct local-AS directly from NetBox, eliminating the need to hard-code it for each device or playbook.

Create Rack Groups and Racks

GUI : Organization → Racks → Rack Groups → + Add

Field Value
Name AKL-ROW-A
Slug akl-row-a
Site DC-Auckland

GUI : Organization → Racks → + Add

Field Value
Name AKL-RACK-01
Site DC-Auckland
Rack Group AKL-ROW-A
Status Active
Type 4-post enclosed
Height (U) 42U
💡
Note: When the rack is populated, space utilization is highlighted.

Device Types & Manufacturers - Hardware Models, Roles, and Platforms

Add Manufacturers

GUI : Device → Device Types → Manufacturers → + Add

Add Device Types — Cisco xrv9k (IOS-XR)

GUI : Device → Device Types → + Add

Field Value
Manufacturer Cisco
Model cisco_xrv9000
Slug cisco_xrv9000
Part Number 8HE03685AARA01
Height (U) 1
Full Depth ✓ Checked
Comments Virtual IOS-XR router

After saving, click the Interfaces tab → Add Interface Template:

Interface Name Type Management Only
GigabitEthernet1 1000BASE-T (1GE) ✓ Yes
GigabitEthernet2 1000BASE-T (1GE) No
GigabitEthernet3 1000BASE-T (1GE) No
Loopback0 Virtual No
💡
Tip : Interface templates automatically populate each device created from this type. Your automation scripts can reliably use device.interfaces.all() to find consistent, vendor-accurate interface names, eliminating the need for guessing or hard-coding.

Add Device Roles

GUI : Device → Device Roles → + Add

Add Platforms

GUI : Device → Platforms → + Add

💡
Note : The platform slug is referenced in your Python PLATFORM_MAP as follows: {'ios-xr': 'cisco_xr, 'junos': 'juniper_junos', 'sros': 'nokia_sros'}. Ensure slugs are lowercase and hyphenated, as they are crucial for automation logic.

Devices

Add core-rtr-01 — Cisco IOS-XR (DC-Auckland)

GUI : Device → Devices → + Add

Field Value
Name core-rtr-01
Device Role Core Router
Device Type cisco_xrv9000
Platform Cisco IOS-XR
Site DC-Auckland
Status Active
Rack AKL-RACK-01

Click Save to navigate to the device detail page. Leave the Primary IP blank for now; it will be assigned after creating the IP address record.

💡
Verify: Devices → Devices should now list all four routers.

IPAM - RIRs, Prefixes, IP Addresses, and Primary IPs

Create RIRs

GUI : IPAM → Aggregates → RIR → + Add

💡
RFC6996 is the correct RIR name for private AS numbers (64512–65534)

Create Prefix Roles and Prefixes

GUI : IPAM → Prefixes → Prefix & VLAN Roles → + Add

GUI : IPAM → Prefixes → + Add

Add IP Addresses and Assign to Interfaces

GUI : IPAM → IP Addresses → + Add

Set Primary IP on Each Device

GUI : Devices → Devices → Edit

Field Value
Primary IPv4 Select the management IP from the dropdown
💡
Tip : The Primary IPv4 field is crucial for automation. The Ansible NetBox inventory plugin relies on primary_ip4 as ansible_host. Without a primary IP, the device is excluded from the inventory and skipped by all playbooks.

Custom Fields - Extending Netbox for Automation

Create Custom Fields

GUI : Customization → Custom Fields → + Add

Populate Custom Fields on Each Device

GUI : Devices → Devices → Edit → (scroll to Custom Fields)

Tags - Flexible Multi-Dimensional Grouping

Create Tags

GUI : Customization → Tags → + Add

💡
Tags used in ansible playbooks nb.dcim.devices.filter(tag="bgp-peer")

Apply Tags to Devices

GUI : Devices → Devices → Edit → Tags Field

💡
Tip : Tags can be queried through the API: nb.dcim.devices.filter(tag='bgp-peer') retrieves only BGP-speaking routers. This allows you to write targeted playbooks, such as 'push new BGP password to all devices tagged as bgp-peer,' without needing separate manual lists.

Cables - Documenting Physical Connectivity

Add a Cable Between core-rtr-01 and pe-rtr-01

GUI : Devices → Devices (choose site) → Interfaces Tab → Connect (cable-icon)

Webhooks & Event Rules - GUI Configured Event-Driven Automation

Create a Webhook

GUI : Integrations → Webhook → + Add

Field Value
Name device-change-to-automation
URL http://your-automation-host:9000/webhook/netbox
HTTP Method POST
HTTP Content Type application/json
Secret
SSL Verification Unchecked for lab ✓ Checked for production

Create Event Rules

GUI : Integrations → Event Rules → + Add

Rule 2 — Device Status Changed to Active (with Condition):

In the Conditions field, the below JSON is used to filter on status change:

{
  "and": [
    {
      "attr": "status.value",
      "value": "active"
    }
  ]
}
💡
Tip : The Conditions filter helps prevent webhook spam with every edit. Without it, any change to a device, even minor ones like adding a comment, would trigger the webhook. Use conditions to focus on the specific state transitions that are relevant to your automation.

Test the Webhook with a Quick Listener

In a terminal, start a one-liner HTTP listener:

python3 -c "
from http.server import HTTPServer, BaseHTTPRequestHandler
import json

class Handler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0))
        raw = self.rfile.read(length)
        data = json.loads(raw)
        print(json.dumps(data, indent=2))
        self.send_response(200)
        self.end_headers()
    def log_message(self, *args):
        pass

print('Listening on port 9000...')
HTTPServer(('', 9000), Handler).serve_forever()
"

In the NetBox GUI, edit pe-rtr-02, change Status from Active → Planned → Active. Expected output:

Listening on port 9000...
{
  "event": "updated",
  "timestamp": "2026-05-27T01:53:21.485685+00:00",
  "object_type": "dcim.device",
  "username": "admin",
  "request_id": "21724c08-cb44-4961-bde1-f76fd4d9fd89",
  "data": {
    "id": 4,
    "url": "/api/dcim/devices/4/",
    "display_url": "/dcim/devices/4/",
    "display": "pe-rtr-02",
    "name": "pe-rtr-02",
    "device_type": {
      "id": 3,
      "url": "/api/dcim/device-types/3/",
      "display": "7750 SR-1",
      "manufacturer": {
        "id": 2,
        "url": "/api/dcim/manufacturers/2/",
        "display": "nokia",
        "name": "nokia",
        "slug": "nokia",
        "description": ""
      },
      "model": "7750 SR-1",
      "slug": "7750-sr-1",
      "description": "",
      "device_count": 2
    },

My personal opinion about NetBox

For a long time, I assumed NetBox was exclusively for production use, primarily employed by enterprise teams to document campus networks and validate their IPAM budgets. I considered it unnecessary for my lab, thinking it was "just a lab."

Then I began using containerlab in a more serious manner.

The Problem Nobody Talks About

Containerlab is truly impressive. You create a YAML topology file, execute containerlab deploy, and in less than a minute, you have a fully connected network of Cisco XRv9000s, Juniper vMX routers, and Nokia SR OS nodes communicating seamlessly. The first experience feels magical.

But here's what happens after the first time.

You create a topology for BGP testing, then another for MPLS, followed by one for SR-MPLS, and a data center fabric. When someone requests you to replicate a production issue, you quickly set up a topology that somewhat resembles it. Soon, you find yourself with six topology files in different stages of completion, a folder full of configurations with names like final_v2_actually_final.cfg, and no clear idea of which IP addresses were used where.

You SSH into something and get a different device than you expected. You run an Ansible playbook and it hits the wrong node. You try to reproduce a test from two weeks ago and spend an hour figuring out what the management IPs were.

This is the source-of-truth problem. And it doesn't only affect production networks.

Why Netbox matters ?

A Source of Truth is now essential in modern networking. NetBox offers the centralized, automation-ready infrastructure platform needed for multi-vendor environments in my case. Modern automation starts with reliable infrastructure data, and NetBox provides that foundation.