> ## Content Index
> Fetch the complete content index at: https://blog.sudowl.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# DHCP on Windows Server — Scopes, Reservations, and the Gotchas
- URL: https://blog.sudowl.com/windows-server-dhcp-setup/
- Published: 2026-05-14T10:00:00.000Z
- Updated: 2026-10-11T08:26:51.000Z
- Description: Set up the Windows Server DHCP role end to end in PowerShell — install, authorise in AD, scope, options, reservations, failover. The gotchas that cost real time.
- Author: Lukas
- Tags: Windows Server

The DHCP role on Windows Server is five minutes of work and one gotcha that eats an afternoon if you miss it: an unauthorised DHCP server in a domain hands out exactly zero leases, silently. Install it, authorise it, scope it — all from PowerShell, no wizard.

**TL;DR:**

```powershell
Install-WindowsFeature DHCP -IncludeManagementTools
netsh dhcp add securitygroups
Restart-Service dhcpserver
Add-DhcpServerInDC -DnsName dhcp01.lab.example.com -IPAddress 10.0.0.5
Add-DhcpServerv4Scope -Name "LAN" -StartRange 10.0.0.100 -EndRange 10.0.0.200 -SubnetMask 255.255.255.0
Set-DhcpServerv4OptionValue -ScopeId 10.0.0.0 -Router 10.0.0.1 -DnsServer 10.0.0.5 -DnsDomain lab.example.com

```

That's a working server. Details and the gotchas below.

## Install the role

```powershell
Install-WindowsFeature DHCP -IncludeManagementTools

```

`-IncludeManagementTools` pulls in the DHCP console and the PowerShell module. Skip it and you've installed a service you can't manage without a second command. No reboot needed.

The host needs a **static IP** before you go further. A DHCP server pulling its own address from another DHCP server is a circular mess — if you've just [run through the initial setup checklist](https://blog.sudowl.com/windows-server-initial-setup-checklist/) the static IP is already done.

## Post-install: security groups and the post-deploy step

Two things Server Manager nags you about after install. Do them in PowerShell instead:

```powershell
netsh dhcp add securitygroups
Restart-Service dhcpserver

```

This creates the local `DHCP Administrators` and `DHCP Users` groups and restarts the service to pick them up. Without it the service runs, but delegated admin won't work.

In the GUI there's a yellow "post-deployment configuration" notification that also marks the install as complete. The PowerShell equivalent flips a registry flag:

```powershell
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\ServerManager\Roles\12 `
  -Name ConfigurationState -Value 2

```

Purely cosmetic — it stops Server Manager pestering you. The server hands out leases regardless. I set it so the dashboard is green and the next admin doesn't think the install was abandoned half-way.

## Authorise in AD — the classic gotcha

```powershell
Add-DhcpServerInDC -DnsName dhcp01.lab.example.com -IPAddress 10.0.0.5

```

**This is the one that wastes the afternoon.** In an Active Directory domain, a DHCP server must be authorised in AD before it will respond to a single DISCOVER. No error in the GUI, no obvious log entry — clients just sit there with APIPA `169.254.x.x` addresses and you start blaming the switch.

The mechanism is deliberate: it stops a rogue DHCP server (someone's home router plugged into the LAN) from poisoning the network. Authorisation requires **Enterprise Admin** rights, because the record lives in the configuration partition of the forest.

Check what's authorised:

```powershell
Get-DhcpServerInDC

```

**The exception:** a standalone (workgroup) DHCP server doesn't need authorisation and `Add-DhcpServerInDC` will fail with no DC to talk to. That's fine — workgroup DHCP just works once the scope is active. Authorisation is an AD-only concept. If you're authorising, the host should already be [joined to the domain](https://blog.sudowl.com/join-windows-server-ad-domain-powershell/), ideally next to your [first domain controller](https://blog.sudowl.com/active-directory-promote-first-domain-controller/).

## Create a scope

```powershell
Add-DhcpServerv4Scope -Name "LAN" `
  -StartRange 10.0.0.100 -EndRange 10.0.0.200 `
  -SubnetMask 255.255.255.0 `
  -State Active

```

The `ScopeId` is derived from the range and mask — here it's `10.0.0.0`, and you reference it by that ID in every later command. The start/end range is the **pool that gets handed out**, not the whole subnet. Leave room below `.100` and above `.200` for static kit: gateways, switches, the DHCP server itself, printers you don't want chasing leases.

`-State Active` matters. Create a scope without it and it sits `InActive`, serving nothing, with no warning louder than a different colour in the console.

## Scope options — router, DNS, domain

```powershell
Set-DhcpServerv4OptionValue -ScopeId 10.0.0.0 `
  -Router 10.0.0.1 `
  -DnsServer 10.0.0.5 `
  -DnsDomain lab.example.com

