Skip to main content

NetBox plugin for full integration with Windows DHCP Server via PowerShell Universal

Project description

netbox-windows-dhcp

A NetBox v4.5.0+ plugin for full integration with Windows DHCP Server via PowerShell Universal (PSU v5).

Features

  • Define Windows DHCP Servers (hostname, port, HTTP/HTTPS, App Token auth, optional SSL verification)
  • Define DHCP Failover relationships (Load Balance or Hot Standby)
  • Correlate DHCP Scopes with NetBox Prefixes (many scopes → one prefix)
  • Lease lifetime stored in seconds, displayed in the most readable unit (e.g. 3 Days, 73 Hours, 30 Minutes)
  • Global library of reusable DHCP Option Values with Option Code Definitions (pre-populated with all standard Windows DHCP built-in codes)
  • One-time Import from Server — pulls failovers, scopes, scope-level option values, and exclusion ranges from a live DHCP server into NetBox
  • Active sync mode: pull leases and reservations → create/update NetBox IP Addresses with status, DNS name, and client MAC
  • Stale record cleanup: expired leases and removed reservations are deleted or downgraded automatically
  • Push reservations, scope config, and exclusion ranges from NetBox → DHCP server (optional, settings-controlled)
  • DHCP Scopes panel injected into the NetBox Prefix detail view
  • All sync and import operations run as background jobs — no HTTP timeouts on large servers
  • All background job changes appear in the NetBox changelog (attributed to the user who queued the job)
  • Scheduled background sync (hourly by default, configurable) + manual Sync Now per server or for all servers
  • Full REST API for all plugin objects
  • Plugin-wide settings managed via the NetBox UI (no PLUGINS_CONFIG entry required)

Requirements

NetBox host

  • NetBox >= 4.5.0
  • Python >= 3.10
  • requests >= 2.28
  • NetBox RQ workers running (required for background sync and import jobs)

Each Windows DHCP server

  • Windows Server 2016 or later with the DHCP Server role installed
  • PowerShell Universal v5.x (tested on 5.6.11+) — see PSU Setup
  • DhcpServer PowerShell module (included with the DHCP Server role)

Installation

1. Install the package

pip install netbox-windows-dhcp

Or from source (editable install recommended for development):

pip install -e /path/to/netbox-windows-dhcp

2. Add to NetBox configuration (configuration.py)

PLUGINS = [
    'netbox_windows_dhcp',
]

No PLUGINS_CONFIG entry is required. All settings are managed through the plugin's Admin → Settings page in the NetBox UI.

3. Run migrations

python manage.py migrate

Running migrations also triggers the post_migrate signal which auto-registers the dhcp_client_id custom field on IP Address objects.

4. Restart NetBox

Restart gunicorn/uwsgi and the RQ workers.

Getting Started

Add a DHCP Server

  1. Go to Windows DHCP → Infrastructure → Servers → Add
  2. Enter the hostname/IP, port, and PSU App Token
  3. Toggle Use HTTPS as appropriate (default: on)
  4. Disable Verify SSL Certificate if the server uses a self-signed certificate

Import from a Server

