vinnymarquez.dev/tutorials/migrating off legacy dhcp, to kea
August 5, 20263 min readcheat sheet#networking#homelab#dhcp

Migrating Off Legacy DHCP, to Kea

ISC dhcpd is end-of-life upstream. moving to Kea, field by field, on a flat network — no VLANs required first.

before touching VLANs at all — see From Flat LAN to Segmented Homelab if you’re here for that — there was a smaller, easier migration sitting in front of it.

ISC dhcpd, the classic DHCP server most router/firewall OSes shipped with for years, is end-of-life upstream. no more security fixes. Kea is the actively maintained replacement, and on most modern router OSes it’s already sitting there, usually already the recommended default.

this one’s a good first project because it’s low-stakes: no new hardware, no VLANs, runs on whatever flat network you already have.

before you start

document your current scope — subnet, range, gateway, DNS servers (and their order, if you run a primary/fallback resolver setup), any static mappings. this is your rollback reference if anything goes sideways.

check for anything that doesn’t map 1:1:

legacy feature Kea equivalent what to do
free-text “additional options” structured option picker re-enter each option explicitly, raw text doesn’t translate
PXE boot fields network-booting fields, if present verify the field exists in your version first
failover peer config Kea High Availability separate reconfiguration, not a checkbox flip
dynamic DNS registration Kea DDNS tab re-verify against your resolver setup
static ARP / deny-unknown “authoritative” flag / reservation-only mode behavior differs, re-test after cutover

version check first — exact field names drift between releases. Kea went from opt-in to default over a few versions, and some installs might already have the legacy backend fully removed.

the actual steps

  1. backup. full config export before touching anything.
  2. enable Kea, general settings. tick the interface it should listen on, set a real lease lifetime — Kea’s built-in default is often much shorter than legacy dhcpd’s implicit behavior, and 24h is a saner homelab default.
  3. recreate the subnet. subnet, pool range — check this doesn’t silently expand to the entire available range, gateway, DNS servers in the same order as before.
  4. recreate static reservations. subnet + IP + MAC + hostname per device. leave option overrides blank unless that one device genuinely needs something different from the rest of the subnet.
  5. re-enter custom options found in the audit above, if any actually apply.
  6. disable the legacy backend on the same interface — both can’t serve it at once.
  7. apply, then check the log for startup errors.
  8. validate — release/renew a test client, confirm IP/gateway/DNS, confirm the lease shows up (lease history doesn’t carry over from the old file, expected).
Kea subnet edit form

the gotcha that got me

the pool range field defaulted to the entire available range on save, not the range i’d actually used with legacy dhcpd. easy to miss, and it matters if you’re relying on a specific low range staying free for static reservations.

also worth checking: some Kea UIs hide the manual router/DNS fields behind an “auto-collect option data” toggle — if you don’t see the fields you expect, that’s probably why.

rollback

re-enable the legacy backend, disable Kea for that interface. both configs stay stored independently, so toggling back is immediate. full restore from the step-1 backup if it’s worse than that.

this one took about twenty minutes end to end, and it’s the kind of infrastructure work that’s invisible when it’s working — which is exactly the point.

▌ comments