DHCP mini-HOWTO: Linux DHCP clients and Kea or dnsmasq servers
DHCP hands out IP addresses, the default gateway and DNS servers automatically. On a Linux client you rarely touch it: NetworkManager or systemd-networkd does the work. For a server, the old ISC dhcpd has been end of life since the end of 2022; use Kea for real networks or dnsmasq for a small LAN.
The classic DHCP mini-HOWTO from 2000 is kept by the Linux Documentation Project at tldp.org. This page covers current releases as of November 2026.
How a lease works
A new client broadcasts DHCPDISCOVER on UDP port 67. Servers reply with an offer, the client requests one offer, and the chosen server acknowledges it. The client may then use the address for the lease time. Halfway through, it tries to renew with the same server; if that fails, it asks any server later on. Every lease carries options: the subnet mask, router (option 3), DNS servers (option 6), domain name, and more. Because DHCP starts with broadcasts, a server only sees clients on its own network segment unless a router relays the requests.
Client side
NetworkManager
Fedora, RHEL and its clones, and desktop installs of Debian and Ubuntu use NetworkManager. Its built-in (“internal”) DHCP client is the default; the other choices for the dhcp= setting in NetworkManager.conf depend on how your distribution built NetworkManager (the upstream manual lists internal and dhcpcd). A wired profile uses DHCP unless you set a static address:
nmcli device status
nmcli connection show
sudo nmcli connection modify "Wired connection 1" ipv4.method auto ipv6.method auto
sudo nmcli connection up "Wired connection 1" # re-runs DHCP
nmcli -f DHCP4 device show enp1s0 # the lease and its options
systemd-networkd
Servers and minimal installs often use systemd-networkd (Ubuntu Server writes its files through netplan). A DHCP interface needs only a .network file, for example /etc/systemd/network/20-wired.network:
[Match]
Name=enp1s0
[Network]
DHCP=yes
DHCP= accepts yes, no, ipv4 or ipv6. Apply and check:
sudo networkctl reload
networkctl status enp1s0
sudo networkctl renew enp1s0
dhclient and dhcpcd
dhclient is part of the ISC DHCP suite and is no longer maintained upstream. Debian 13 still packages it (isc-dhcp-client), and classic ifupdown (/etc/network/interfaces with iface eth0 inet dhcp) tries dhclient, then udhcpc, then dhcpcd, whichever is installed. Installing dhcpcd-base gives ifupdown a maintained client. On new systems, prefer NetworkManager or networkd.
Which server to run
| Server | Status | Good for |
|---|---|---|
| ISC dhcpd | End of maintenance since end of 2022; last releases 4.4.3-P1 and 4.1-ESV-R16-P2 (October 2022) | Nothing new; migrate away |
| ISC Kea | Maintained. Upstream branches: 3.0 (long-term support), 3.2 (stable), 3.3 (development). Debian 13 ships 2.6; Fedora 43 and 44 ship 3.0, Fedora 45 ships 3.2; RHEL 10 documents Kea as its DHCP server | Offices, campuses, ISPs; JSON config, REST API, database back ends, high availability |
| dnsmasq | Maintained | Home and small office routers; DHCP and DNS caching in one small daemon |
| systemd-networkd | Maintained | A simple server on one interface, such as a lab or VM network |
Run only one DHCP server per network segment, and switch off the DHCP server in your Internet router if Linux takes over.
Kea DHCPv4 server
# Debian / Ubuntu
sudo apt install kea-dhcp4-server
# Fedora / RHEL 10 / Alma / Rocky — the package is "kea"
sudo dnf install kea
Both put the config in /etc/kea/kea-dhcp4.conf. The service is kea-dhcp4-server on Debian and Ubuntu and kea-dhcp4 on Fedora. ISC also publishes its own packages for current branches. This complete file serves 192.168.1.0/24 on interface enp2s0, with the router and DNS server at 192.168.1.1 and one fixed address:
{
"Dhcp4": {
"interfaces-config": {
"interfaces": [ "enp2s0" ]
},
"lease-database": {
"type": "memfile",
"persist": true,
"lfc-interval": 3600
},
"valid-lifetime": 43200,
"renew-timer": 21600,
"rebind-timer": 37800,
"option-data": [
{ "name": "domain-name-servers", "data": "192.168.1.1" },
{ "name": "domain-name", "data": "lan" }
],
"subnet4": [
{
"id": 1,
"subnet": "192.168.1.0/24",
"pools": [
{ "pool": "192.168.1.100 - 192.168.1.199" }
],
"option-data": [
{ "name": "routers", "data": "192.168.1.1" }
],
"reservations": [
{
"hw-address": "52:54:00:12:34:56",
"ip-address": "192.168.1.20",
"hostname": "nas"
}
]
}
]
}
}
Times are in seconds: a 43,200-second lease is 12 hours, renewal starts at 6 hours (21,600) and rebinding at 10.5 hours (37,800). The file is JSON: no trailing commas, every string in double quotes. Give every subnet a unique, stable id. Keep reserved addresses outside the pool (here .20 is below .100) so Kea never hands them to another machine.
Test the file, then start the server:
sudo kea-dhcp4 -t /etc/kea/kea-dhcp4.conf && echo OK
sudo systemctl enable --now kea-dhcp4-server # Fedora: kea-dhcp4
journalctl -u kea-dhcp4-server -f
-t parses and checks the file and exits with 0 when it is valid; it also fails if the named interface does not exist on the machine. Leases are written to /var/lib/kea/kea-leases4.csv. Open the firewall for DHCP on the LAN side only: with firewalld, add the service to the zone that holds the LAN interface (for example sudo firewall-cmd --permanent --zone=internal --add-service=dhcp, then sudo firewall-cmd --reload); with ufw, sudo ufw allow in on enp2s0 to any port 67 proto udp.
Coming from dhcpd? The subnet { range …; option routers …; host … { hardware ethernet …; fixed-address …; } } blocks of dhcpd.conf map directly onto subnet4, pools, option-data and reservations. ISC links migration help from its ISC DHCP page, and Fedora packages ISC’s conversion tool as kea-keama.
dnsmasq for a small network
dnsmasq combines a DHCP server, a DNS cache and a TFTP server. It reads /etc/dnsmasq.conf at startup. Each line is a long command-line option without the leading --. Install with sudo apt install dnsmasq or sudo dnf install dnsmasq, then add:
interface=enp2s0
bind-interfaces
domain=lan
expand-hosts
dhcp-range=192.168.1.100,192.168.1.199,12h
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.1
dhcp-host=52:54:00:12:34:56,192.168.1.20,nas
dhcp-authoritative
dhcp-host is the reservation: MAC address, IP address, host name. dhcp-authoritative tells dnsmasq it is the only DHCP server on this network; set it only when that is true. With expand-hosts and domain=lan, DHCP clients become resolvable as name.lan through dnsmasq’s DNS side.
dnsmasq --test # prints "dnsmasq: syntax check OK."
sudo systemctl enable --now dnsmasq
cat /var/lib/misc/dnsmasq.leases # current leases (Debian/Ubuntu)
sudo cat /var/lib/dnsmasq/dnsmasq.leases # Fedora/RHEL
Port 53 clash. dnsmasq also starts a DNS server. If systemd-resolved or another resolver already owns port 53 on the same address, keep bind-interfaces and the interface= line so dnsmasq only binds the LAN interface, or add port=0 to turn its DNS side off. Sharing an Internet connection with dnsmasq is covered in the IP Masquerade HOWTO.
A tiny server with systemd-networkd
For a lab network or a bridge for virtual machines, networkd can serve DHCP itself:
[Match]
Name=enp2s0
[Network]
Address=192.168.50.1/24
DHCPServer=yes
[DHCPServer]
PoolOffset=100
PoolSize=50
EmitDNS=yes
DNS=192.168.50.1
[DHCPServerStaticLease]
MACAddress=52:54:00:12:34:56
Address=192.168.50.20
This hands out 192.168.50.100 to .149, gives the router address (the server itself) automatically, and always gives the listed MAC address .20.
Troubleshooting
- No offer at all: watch the wire with
sudo tcpdump -ni enp2s0 port 67 or port 68. If you see DISCOVER but no OFFER, the server is not listening on that interface or the firewall blocks UDP 67. - Two servers answering: clients get random gateways. Find the other one in the tcpdump output (the OFFER’s source address) and disable it.
- Clients on another subnet: they need a DHCP relay on the router, and the server needs a subnet entry that matches the relay’s address.
- Reservation ignored: check the MAC address. Many phones and laptops use a random MAC per Wi-Fi network; turn that off for that network on the device, or reserve by client identifier.
- Wrong DNS on clients: check the lease options with
nmcli -f DHCP4 device showornetworkctl status, then see the DNS HOWTO.
Sources
- ISC DHCP: end of maintenance and final releases, ISC
- Kea DHCP versions and support dates, ISC
- Kea Administrator Reference Manual: the DHCPv4 server, ISC
- kea-dhcp4-server package file list, Debian 13
- kea package sources (version and kea-dhcp4.service), Fedora
- kea package versions per release, Fedora Packages
- Managing networking infrastructure services (Kea), RHEL 10 documentation
- isc-dhcp-client package, Debian 13
- dnsmasq manual page, thekelleys.org.uk
- systemd.network(5), man7.org
- NetworkManager.conf(5), NetworkManager project
- interfaces(5), Debian 13 manual pages