Quick Start — Get a DHCP Server Running in 5 Minutes
Six months ago I replaced an aging router — it was doing double-duty as a DHCP host and starting to flake out — with a dedicated Ubuntu 22.04 box. Three subnets and six months of production use later, the Linux setup hasn’t missed a beat. It’s more stable and more flexible than any consumer firmware I’ve dealt with.
The fastest path to a working DHCP server on Linux is dnsmasq. It handles DHCP and DNS in one lightweight package — perfect if you don’t need enterprise-grade features yet.
# Install dnsmasq
sudo apt update && sudo apt install -y dnsmasq
# Stop systemd-resolved if it's occupying port 53
sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
Edit the main config file:
sudo nano /etc/dnsmasq.conf
Add these lines (adjust the interface and IP range to match your network):
interface=eth1
bind-interfaces
dhcp-range=192.168.10.100,192.168.10.200,24h
dhcp-option=option:router,192.168.10.1
dhcp-option=option:dns-server,8.8.8.8,1.1.1.1
Start it up:
sudo systemctl restart dnsmasq
sudo systemctl enable dnsmasq
That’s the minimum to hand out IPs on your local network. If you need more control — static leases, multiple subnets, PXE boot — keep reading.
Deep Dive — ISC DHCP Server for Full Control
When my setup grew to handle three VLANs and a PXE boot environment, dnsmasq started showing its limits. I switched to isc-dhcp-server (the classic dhcpd), which gives you granular control over every aspect of address assignment.
Installation
sudo apt install -y isc-dhcp-server
Declare the Listening Interface
Edit /etc/default/isc-dhcp-server to tell dhcpd which interface to listen on:
INTERFACESv4="eth1"
Write the Main Config
The real config lives at /etc/dhcp/dhcpd.conf. Here’s a production-ready example with static reservations and sensible lease times:
# Global settings
default-lease-time 86400; # 24 hours
max-lease-time 604800; # 7 days
authoritative;
# Subnet declaration
subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.100 192.168.10.200;
option routers 192.168.10.1;
option subnet-mask 255.255.255.0;
option domain-name-servers 8.8.8.8, 1.1.1.1;
option broadcast-address 192.168.10.255;
}
# Static lease for a server
host fileserver {
hardware ethernet aa:bb:cc:dd:ee:ff;
fixed-address 192.168.10.50;
}
Start and Verify
sudo systemctl restart isc-dhcp-server
sudo systemctl enable isc-dhcp-server
# Check status
sudo systemctl status isc-dhcp-server
# Watch leases in real time
sudo tail -f /var/lib/dhcp/dhcpd.leases
If the service fails to start, the config parser usually gives you a clear error message. Run sudo dhcpd -t -cf /etc/dhcp/dhcpd.conf to validate the config without restarting the service.
Understanding the Lease File
The lease database at /var/lib/dhcp/dhcpd.leases records every assignment. Entries look like this:
lease 192.168.10.105 {
starts 5 2024/01/12 02:30:00;
ends 6 2024/01/13 02:30:00;
binding state active;
hardware ethernet 11:22:33:44:55:66;
client-hostname "laptop-dev";
}
This file is append-only — expired entries pile up over time. That’s normal. dhcpd rewrites it periodically to keep it from growing forever.
Advanced Usage
Multiple Subnets and VLANs
By month two, I needed multi-subnet support. The approach: one virtual interface per VLAN on the Linux host, or a trunk port on a managed switch. Here’s how to create the VLAN interfaces:
# Create VLAN interfaces (requires vlan package)
sudo ip link add link eth1 name eth1.20 type vlan id 20
sudo ip addr add 192.168.20.1/24 dev eth1.20
sudo ip link set eth1.20 up
Then add another subnet block in dhcpd.conf:
subnet 192.168.20.0 netmask 255.255.255.0 {
range 192.168.20.50 192.168.20.150;
option routers 192.168.20.1;
option domain-name-servers 8.8.8.8;
}
Update the interface line in /etc/default/isc-dhcp-server:
INTERFACESv4="eth1 eth1.20"
PXE Boot Support
Deploying machines via network boot? Add these options to your subnet block:
subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.100 192.168.10.200;
option routers 192.168.10.1;
option domain-name-servers 8.8.8.8;
# PXE boot options
filename "pxelinux.0";
next-server 192.168.10.10; # IP of your TFTP server
}
Monitoring Active Leases
For quick visibility, I wrote a small alias to parse the lease file into a readable table:
alias dhcp-leases='grep -E "lease|hardware|client-hostname" /var/lib/dhcp/dhcpd.leases | paste - - -'
For something more structured, dhcpd-pools gives pool utilization stats:
sudo apt install dhcpd-pools
dhcpd-pools -c /etc/dhcp/dhcpd.conf -l /var/lib/dhcp/dhcpd.leases
Practical Tips from Six Months in Production
Always Run dhcpd -t Before Restarting
A config syntax error will silently kill your DHCP service. Make this a habit:
sudo dhcpd -t -cf /etc/dhcp/dhcpd.conf && sudo systemctl restart isc-dhcp-server
Set Up a Failover Pair
Don’t skip this step. When your DHCP server goes down, every new device on the network fails to get an IP — they connect, wait through a 60-second timeout, and give up. ISC DHCP has a native failover protocol built in. Two servers share lease state, so clients can renew from either one:
# On the primary server, add inside the subnet block:
failover peer "dhcp-failover" {
primary;
address 192.168.10.1;
port 647;
peer address 192.168.10.2;
peer port 647;
max-response-delay 60;
max-unacked-updates 10;
load balance max seconds 3;
mclt 3600;
split 128;
}
The secondary mirrors the same config with secondary; instead of primary;.
Firewall Rules
Don’t forget to allow DHCP traffic through your firewall. DHCP uses UDP ports 67 (server) and 68 (client):
sudo ufw allow 67/udp
sudo ufw allow 68/udp
Log Everything Useful
dhcpd logs to syslog by default. Filter just DHCP activity with:
sudo journalctl -u isc-dhcp-server -f
Prefer persistent log files? Redirect in /etc/dhcp/dhcpd.conf:
log-facility local7;
Then configure rsyslog to write local7.* to /var/log/dhcpd.log.
dnsmasq vs isc-dhcp-server — When to Use Which
- dnsmasq: Home lab, small office, combined DNS+DHCP on one box, minimal config overhead.
- isc-dhcp-server: Multiple subnets, failover, PXE boot, complex option sets, fine-grained lease control.
Both work great in production. Pick based on how much complexity you actually need to manage — not reputation.