Once a server is configured, click Import from Server on the server detail page to run a one-time background import of:

  • Failover relationships (matched to existing DHCP Server objects by hostname)
  • Scopes (NetBox Prefixes are created automatically if they don't exist)
  • Scope-level option values (unknown option codes are created automatically)
    • Option 3 (Router) and Option 51 (Lease Time) are skipped — they are stored directly on the Scope object

You will be redirected to the job status page where you can monitor progress and view the full results log. Existing records are skipped; the import never overwrites data already in NetBox.

Configure Sync Settings

Go to Windows DHCP → Admin → Settings to configure:

Setting Description
Sync IP Addresses from Leases & Reservations When checked, pull leases and reservations and create/update/delete NetBox IP Address records. When unchecked, sync scope config only.
Push Reservations to DHCP Server Push NetBox reserved IPs to the DHCP server as reservations
Push Scope Info to DHCP Server Push scope config changes from NetBox to the DHCP server
Sync Interval (minutes) How often the background sync runs (5–1440)
Sync Job Queue Worker queue priority (High / Default / Low) used for all sync and import background jobs. Default: Default.
Sync-Protected Tag A NetBox tag. Any IP Address carrying this tag is fully shielded from sync — its status, DNS name, and record itself are never modified or removed. Leave blank to disable.
Update Client ID for Protected IPs When enabled, the sync updates the dhcp_client_id custom field on protected IPs to match the DHCP server's active lease. All other sync writes remain blocked. Useful after a server replacement when the client MAC changes.

Editing Rules

Not all objects in the plugin support full CRUD. The table below summarises what operations are allowed and under what conditions.

Failover Relationships

Operation Allowed
View ✅ Always
Delete ✅ Always
Create ❌ Never — import from the DHCP server
Edit ✅ Via direct URL only (not exposed in the UI)

Failover relationships are created automatically during an Import from Server run. The Add button and Edit button are intentionally hidden from the list and detail views — relationships should be managed on the DHCP server and imported into NetBox. The Sync Enabled toggle on the list view is the primary way to manage a failover relationship after import.

DHCP Scopes

Operation Push Scope Info off Push Scope Info on
View
Create
Edit
Delete

When Push Scope Info to DHCP Server is disabled, the DHCP server is the source of truth for scope configuration. Scopes reach NetBox via Import from Server and are kept up to date by periodic sync. Direct edits are blocked to prevent NetBox from drifting out of sync with the server.

When Push Scope Info to DHCP Server is enabled, NetBox becomes the source of truth. Scope changes saved in NetBox are pushed to the DHCP server on the next sync. Full CRUD is permitted.

Note: Exclusion Ranges follow scope info — create, edit, and delete are permitted whenever Push Scope Info is enabled, and blocked when it is disabled.

IP Address Status Validation

Any IP Address with status dhcp must satisfy both of the following conditions when saved through the UI or REST API:

  1. The IP address must fall within the prefix of at least one configured DHCP Scope.
  2. The IP address must not fall within any exclusion range of that scope.

This validation runs during form submission and API writes. It does not run during background sync — the sync sets statuses based on authoritative data from the DHCP server and bypasses this check by design.

The reserved status is not validated against DHCP scope membership — it is a general-purpose NetBox status used for both DHCP reservations and non-DHCP purposes.

There are no UI-level restrictions on editing IP addresses with dhcp or reserved status beyond the above. Changes made manually to DHCP-managed IPs will be overwritten on the next sync if Sync IP Addresses from Leases & Reservations is enabled.

Scope Source

Every DHCP Scope must be associated with exactly one of:

  • Server — for standalone scopes that are not part of a failover relationship. Set automatically during Import from Server when the scope has no failover name.
  • Failover Relationship — for scopes managed under a Windows DHCP failover pair.

This association determines which server is responsible for syncing the scope. Standalone scopes are only synced against their assigned server; failover scopes are synced via the primary server of their failover relationship.

Sync Behavior

Scope eligibility

Not every scope is synced on every server. Before processing a scope, the sync checks eligibility:

Scope type Synced when
Standalone (has Server) Server's Sync Standalone Scopes is enabled, and the scope's assigned server matches the server being synced
Failover-linked The failover relationship's Sync Enabled is on, and the server being synced is the primary of that failover
Neither assigned Never synced

Server pre-flight: If a server has Sync Standalone Scopes disabled and is not the primary server for any active failover relationship, the sync skips it entirely — no network connection is made.

Per-failover sync control

Each failover relationship has a Sync Enabled toggle (visible on the failover list and toggleable per-row). When disabled, all scopes using that failover are excluded from sync. This allows pausing sync for a specific failover pair without affecting others.

IP Address sync

When Sync IP Addresses from Leases & Reservations is unchecked (default), the sync pulls and stores scope config only — no IP Address objects are created or modified.

When checked, the sync pulls leases and reservations from each DHCP server and creates/updates/deletes NetBox IP Address records.

IP Address lifecycle (active sync)

Creating and updating:

Source IPAddress.status dns_name dhcp_client_id
Active DHCP lease dhcp Hostname from DHCP (lowercased) Client MAC address
DHCP reservation reserved Name from reservation (lowercased) Client MAC address

Reservations take precedence — a reserved IP is not overwritten by a lease record for the same address.

Special case — reserved IP with no dhcp_client_id: If a reserved IP address has no dhcp_client_id set (e.g. it was manually created before the client MAC was known), and a lease is discovered on the DHCP server for that address, the sync will populate dhcp_client_id from the lease but will not change the status or dns_name. This allows the IP to be pre-registered before provisioning.

New IP Addresses are created using the prefix length of the associated scope's NetBox Prefix (not /32).

The dhcp_client_id custom field (auto-registered on IP Address) stores the client MAC address in Windows DHCP hyphen-separated format (00-11-22-33-44-55).

All IP Address creates and updates are recorded in the NetBox changelog, attributed to the user who queued the sync job. DHCP lease metadata (lease hostname, active status, expiration) is stored in a separate non-changelog side-table (DHCPLeaseInfo) and displayed on the IP Address detail page — these updates do not generate changelog entries.

Cleanup (stale record removal):

After syncing leases and reservations for a scope, the plugin removes records that no longer exist on the server:

NetBox status dhcp_client_id DHCP-managed? Server state Action
dhcp Lease still active No change
dhcp Lease expired or gone Deleted
reserved Any Never auto-deleted (pre-staged or manual)
reserved set No (manually created) Any Never auto-deleted
reserved set Yes (sync-created) Reservation still exists No change
reserved set Yes (sync-created) No reservation, but lease exists Downgraded to dhcp
reserved set Yes (sync-created) Neither reservation nor lease Deleted

"DHCP-managed" means the record was created or previously updated by the sync (indicated by a DHCPLeaseInfo side-record). Manually-created reserved IPs are never auto-deleted even if they have a dhcp_client_id.

Note: When Push Reservations to DHCP Server is enabled, NetBox is the source of truth for reservations. reserved IP Addresses with a dhcp_client_id are never deleted or downgraded based on server state — they will be pushed to the server on the next sync instead.

Scope cleanup:

When a scope exists in NetBox but is no longer reported by the DHCP server, and the server was successfully reached, and Push Scope Info to DHCP Server is disabled, the scope is deleted from NetBox. Only scopes whose Scope Source links them to the server being synced (either directly as a standalone scope, or via a failover relationship where this server is primary) are considered.

When Push Scope Info to DHCP Server is enabled, a scope missing from the server will instead be created on the server.

Safety: If the API call to fetch leases/reservations fails for a scope, cleanup is skipped for that scope. If list_scopes() fails entirely, the server is unreachable and no cleanup runs at all.

Pre-Staging IPs

To register a device in NetBox before its client MAC is known, create the IP Address with:

  • Status reserved
  • dns_name set to the planned canonical hostname
  • Leave dhcp_client_id blank

The sync will never delete or overwrite the status or dns_name of a reserved IP with no dhcp_client_id. If a lease appears on the DHCP server for that address, the sync populates dhcp_client_id from the lease (so the reservation can be pushed once the MAC is known) but leaves everything else unchanged.

Typical lifecycle:

  1. Create the IP in NetBox with status reserved, dns_name set to the planned hostname, and no dhcp_client_id.
  2. Device is provisioned; it receives a DHCP lease. The sync populates dhcp_client_id from the lease.
  3. Once dhcp_client_id is set, the reservation is pushed to the DHCP server on the next sync (if Push Reservations is enabled). The dns_name is used as the reservation name on the server.

Sync-Protected IPs

Any IP Address tagged with the configured Sync-Protected Tag is fully shielded from sync writes. The sync will never change its status, DNS name, or dhcp_client_id, and will never delete the record during cleanup.

DHCP lease metadata (DHCPLeaseInfo) is always updated for protected IPs regardless of protection status — the lease hostname, active state, and expiration are still recorded and visible on the IP Address detail page.

Update Client ID for Protected IPs

Enable this checkbox to allow one narrow exception: the sync may update the dhcp_client_id custom field on a protected IP when the server's active lease carries a different client MAC. All other writes (status, DNS name, record deletion) remain blocked. This is useful after a DHCP server replacement where the client MAC for the same device changes.

Typical use: Tag an IP as protected when it has been manually configured and should not be overwritten by automated sync, even if the DHCP server has a conflicting record.

Sync Now

The Sync Now button on a server detail page enqueues a background sync job and redirects to the job status page. The full sync log is visible there. A Sync All Servers action is also available from the server list page.

Lease Lifetime Display

Lease lifetimes are stored in seconds and displayed in the most readable exact unit:

  • 864001 Day
  • 2592003 Days
  • 26280073 Hours (not an exact number of days)
  • 36001 Hour
  • 601 Minute
  • 4545 Seconds

When configuring a scope, enter the value and select the unit (Seconds / Minutes / Hours / Days). The form defaults to 1 Day for new scopes. Values learned from the DHCP server are automatically decomposed to the largest clean unit.

Navigation

The plugin adds a Windows DHCP menu to the NetBox left sidebar:

  • Infrastructure → Servers, Failover
  • Scopes → Scopes
  • Options → Option Values, Option Code Definitions
  • Admin → Settings

PSU Setup

See psu/README.md for full deployment instructions.

The plugin expects PowerShell Universal v5.x (tested on 5.6.11+) on each DHCP server, exposing endpoints under /api/dhcp/. The PSU script is at psu/dhcp_api_endpoints.ps1.

Endpoint reference

Method Path Description
GET /api/dhcp/scopes List all scopes (includes router and failover name)
GET /api/dhcp/scopes/:scope_id Get a single scope
POST /api/dhcp/scopes Create a scope
PUT /api/dhcp/scopes/:scope_id Update a scope
GET /api/dhcp/leases[?scope_id=] List active leases
GET /api/dhcp/reservations[?scope_id=] List reservations
POST /api/dhcp/reservations Create a reservation
PUT /api/dhcp/reservations/:client_id Update a reservation
DELETE /api/dhcp/reservations/:client_id Delete a reservation
GET /api/dhcp/failover List failover relationships
POST /api/dhcp/failover Create a failover relationship
GET /api/dhcp/options/server Server-level option values
GET /api/dhcp/options/scope/:scope_id Scope-level option values
GET /api/dhcp/exclusions?scope_id= List exclusion ranges for a scope
POST /api/dhcp/exclusions Create an exclusion range
DELETE /api/dhcp/exclusions Delete an exclusion range (body: scope_id, start_ip, end_ip)

Authentication: PSU v5 App Tokens are sent as Authorization: Bearer <token>. Generate a token in the PSU admin console under Security → App Tokens and paste it into the App Token field on the DHCP Server object in NetBox.

REST API

The plugin exposes a REST API under /api/plugins/netbox-windows-dhcp/:

Endpoint Model
/servers/ DHCP Servers
/failover/ Failover relationships
/option-codes/ Option Code Definitions
/option-values/ Option Values
/scopes/ DHCP Scopes (includes nested exclusion_ranges)
/exclusion-ranges/ DHCP Exclusion Ranges

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

netbox_windows_dhcp-1.0.0.tar.gz (63.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

netbox_windows_dhcp-1.0.0-py3-none-any.whl (70.9 kB view details)

Uploaded Python 3

File details

Details for the file netbox_windows_dhcp-1.0.0.tar.gz.

File metadata

  • Download URL: netbox_windows_dhcp-1.0.0.tar.gz
  • Upload date:
  • Size: 63.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for netbox_windows_dhcp-1.0.0.tar.gz
Algorithm Hash digest
SHA256 a12b7756cce96464c3d0cc03487805046f90f9e163d9c406c78ce6d75bbfafb8
MD5 4cf4fd39369460817321ea5715972636
BLAKE2b-256 282a3b56f2a580fb9ce8467e8cf8a5d3266e9de857bdb326a7dfee5534148a69

See more details on using hashes here.

File details

Details for the file netbox_windows_dhcp-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for netbox_windows_dhcp-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f19e3f7ee7aef45d5c8e4563771337b9d1bd1f84b39c061efddcb4d79263ce65
MD5 909f491d70da24b234cb03a54d09e803
BLAKE2b-256 fa74c88721079e1dde597de3aac87247be40bf227e6a42abba0af6f1f1eb1009

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page