```

These are the three options that actually matter day to day:

| Option | Cmdlet flag | What it sets                     |
| ------ | ----------- | -------------------------------- |
| 003    | \-Router    | Default gateway                  |
| 006    | \-DnsServer | DNS server(s) clients use        |
| 015    | \-DnsDomain | DNS suffix appended to hostnames |

In a domain, **option 006 must point at your DCs**, not a public resolver like `1.1.1.1`. Domain-joined clients that resolve through public DNS can't find `_ldap._tcp` SRV records and Group Policy quietly stops applying. This is a top-three cause of "GPO isn't working" tickets.

Set options at the server level (`-ScopeId` omitted, or via `Set-DhcpServerv4OptionValue` without a scope) for defaults that apply everywhere; set them per-scope to override. Per-scope wins.

## Reservations — pin a MAC to an IP

```powershell
Add-DhcpServerv4Reservation -ScopeId 10.0.0.0 `
  -IPAddress 10.0.0.150 `
  -ClientId "AA-BB-CC-DD-EE-FF" `
  -Description "office-printer"

```

`-ClientId` is the MAC. Dashes or no separators both parse; colons do not — `AA-BB-CC-DD-EE-FF` or `AABBCCDDEEFF`, never `AA:BB:...`. The reserved IP **must sit inside the scope range** or the reservation never fires.

Reservations beat static IPs on the device for anything that supports DHCP: change a subnet once on the server instead of touching every printer and NAS by hand. List them:

```powershell
Get-DhcpServerv4Reservation -ScopeId 10.0.0.0

```

## Exclusions — carve holes in the pool

```powershell
Add-DhcpServerv4ExclusionRange -ScopeId 10.0.0.0 `
  -StartRange 10.0.0.100 -EndRange 10.0.0.110

```

Use this when you want a scope to cover a wide range but keep a block free for static assignment — e.g. you scoped `.100`–`.200` but want `.100`–`.110` reserved for servers you'll address by hand. Excluded addresses are never offered, even though they're inside the pool.

## Lease duration and conflict detection

```powershell
Set-DhcpServerv4Scope -ScopeId 10.0.0.0 -LeaseDuration 8.00:00:00   # 8 days
Set-DhcpServerSetting -ConflictDetectionAttempts 1

```

Default lease is 8 days — fine for a stable office. Drop it to a few hours on guest/transient networks where devices churn, so the pool recycles fast. Don't go below an hour on a busy LAN or you'll flood the server with renewals.

**Conflict detection** makes the server ping an address before offering it. Off by default (zero attempts) for speed. Set it to `1` or `2` if you've got static IPs squatting inside the pool and want to avoid handing out a duplicate. It adds latency to every lease, so leave it at `0` on a clean network.

## Failover — redundancy in two commands

One DHCP server is a single point of failure: it dies, leases expire, the LAN goes dark. Modern Windows Server does this properly with **DHCP failover** — no more manual 80/20 split-scope juggling.

```powershell
Add-DhcpServerv4Failover -Name "LAN-failover" `
  -PartnerServer dhcp02.lab.example.com `
  -ScopeId 10.0.0.0 `
  -LoadBalancePercent 50 `
  -SharedSecret (Read-Host -AsSecureString)

```

Both servers serve the same scope, sync lease state, and cover for each other. `LoadBalance` mode splits active load 50/50; `HotStandby` mode keeps the partner idle until the primary drops. The partner needs the DHCP role installed and authorised first — failover replicates the scope config for you, so you don't recreate it by hand.

## Verify

```powershell
Get-DhcpServerInDC                                  # authorised?
Get-DhcpServerv4Scope                                # scope active?
Get-DhcpServerv4OptionValue -ScopeId 10.0.0.0        # options set?
Get-DhcpServerv4Lease -ScopeId 10.0.0.0              # anyone leasing?

```

If `Get-DhcpServerv4Lease` returns rows with real hostnames, you're done. Empty on a live network means clients aren't getting offers — work back up the list.

## Gotchas

- **No leases, no error, in a domain** — almost always missing `Add-DhcpServerInDC`. Check `Get-DhcpServerInDC` first, every time.
- **Scope created but dead** — `State` is `InActive`. Set `-State Active` or `Set-DhcpServerv4Scope -State Active`.
- **GPO stops applying after DHCP changes** — option 006 points at a public DNS instead of your DCs. Domain clients need domain DNS.
- **Reservation ignored** — colon-separated MAC, or the reserved IP sits outside the scope range. Both fail quietly.
- **Two DHCP servers, intermittent wrong gateway** — you stood up a second server without failover and both are answering independently. Use `Add-DhcpServerv4Failover`, not two parallel scopes.
- **`Add-DhcpServerInDC` errors on a workgroup box** — expected, there's no AD. Standalone DHCP needs no authorisation; ignore it.

Five commands to a working server, one of which everyone forgets. Authorise in AD first and the rest is plumbing.

---

### Related posts

- [Active Directory Part 2 — OUs, Users, and GPO Basics](https://blog.diengdoh.com/active-directory-part-2-ous-users-gpo-basics/?ref=blog.sudowl.com)
- [Active Directory Part 1 — Promoting Your First Domain Controller](https://blog.diengdoh.com/active-directory-promote-first-domain-controller/?ref=blog.sudowl.com)
- [PowerShell for Sysadmins — A Cheatsheet From My Daily Use](https://blog.diengdoh.com/powershell-sysadmin-cheatsheet/?ref=blog.sudowl.com)