← Interview Prep
Source of Truth & NetBox
What a Source of Truth is and why the device isn't it: modeling with NetBox (site→device→interface→IP), data validation (pydantic/JSON Schema), config drift & the device-vs-SoT conflict, and the SoT→intended→diff→deploy closed loop.
Automation is only as good as the data it renders from. A Source of Truth (SoT) is the
authoritative, machine-readable definition of the network's intended state — devices, interfaces, IPs,
VLANs, cabling, circuits. Config is generated from the SoT; the device is not the truth.
Getting this right is what separates "we have scripts" from "we have automation."
The mental flip: stop treating the running-config as reality. The SoT is the intent;
the device's config is a rendering of it. Anything on the box that the SoT didn't put there is
drift — to be reverted or reconciled, never silently accepted.
What counts as "truth"
- Intended state only. The SoT holds what should be: which VLANs exist, which IP is on
which interface, how devices cable together. It does not hold operational state (counters, BGP session
status) — that's observed, not declared.
- Single authority per fact. Each attribute has exactly one owning system. When facts live in
several places (an IPAM, a spreadsheet, DNS), you need a SoT-of-SoTs / aggregation layer with a
clear precedence, or they'll disagree.
- Config is derived, never hand-edited on the box. That's the whole contract.
NetBox as the SoT (DCIM + IPAM)
NetBox is the de-facto network SoT: a data model + REST/GraphQL API + webhooks. It models the
network as a hierarchy you traverse to render config:
| Layer | Models |
| Where | Region → Site → Location → Rack |
| What | Device (role, type, platform) → Interface → IP address |
| L2/L3 | VLAN, VLAN group, VRF, Prefix, IP range, aggregate |
| Connectivity | Cables / connections, circuits & providers |
| Org & extension | Tenancy, tags, custom fields, config contexts (structured data attached to devices) |
Generators pull this via the API (a device's interfaces, their IPs/VLANs, its neighbors) and render config —
exactly how Annet and
Ansible/Nornir use NetBox as inventory + intent.
Alternatives: Nautobot (adds jobs + Golden Config), Infrahub, or Git-as-SoT (versioned
YAML) for smaller setups.
Modeling: site → device → interface → IP
Model the real relationships, not flat lists, so the data is queryable and consistent:
Site "LHR1"
└─ Device "lhr1-leaf01" (role=leaf, platform=cisco_ios)
├─ Interface "Gi0/1" → IP 10.1.0.1/31 (VRF: default)
│ cable → lhr1-spine01 Gi0/1
└─ Interface "Vlan10" → IP 10.1.10.1/24 (VLAN 10 "users")
Prefix 10.1.0.0/16 (container, site=LHR1) → child prefixes per role
Now "give me every interface + IP on lhr1-leaf01" is one API query, and IP/VLAN uniqueness is enforced by the
model — no more overlapping subnets in a spreadsheet.
Data validation — trust the truth
A SoT that's wrong is worse than none (you automate the mistake at scale). Validate inputs:
- Schema / types: model intent with pydantic or JSON Schema so
bad data (a string where an int belongs, a missing gateway) fails fast, in CI, before it renders config.
- Referential integrity & rules: every access port has a VLAN; every P2P link is a /31; no
duplicate loopbacks; naming conventions. NetBox custom validators / Nautobot data-validation, or a pre-commit
check on the exported data.
- Report jobs: scheduled audits ("devices with no primary IP", "prefixes with no site") keep the
SoT clean over time.
Drift & the device-vs-SoT conflict
- Drift = divergence between the intended config (rendered from the SoT) and the
actual running-config (or operational state). Someone consoled in and made a change; a rollback left
residue; a manual "quick fix" stuck.
- Detect: periodically diff running-config vs intended (Annet
diff, NAPALM
compare_config, Nautobot Golden Config, Batfish) — see
Testing & CI/CD.
- Resolve — who wins? The SoT is authoritative, so the default is re-deploy the
intended config (revert the drift). If the manual change was legitimate, the fix is to update
the SoT and re-render — not to bless the box. The device never becomes the source of truth.
- Brownfield onboarding is the one time you read from the device: parse existing configs
to seed the SoT, review, then flip to SoT-driven going forward.
The pattern: SoT → intended → diff → deploy
The closed loop every mature stack runs:
- SoT — declare intent (NetBox / YAML in Git).
- Intended — render target config from it (generators/templates).
- Diff — fetch running-config, compare to intended (idempotent: no diff = no change).
- Deploy — push only the delta, with pre/post-checks and rollback.
Run it continuously and drift can't survive: every cycle re-asserts the truth.
Likely interview questions
- What is a Source of Truth, and why isn't the device's config the truth?
- Model a network in NetBox — walk site → device → interface → IP.
- What is config drift, how do you detect it, and who wins in a device-vs-SoT conflict?
- How do you validate SoT data before it renders config? (pydantic/JSON Schema, integrity rules, CI)
- Describe the SoT → intended → diff → deploy loop and why it's idempotent.
- How do you onboard a brownfield network into a SoT?
- What do you do when the same fact lives in two systems? (SoT-of-SoTs, precedence)
- NetBox vs Nautobot vs Git-as-SoT — trade-offs?