Manage NetBox prefixes and Kea DHCP scopes together from a single subnet definition under config/<region>/<dc>/subnets/<name>.yaml. - modules/ipam: netbox_prefix + netbox_ip_range (dhcp role) + gateway/managed netbox_ip_address + kea_subnet; tokens read from Vault KV via the vault provider - environments/au/syd1 terragrunt env, Consul state backend - config seed: five DHCP subnets (198.18.13-17) + local netbox-only 198.18.25.0/24 - .woodpecker pre-commit+plan on PR, apply on main; Makefile Vault auth pattern Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
terraform-ipam
YAML-driven Terraform/Terragrunt for IP address management: it manages NetBox IPAM prefixes and Kea DHCP scopes together from a single subnet definition.
Defining a subnet creates the NetBox prefix, optionally a DHCP scope in Kea (via
the kea provider against the KeaAPI), marks the DHCP range in NetBox, and
records the gateway.
Layout
config/<region>/<dc>/subnets/<name>.yaml # one file per subnet, filename = subnet name
config/<region>/<dc>/managed-ips.yaml # extra manually-managed IPs
environments/<region>/<dc>/terragrunt.hcl # one Terragrunt env per region/dc
modules/ipam/ # the subnet module
make plan / make apply (via Terragrunt) reconcile the YAML against NetBox +
Kea. State lives in Consul under infra/terraform/ipam/<region>/<dc>/state.
Subnet schema (config/<region>/<dc>/subnets/<name>.yaml)
prefix: 198.18.15.0/24
description: syd1 production
site: syd1 # NetBox site slug (optional; resolved to site_id)
dhcp: # omit the whole block for a NetBox-only prefix
enabled: true
start: 200 # host-octet int; pool/range start
stop: 220 # host-octet int; pool/range stop
router: 254 # host-octet int; recorded as the gateway IP
dns: [198.18.200.7]
next_server: 198.18.19.19
domain: main.unkin.net
Resource mapping per subnet:
| YAML | Resource |
|---|---|
prefix |
netbox_prefix (status=active, description, site_id) |
dhcp.start/stop |
netbox_ip_range (role dhcp) + kea_subnet pool |
router |
netbox_ip_address <router>/mask description gateway |
dns/next_server/domain |
kea_subnet dns_servers / next_server / domain_name |
Host-octet ints are expanded against the prefix with cidrhost(). A subnet with
no dhcp block is NetBox-only (e.g. local.yaml = 198.18.25.0/24 — excluded
from Kea). The dhcp role is a single shared netbox_ipam_role. PXE boot files
are handled by Kea cluster client-classes, not here.
Managed IPs (config/<region>/<dc>/managed-ips.yaml)
A list of {ip, description} (ip in full CIDR form) rendered as netbox_ip_address.
Providers
| Provider | Source | Notes |
|---|---|---|
| netbox | e-breuninger/netbox 4.3.0 |
community provider from the OpenTofu registry |
| kea | artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/kea 0.0.1 |
KeaAPI; cluster_ref=kea |
| vault | hashicorp/vault 5.6.0 |
reads the KeaAPI + NetBox tokens |
Endpoints (module variable defaults): NetBox https://netbox.k8s.syd1.au.unkin.net,
KeaAPI http://kea-api.dhcp-system.svc:8080 (ClusterIP, in-cluster only).
Tokens are read at plan time from Vault KV v2 kv/service/terraform/ipam with
fields netbox_token and kea_token (the vault provider authenticates with the
CI VAULT_TOKEN).
Deployment status / blockers
- NetBox is not deployed on the cluster yet (only on the unmerged
benvin/netboxargocd-apps branch; hostnetbox.k8s.syd1.au.unkin.net). Until it is live and reachable,plan/applyagainst NetBox will fail. - KeaAPI is not deployed yet (only on the unmerged
benvin/kea-deploymentargocd-apps branch;KeaAPICRkea-api, nsdhcp-system, ClusterIP:8080). - Seed
kv/service/terraform/ipamin Vault withnetbox_token+kea_tokenbefore the pipeline can authenticate to either API. - Confirm the
keaprovider 0.0.1 is published to theterraform-unkinArtifactAPI registry (release the provider repo if not).