Skip to main content

netbox-kea-ng

PyPI PyPI - Downloads CI Coverage CodeQL REUSE License Python NetBox

Fork notice: This is netbox-kea-ng, an independently maintained fork of netbox-kea by Devon Mar. It is published to PyPI as netbox-kea-ng and tracked in this repository. Upstream changes are periodically merged where applicable.

NetBox plugin for the Kea DHCP server. Manage your DHCP infrastructure directly from NetBox — view daemon status, search and manage leases, manage host reservations, configure subnets/pools/options, and keep your NetBox IPAM synchronized with live Kea data via a background job.

Features

Core (from upstream)

  • View Kea daemon status (DHCPv4/DHCPv6 daemons — and the Control Agent on Kea < 3.0)
  • Full DHCPv4 and DHCPv6 support
  • Search, view, delete and export DHCP leases
  • Search for NetBox devices/VMs directly from DHCP leases
  • View DHCP subnets from Kea configuration
  • REST API and GraphQL support for Server objects

Additions in this fork

Host Reservations

  • Full CRUD for DHCPv4 and DHCPv6 reservations via host_cmds and subnet_cmds hooks
  • Identifier types: hw-address (v4), DUID (v6), client-id, flex-id, circuit-id, remote-id
  • Reservations that reserve no address — an identifier-only host (hostname, options or client classes only) and a DHCPv6 host that only delegates prefixes. Both are listed, created, edited and deleted by client identifier instead of by IP, and the IPAM sync reports them as skipped: there is no address to record in NetBox. Their Lease column matches the client identifier against the leases of the reservation's own subnet, there being no reserved address to match on
  • Per-reservation DHCP options
  • Journal entries on add/edit/delete
  • Validated YAML or JSON bulk transfer. Export a Complete Snapshot from one server or the combined view, then import it from the matching DHCPv4 or DHCPv6 Reservations page

Subnet Management

  • Add, edit and delete subnets (requires subnet_cmds or config-set)
  • Pool management (add/delete pools per subnet)
  • Shared network management (add/edit/delete)
  • Per-subnet and global DHCP option editing

IPAM Sync

  • Sync active leases → NetBox IPAddress (status active)
  • Sync reservations → NetBox IPAddress (status reserved)
  • Sync button on individual leases and reservations
  • Bulk sync for entire lease tables
  • Pending-change detection: badge on leases where a reservation exists at a different IP
  • MAC address sync → NetBox MACAddress
  • Sets dns_name on IPAddress for automatic DNS sync via netbox-dns IPAMDNSsync

Periodic Background Sync (requires rqworker)

  • Automatic Kea→NetBox IPAM sync on a configurable interval (default 5 minutes)
  • Syncs all leases and reservations from all configured servers
  • Visible in NetBox System → Background Jobs

DHCP Control

  • Enable/disable DHCPv4 and DHCPv6 daemons from the NetBox UI

Dual-URL Server

  • Optional separate URLs for the DHCPv4 and DHCPv6 endpoints
  • Supports Kea 3.0+ (each daemon exposes its own HTTP control socket) and split v4/v6 deployments

Global / Cross-Server Views

  • Combined dashboard, lease, reservation, subnet and shared-network views across all servers

Lease Add / Edit / Bulk Import

  • Add and edit individual leases
  • Bulk import leases from CSV

Requirements

  • NetBox 4.3 – 4.7
  • Kea 3.0+ (recommended) — the plugin connects directly to each daemon's built-in HTTP control socket (kea-dhcp4 / kea-dhcp6). The Kea Control Agent was deprecated in Kea 2.7 and removed in 3.0; on Kea < 3.0, point the server URL at the Control Agent instead.
  • lease_cmds hook library (for lease search and management)
  • stat_cmds hook library (for guarded Subnet lease searches unless lease_query_max_unpaged_leases is 0)
  • Kea 3.1.5+ for state-filtered Subnet lease searches. Earlier releases do not provide the scoped state commands, so these searches fail closed.
  • host_cmds hook library (optional, for reservation management — also requires subnet_cmds to resolve a reservation's subnet from its CIDR)
  • subnet_cmds hook library (optional, for subnet add/edit/delete, reservation management, and the subnet suggestions on the lease search and reservation forms)

The plugin degrades gracefully when optional hooks are absent — tabs for unavailable features are hidden automatically. Two pages offer the server's configured subnets as suggestions and read them through subnet_cmds; without that hook each says so in a banner rather than silently offering nothing:

  • Lease search keeps working: the Search field offers no subnet suggestions, so type an exact configured subnet CIDR or ID.
  • Add reservation cannot save, because resolving the entered CIDR to a Kea subnet ID needs subnet_cmds. Load the hook first.

Compatibility

netbox-kea-ng NetBox Kea
1.x 4.3 – 4.7 3.0+ recommended (2.4+ via Control Agent)

On Kea 3.0+ the plugin talks directly to each DHCP daemon's HTTP control socket; on Kea < 3.0 it connects through the (now-deprecated) Control Agent. CI tests against Kea 3.2.0 using the memfile lease database.

netbox-branching

In a netbox-branching branch, the plugin is read-only. CI tests NetBox 4.7 with netbox-branching 1.2.1. List netbox_branching last in PLUGINS.

  • Kea servers, sync settings and DHCP plugin links stay in main. A branch has no copy of them, so it shows main's values.
  • Kea data is live, in main and in every branch.
  • In a branch, the plugin refuses every change that comes through its web pages or its REST API, before it sends anything to Kea or writes to the database. A page shows HTTP 409 with a link to main; the REST API answers 409 with the code branch_write_refused. Plugin pages show a banner, and plugin and GraphQL responses carry an X-NetBox-Kea-Sources header.
  • A change request that still selects a branch that you can no longer use changes nothing. A _branch query that names a merged, archived, or not ready branch, and an active_branch cookie that names such a branch or a deleted one, get HTTP 409 with the code branch_selection_unusable. netbox-branching answers HTTP 400 first when a _branch query names a deleted branch, and when an API X-NetBox-Branch header names a deleted or unusable branch. Select main (?_branch=) and try again.
  • Code that runs outside a web request (a custom script, for example) is also refused in a branch. A save or a delete of a Kea server, the sync settings or a DHCP plugin link raises BranchActive, and so does a Kea command that changes Kea, from a client that Server.get_client() returns. The periodic IPAM sync job fails when it runs in a branch.
  • A merge fails, and changes nothing, when the branch deletes a VRF that a Kea server in main now syncs into. Clear or change that server's Sync VRF, then merge again.

Upgrade with open branches. Earlier releases let netbox-branching copy the Kea servers table into each new branch. Nothing removes that copy: branch sync no longer updates it, and branch migrate does not drop it. NetBox still reads Kea servers from main, but a VRF delete in the branch checks the old copy, not main. A merge also applies to main every Kea server change that the branch recorded before the upgrade. Before you upgrade, merge or delete every branch that is not yet merged, and create new branches after the upgrade. If a branch changed a Kea server password, delete it and make the change again in main: the change log holds a placeholder, not the password, so a merge can write the placeholder to main. A merged branch keeps its schema until you archive it; archive it when you no longer need to revert it.


Installation

1. Install the package

Add netbox-kea-ng to your local_requirements.txt (or install with pip):

pip install netbox-kea-ng

2. Enable the plugin

In configuration.py:

PLUGINS = ["netbox_kea"]

Optionally configure plugin settings (see Configuration):

PLUGINS_CONFIG = {
    "netbox_kea": {
        "kea_timeout": 30,
        "lease_query_max_unpaged_leases": 1000,
        "sync_interval_minutes": 5,
        "sync_leases_enabled": True,
        "sync_reservations_enabled": True,
        "sync_prefixes_enabled": True,
        "sync_ip_ranges_enabled": True,
        "sync_max_leases_per_server": 50000,
        "stale_ip_cleanup": "remove",
    }
}

3. Run migrations

./manage.py migrate

4. Start the background worker (required for periodic sync)

The periodic IPAM sync job runs via NetBox's built-in rqworker. If you're not already running it:

./manage.py rqworker

The Kea IPAM Sync job will appear under System → Background Jobs and runs on the configured interval.


Configuration

All settings are under PLUGINS_CONFIG["netbox_kea"]:

Setting Default Description
kea_timeout 30 HTTP request timeout in seconds for Kea API calls
lease_query_max_unpaged_leases 1000 Reject an unpaged Subnet lease query when its Kea statistics count exceeds this limit. Set to 0 to disable this safety check
stale_ip_cleanup "remove" What to do with stale IPs after sync: "remove" (delete), "deprecate" (set status=deprecated), "none" (skip)
sync_interval_minutes 5 Initial interval of the background sync job (minutes). Edit it later on the Sync Jobs page
sync_leases_enabled True Sync active DHCP leases to NetBox IPAM
sync_reservations_enabled True Sync Kea reservations to NetBox IPAM
sync_prefixes_enabled True Sync Kea subnets to NetBox IPAM as IP Prefixes
sync_ip_ranges_enabled True Sync Kea pools to NetBox IPAM as IP Ranges
sync_max_leases_per_server 50000 Hard cap on leases fetched per server per sync run. Set to 0 for no limit

./manage.py migrate reads sync_interval_minutes, sync_enabled and the four sync_*_enabled toggles once, when it creates the Sync Configuration. After that, the Sync Jobs page holds these values, and a later change to these settings in PLUGINS_CONFIG has no effect.

Subnet lease searches use stat-lease4-get or stat-lease6-get before an unpaged lease command. Kea statistics can reject a query that is already too large. They cannot prove that an unqualified query is below the limit because stored expired states are not included in all statistics. Select Active or Declined to narrow a large query. Other states require an exact IP address or client identifier search. The guard fails closed when the stat_cmds hook is not available. State-filtered searches also fail closed when Kea does not support the scoped state commands. Set the limit to 0 only when you accept unbounded responses.

A Configuration Change holds a PostgreSQL advisory lock in an open transaction for all of its Kea requests, up to and including the save to disk. A PostgreSQL idle_in_transaction_session_timeout or a connection pooler timeout shorter than the longest Configuration Change ends that transaction and releases the lock while the change runs, so set these timeouts longer.


Server Configuration

Single-URL (Control Agent, or a single-protocol daemon)

Point one Server URL at a Kea endpoint that serves every enabled protocol — a Control Agent (Kea < 3.0, which fronts both DHCPv4 and DHCPv6), or a single DHCP daemon's HTTP control socket (Kea 3.0+) when the server runs only DHCPv4 or only DHCPv6. A dual-stack Kea 3.0+ deployment needs one URL per daemon — see Dual-URL below.

Field Description
CA / Server URL (ca_url) URL of the Kea HTTP endpoint — a DHCP daemon control socket (Kea 3.0+) or the Control Agent (Kea < 3.0), e.g. https://kea.example.com:8000
DHCPv4 Enable DHCPv4 lease/reservation/subnet management
DHCPv6 Enable DHCPv6 lease/reservation/subnet management
CA Username (ca_username) / CA Password (ca_password) HTTP Basic Auth credentials (if required)
CA File Path Path to a custom CA certificate file for TLS verification
SSL Verification Enable/disable TLS certificate verification (enabled by default)

Dual-URL (separate v4/v6 processes)

When DHCPv4 and DHCPv6 have separate endpoints — the norm on Kea 3.0+, where each daemon exposes its own HTTP control socket:

Field Description
DHCPv4 URL URL of the DHCPv4 daemon's HTTP control socket (or its Control Agent on Kea < 3.0)
DHCPv6 URL URL of the DHCPv6 daemon's HTTP control socket (or its Control Agent on Kea < 3.0)

The main CA URL (ca_url) is required and acts as a fallback for any protocol without a dedicated URL. By default, both DHCPv4 URL and DHCPv6 URL use CA-level credentials; see Per-protocol credentials below for optional overrides.


Per-protocol credentials

When connecting directly to DHCP daemons (bypassing the Control Agent), you can configure separate credentials per protocol:

Field Description
dhcp4_username Username for the DHCPv4 daemon (overrides ca_username for DHCPv4)
dhcp4_password Password for the DHCPv4 daemon (overrides ca_password for DHCPv4)
dhcp6_username Username for the DHCPv6 daemon (overrides ca_username for DHCPv6)
dhcp6_password Password for the DHCPv6 daemon (overrides ca_password for DHCPv6)

If per-protocol credentials are not set, the CA-level credentials (ca_username/ca_password) are used as the default for all connections.


Per-server IPAM sync settings

Each server has optional overrides for the IPAM sync job:

Field Default Description
IPAM Sync Enabled (sync_enabled) True Include this server in the periodic sync job
Sync Leases (sync_leases_enabled) True Sync active DHCP leases as NetBox IP Addresses
Sync Reservations (sync_reservations_enabled) True Sync DHCP reservations as NetBox IP Addresses
Sync Prefixes (sync_prefixes_enabled) True Sync Kea subnets as NetBox IP Prefixes
Sync IP Ranges (sync_ip_ranges_enabled) True Sync Kea pools as NetBox IP Ranges
Sync VRF (sync_vrf) None (global routing table) VRF to assign when syncing Prefixes and IP Ranges. There is no global fallback: leave blank to use the global routing table (no VRF). NetBox refuses to delete a VRF while a server syncs into it
Persist configuration (persist_config) True Automatically save Kea config after each change via config-write. Disable when Kea config is managed externally (e.g. Ansible)

These fields override the global PLUGINS_CONFIG values for that specific server.


Background IPAM Sync

The Kea IPAM Sync job runs automatically when rqworker is active:

  1. Iterates all configured Server objects
  2. For each server: fetches all active leases (v4 + v6) and all reservations
  3. Creates or updates NetBox IPAddress objects:
    • Leases → status=active, dns_name set from Kea hostname
    • Reservations → status=reserved, dns_name set from Kea hostname
  4. Cleans up stale IPs (configurable via stale_ip_cleanup)
  5. One server failing does not block others
  6. Summary logged per server and in total

Each server's summary reports created, updated, errors, prefix_errors, conflicts and skipped:

  • skipped — rows the sync deliberately did not write, chiefly reservations that reserve no address. They are not errors and do not fail the job.
  • errors — rows that failed to sync. Any error fails the job; the per-row reason is logged at warning level with the server, IP version, subnet id and identifier type (never the identifier value, which can carry operator data).
  • conflicts — addresses already held in NetBox by something other than this Kea server, deduplicated per server across the lease and reservation phases. Up to 20 of them are named in the summary and the log, so the addresses to look at are visible without trawling debug output.

View job history, next scheduled time and logs under System → Background Jobs → Kea IPAM Sync.

To change the sync interval, edit it on the Sync Jobs page. You do not need to restart the worker: the new interval applies after the next scheduled run.


DNS Integration

When netbox-dns with IPAMDNSsync is installed:

  1. The IPAM sync sets dns_name on IPAddress objects from the Kea hostname
  2. IPAMDNSsync picks up dns_name changes via Django signals
  3. A/AAAA/PTR records are created automatically (provided matching DNS views + zones exist)

No additional configuration is required — the integration is automatic when both plugins are present.


Add custom links to NetBox models to navigate directly to Kea lease searches.

Replace <Kea Server ID> with your server's object ID (visible in the top-right corner of the server detail page as netbox_kea.server:<ID>).

Show DHCP leases for a prefix

Content type: IPAM > Prefix

URL: https://netbox.example.com/plugins/kea/servers/<Kea Server ID>/leases{{ object.prefix.version }}/?q={{ object.prefix }}&by=subnet

Show DHCP leases for a device/VM interface (by MAC)

Content types: DCIM > Interface, Virtualization > Interface

DHCPv4 URL: https://netbox.example.com/plugins/kea/servers/<Kea Server ID>/leases4/?q={{ object.mac_address }}&by=hw

DHCPv6 URL: https://netbox.example.com/plugins/kea/servers/<Kea Server ID>/leases6/?q={{ object.mac_address }}&by=hw

Show DHCP leases for a device/VM (by hostname)

Content types: DCIM > Device, Virtualization > Virtual Machine

DHCPv4 URL: https://netbox.example.com/plugins/kea/servers/<Kea Server ID>/leases4/?q={{ object.name|lower }}&by=hostname

DHCPv6 URL: https://netbox.example.com/plugins/kea/servers/<Kea Server ID>/leases6/?q={{ object.name|lower }}&by=hostname

You can substitute {{ object.name|lower }} with a custom field: {{ object.cf.<your_field>|lower }}.


Development

# Install dev dependencies
uv sync

# Lint
uv run ruff check .
uv run ruff format --check .

# REUSE compliance check
uv run reuse lint

# Format
uv run ruff format .

# Install pre-commit hooks
uv run pre-commit install

# Build wheel (required before integration tests)
uv build

# Run unit tests; both variables are required (see AGENTS.md for picking values)
TEST_DB_NAME=test_netbox_kea_local TEST_REDIS_HOST=localhost \
  uv run --native-tls pytest --reuse-db -n auto --maxschedchunk=1 -q

# Run integration tests (requires Docker — see tests/test_setup.sh)
./tests/test_setup.sh
uv run --native-tls pytest -p no:django tests/ --tracing=retain-on-failure -v --cov=netbox_kea --cov-report=xml

See CHANGELOG for version history.


License

Apache-2.0 — original code by Devon Mar, fork maintained by Marcin Zieba.

Metadata

Release files for netbox-kea-ng 1.12.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for netbox-kea-ng 1.12.0
File Size Uploaded Provenance
netbox_kea_ng-1.12.0.tar.gz 692.8 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for netbox-kea-ng 1.12.0
File Interpreter ABI Platform
netbox_kea_ng-1.12.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / netbox_kea_ng-1.12.0.tar.gz

Download URL netbox_kea_ng-1.12.0.tar.gz
Size 692.8 kB
Tags Source
SHA-256 checksum
How to use checksums
5a08029b0c49e46a0f0ce70d31f1f975ff09f6aa51f674b2fbadb03933b3e216
BLAKE2b-256 checksum
How to use checksums
b28fa42375a9b59ff6826b7fd1327509d8ecabcbf564209d7667e9dc8cfd2ecf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / netbox_kea_ng-1.12.0-py3-none-any.whl

Download URL netbox_kea_ng-1.12.0-py3-none-any.whl
Size 318.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b88073827709789166cfe139a36efb1221f3f06102c0446dc51afc728ae86897
BLAKE2b-256 checksum
How to use checksums
dc99a481c5edf212746ef4a5b6c72ff69a49c745ad8376ba19685b7ee04fd560
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for netbox-kea-ng 1.12.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.12.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page