How to Set Up a DHCP Server on Linux: A Field-Tested Guide

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

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.

Share: