$linuxjunkies
>

How to Set Up a DHCP Server on Linux

Install and configure ISC DHCP or Kea on Linux: define scopes, set static reservations, inspect leases, open firewall ports, and hook into dynamic DNS.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • Root or sudo access on the server
  • A static IP already configured on the server's LAN interface
  • No other DHCP server active on the same network segment
  • Basic familiarity with systemd service management

A DHCP server hands out IP addresses, gateways, DNS servers, and other network parameters automatically to clients on your LAN. On Linux, two solid choices exist: the venerable ISC DHCP (isc-dhcp-server) and the modern replacement Kea, also from ISC. ISC DHCP is still widely deployed and well-documented; Kea is its actively developed successor with a REST API and better scalability. This guide covers both, including scopes, static reservations, lease inspection, and a basic DDNS hook.

Prerequisites and Planning

Before touching a package manager, decide:

  • Subnet and range — e.g., 192.168.10.0/24, dynamic pool 192.168.10.100–200
  • Router (gateway) IP — the host's LAN interface address or a dedicated router
  • DNS servers — upstream resolvers or your own (e.g., 192.168.10.1)
  • Which interface to listen on — run ip link to confirm (eth0, enp3s0, etc.)

Only one DHCP server should be authoritative per broadcast domain. If your router already runs DHCP, disable it before starting this server.

Option A — ISC DHCP Server

1. Install isc-dhcp-server

Debian/Ubuntu:

sudo apt update && sudo apt install isc-dhcp-server -y

Fedora / RHEL 8+ / Rocky:

sudo dnf install dhcp-server -y

Arch Linux:

sudo pacman -S dhcp

2. Bind to the Correct Interface

On Debian/Ubuntu, edit /etc/default/isc-dhcp-server and set the interface:

INTERFACESv4="enp3s0"

On Fedora/RHEL/Arch the interface is declared inside dhcpd.conf itself, so this step is Debian-specific.

3. Write the Main Configuration

Edit /etc/dhcp/dhcpd.conf (Debian/Ubuntu/Arch) or /etc/dhcp/dhcpd.conf (Fedora/RHEL — same path). Replace values to match your network:

# Global options
default-lease-time 86400;       # 24 hours
max-lease-time 172800;          # 48 hours
authoritative;

option domain-name "home.lan";
option domain-name-servers 192.168.10.1, 8.8.8.8;

# Subnet scope
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 broadcast-address 192.168.10.255;
}

# Static reservation (match by MAC address)
host printer01 {
  hardware ethernet aa:bb:cc:dd:ee:ff;
  fixed-address 192.168.10.50;
  option host-name "printer01";
}

The authoritative; directive tells the daemon to send DHCPNAK when a client requests an address outside the defined scope — essential on a production LAN.

4. Enable and Start the Service

sudo systemctl enable --now isc-dhcp-server     # Debian/Ubuntu
sudo systemctl enable --now dhcpd               # Fedora/RHEL/Rocky/Arch

5. Verify Leases

Active leases are written to /var/lib/dhcp/dhcpd.leases (Debian/Ubuntu) or /var/lib/dhcpd/dhcpd.leases (Fedora/RHEL). Read them directly or use dhcp-lease-list if installed:

cat /var/lib/dhcp/dhcpd.leases

Output will show blocks like lease 192.168.10.105 { ... } with timestamps and client MAC addresses.

Option B — Kea DHCP Server

Kea is the ISC's modern replacement. It uses JSON configuration, supports a REST API, and separates DHCPv4, DHCPv6, and DDNS into individual daemons.

1. Install Kea

Debian/Ubuntu (22.04+):

sudo apt install kea -y

Fedora 38+ / RHEL 9 via EPEL:

sudo dnf install epel-release -y
sudo dnf install kea -y

Arch Linux (AUR):

yay -S kea

2. Configure kea-dhcp4

The primary config lives at /etc/kea/kea-dhcp4.conf. A minimal working example:

