NetBox Routing Protocols
A NetBox plugin for modelling static routes, routing policy and BGP configuration alongside the devices and IPAM objects they belong to.
It gives you somewhere to record routing intent — which is the piece NetBox leaves to you — so that config generation, compliance checks and automation can read it back out of the API.
Features
Static routing
- Static routes bound to a device, VRF, prefix and next hop
- Explicit default-route modelling (
0.0.0.0/0/::/0) without needing a placeholder prefix - A Static Routes tab on the IPAM Prefix view
Routing policy
- Prefix lists with ordered, sequenced rules
- Prefix list rules matching a prefix, any prefix, or the default route, with
ge/lelength bounds - Route maps with ordered rules matching against prefix lists
- Optional automatic terminating
deny 9999rule on new prefix lists and route maps
BGP
- BGP routers per device and VRF, with ASN, router ID, AS-path handling and route reflection
- Peers addressed by IP or as unnumbered interface peers
- Peer groups, with peers inheriting group attributes
- Address families (IPv4 unicast, IPv6 unicast, L2VPN EVPN) at router, peer and peer-group level
- Per-address-family inbound and outbound route-map policy
- Network statements, aggregates and protocol redistribution
Every model supports the standard NetBox features: tags, custom fields, change logging, journaling, export templates, global search, the REST API and the GraphQL API.
Compatibility
| Plugin | NetBox | Python |
|---|---|---|
| 1.1.x | 4.6.x, 4.7.x | 3.12+ |
| 1.0.x | 4.6.x | 3.12+ |
Installation
Install into your NetBox virtual environment:
source /opt/netbox/venv/bin/activate
pip install netbox-routing-protocols
Add it to PLUGINS in configuration.py:
PLUGINS = [
'netbox_routing_protocols',
]
Run the migrations:
python manage.py migrate
Add the package to local_requirements.txt so it survives a NetBox upgrade:
echo netbox-routing-protocols >> /opt/netbox/local_requirements.txt
Restart NetBox:
sudo systemctl restart netbox netbox-rq
Configuration
All settings are optional.
PLUGINS_CONFIG = {
'netbox_routing_protocols': {
# Create a terminating "deny 9999 / match any" rule whenever a new prefix
# list or route map is created. Set to False to start them empty.
'create_default_deny_rule': True,
},
}
API
REST endpoints are published under /api/plugins/routing-protocols/, and all models are
exposed through NetBox's GraphQL API.
curl -H "Authorization: Token $NETBOX_TOKEN" \
https://netbox.example.com/api/plugins/routing-protocols/bgp-peers/?device=core-sw-01
⚠️ BGP passwords are stored and returned in clear
BGPPeer.password and BGPPeergroup.password hold the BGP MD5 authentication key. The field
is treated like any other: it is stored as entered and returned verbatim by the REST API,
the GraphQL API, the change log (and therefore webhook payloads), and the UI.
That is deliberate. The key has to reach device configuration, so config generation must be able to read it back — a value automation cannot retrieve would defeat the point of recording it here.
It does mean the value is readable by anyone who can view the object, and by anything holding
core.view_objectchange, plus anyone with database or Django shell access.
Store your platform's hashed or encrypted form, not the raw secret. Most network operating systems accept a pre-encrypted key and will render it straight into the configuration:
! Cisco IOS — type 7
neighbor 192.0.2.1 password 7 070C285F4D06
! Arista EOS — type 7
neighbor 192.0.2.1 password 7 <encrypted>
! Juniper — $9$ encrypted
set protocols bgp group EXTERNAL neighbor 192.0.2.1 authentication-key "$9$..."
Storing that form means NetBox never holds the raw secret, and the value can still be rendered into config unchanged.
Be aware of what this does and does not buy you. Cisco/Arista type 7 is obfuscation, not
encryption — it is trivially reversible, so it protects against casual exposure (a screenshot,
a shared export, an over-broad API token) rather than against an attacker who obtains the
value. Juniper $9$ is likewise reversible. If your platform supports a genuinely
non-reversible form, prefer it.
Regardless of which form you store, restrict object permissions to match the sensitivity, and treat database backups and webhook destinations as carrying secrets.
Contributing
Issues and pull requests are welcome at https://github.com/jasonyates/netbox-routing-protocols.
Generating migrations
Generate migrations against the oldest supported NetBox release (min_version in
__init__.py), not whichever one you happen to have installed. makemigrations records a
dependency on the newest migration of every app it references, so a migration generated
against a later patch release will fail on earlier ones with:
NodeNotFoundError: Migration netbox_routing_protocols.0001_initial dependencies
reference nonexistent parent node ('dcim', '0237_...')
CI runs the test matrix against both ends of the supported range, so this is caught before release rather than by users.
Licence
Apache-2.0. See LICENSE.
Release files for netbox-routing-protocols 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| netbox_routing_protocols-1.1.0.tar.gz | 79.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| netbox_routing_protocols-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 175.3 kB
Release files / netbox_routing_protocols-1.1.0.tar.gz
| Download URL | netbox_routing_protocols-1.1.0.tar.gz |
|---|---|
| Size | 79.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54b208b500d35b5000d339255fe6c322149f7e150c04f4158aaaeeae5e1b4ab7
|
|
BLAKE2b-256 checksum How to use checksums |
a8fb0227f2fb254f858f2aa3266a4e93f503d86e7df109cb69d215a0bfec02c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency logRelease files / netbox_routing_protocols-1.1.0-py3-none-any.whl
| Download URL | netbox_routing_protocols-1.1.0-py3-none-any.whl |
|---|---|
| Size | 96.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
231f1f30c7375c8bef9f1622cf9acfec9ca429de6f0438e7e1b3879610eb1469
|
|
BLAKE2b-256 checksum How to use checksums |
0e4025c76e7cf7627b25edd9a4ff3523261728bf0a47746f7091db8a498308ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.
Transparency log