{
  "Dhcp4": {
    "interfaces-config": {
      "interfaces": ["enp3s0"]
    },
    "lease-database": {
      "type": "memfile",
      "persist": true,
      "name": "/var/lib/kea/kea-leases4.csv"
    },
    "valid-lifetime": 86400,
    "max-valid-lifetime": 172800,
    "option-data": [
      { "name": "domain-name-servers", "data": "192.168.10.1, 8.8.8.8" },
      { "name": "domain-name",         "data": "home.lan" }
    ],
    "subnet4": [
      {
        "subnet": "192.168.10.0/24",
        "pools": [ { "pool": "192.168.10.100 - 192.168.10.200" } ],
        "option-data": [
          { "name": "routers", "data": "192.168.10.1" }
        ],
        "reservations": [
          {
            "hw-address": "aa:bb:cc:dd:ee:ff",
            "ip-address":  "192.168.10.50",
            "hostname":    "printer01"
          }
        ]
      }
    ]
  }
}

3. Validate and Start Kea

sudo kea-dhcp4 -t /etc/kea/kea-dhcp4.conf   # dry-run syntax check
sudo systemctl enable --now kea-dhcp4

4. Inspect Kea Leases

Kea writes a CSV lease file rather than the flat text format used by ISC DHCP:

cat /var/lib/kea/kea-leases4.csv

Columns include address, hwaddr, client_id, valid_lifetime, expire, hostname, and state. You can also query the live daemon via its control socket if the control-socket stanza is configured.

Firewall Rules

DHCP uses UDP ports 67 (server) and 68 (client). Allow inbound on the server:

nftables:

sudo nft add rule inet filter input udp dport 67 accept

firewalld (Fedora/RHEL):

sudo firewall-cmd --permanent --add-service=dhcp
sudo firewall-cmd --reload

ufw (Ubuntu/Debian):

sudo ufw allow 67/udp

Integrating with DNS (Dynamic DNS)

When a client gets an address, you can update a local DNS server (e.g., BIND or Unbound) automatically. With ISC DHCP, add a ddns-update-style directive and generate a TSIG key shared with BIND:

# Generate a TSIG key
tsig-keygen -a hmac-sha256 dhcp-ddns-key | sudo tee /etc/dhcp/ddns.key
# In dhcpd.conf, add:
ddns-update-style interim;
ddns-domainname "home.lan.";
ddns-rev-domainname "in-addr.arpa.";
include "/etc/dhcp/ddns.key";

zone home.lan. {
  primary 127.0.0.1;
  key dhcp-ddns-key;
}
zone 10.168.192.in-addr.arpa. {
  primary 127.0.0.1;
  key dhcp-ddns-key;
}

With Kea, DDNS is handled by the separate kea-dhcp-ddns daemon and configured in /etc/kea/kea-dhcp-ddns.conf. Enable it alongside kea-dhcp4:

sudo systemctl enable --now kea-dhcp-ddns

Troubleshooting

  • Clients get no address — Confirm the daemon is running (systemctl status isc-dhcp-server or kea-dhcp4), the interface name in config matches reality (ip link), and the firewall allows UDP 67.
  • Config syntax errors — ISC DHCP logs to journalctl -u isc-dhcp-server -e. Kea errors appear in /var/log/kea/kea-dhcp4.log or journald.
  • Address pool exhausted — Check dhcpd.leases or the Kea CSV for stale entries. Reduce default-lease-time or expand the pool range.
  • Reservation not working — MAC address must match exactly, including case. Use ip link show on the client or check lease logs to confirm the address the server sees.
  • Two DHCP servers on same segment — Use tcpdump -i enp3s0 port 67 or port 68 to identify rogue DHCP offers. Kill or disable any conflicting server.
tested on:Ubuntu 24.04Debian 12Fedora 40Rocky 9

Frequently asked questions

Should I use ISC DHCP or Kea for a new deployment?
Prefer Kea for new setups. ISC DHCP entered maintenance-only mode; Kea receives active development, supports a REST API, and handles high-availability configurations more cleanly.
Can I run a DHCP server on the same machine as my router or firewall?
Yes, and it's common. Just ensure the daemon binds only to the internal LAN interface and that your firewall rules allow UDP 67 inbound on that interface only.
How do I see which MAC address a client is using without physical access?
Run 'sudo tcpdump -i enp3s0 -n port 67 or port 68' on the server while the client requests an address; the DHCP DISCOVER packet contains the client's MAC.
What is the difference between a lease time and a reservation?
A lease time controls how long a dynamically assigned address is valid before the client must renew. A reservation permanently maps a specific MAC to a specific IP regardless of lease duration.
My Kea config change isn't taking effect after a reload. Why?
Kea does not re-read its config file on SIGHUP like ISC DHCP does. You must fully restart the service with 'systemctl restart kea-dhcp4', or use the control socket to issue a config-reload command via kea-shell.

Related guides