Pi-hole as a Primary DNS Server
Beyond Ad Blocking
Pi-hole is best known for network-wide ad blocking, but it’s also a fully capable DNS server. This guide covers the DNS features — configuring Pi-hole as your network’s primary resolver with custom upstream servers, local DNS records, conditional forwarding, and DNSSEC. If you’ve already deployed Pi-hole for ad blocking, you already have a DNS server. This guide shows you how to use it.
For the ad blocking setup guide, see Pi-hole: Network-Wide Ad Blocking. For dedicated recursive DNS resolution, see Unbound.
Prerequisites
- Pi-hole deployed and running (Pi-hole setup guide)
- Docker and Docker Compose installed (guide)
- Access to your router’s DHCP settings (to point clients at Pi-hole)
- Understanding of DNS concepts (DNS Explained)
Docker Compose Configuration
If you haven’t deployed Pi-hole yet, here’s the Docker Compose focused on DNS functionality:
services:
pihole:
image: pihole/pihole:2025.03.0
container_name: pihole
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp" # Web admin interface
environment:
TZ: "UTC"
WEBPASSWORD: ${PIHOLE_PASSWORD} # Set in .env
PIHOLE_DNS_: "1.1.1.1;9.9.9.9" # Upstream DNS (semicolon-separated)
DNSSEC: "true" # Enable DNSSEC validation
REV_SERVER: "true" # Enable conditional forwarding
REV_SERVER_DOMAIN: "home.lan" # Your local domain
REV_SERVER_TARGET: "192.168.1.1" # Your router IP
REV_SERVER_CIDR: "192.168.1.0/24" # Your LAN subnet
volumes:
- pihole-data:/etc/pihole
- pihole-dnsmasq:/etc/dnsmasq.d
restart: unless-stopped
healthcheck:
test: ["CMD", "dig", "+norecurse", "+retry=0", "@127.0.0.1", "pi.hole"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
volumes:
pihole-data:
pihole-dnsmasq:
Create the .env file:
cat > .env << 'EOF'
PIHOLE_PASSWORD=change-this-admin-password
EOF
Start Pi-hole:
docker compose up -d
Configuring Upstream DNS
Web UI Method
- Open
http://your-server-ip/admin - Go to Settings > DNS
- Select or enter your preferred upstream DNS servers
Environment Variable Method
Set upstream resolvers via PIHOLE_DNS_:
# Single provider
PIHOLE_DNS_: "1.1.1.1;1.0.0.1"
# Mixed providers
PIHOLE_DNS_: "1.1.1.1;9.9.9.9"
# Use Unbound as upstream (local recursive resolver)
PIHOLE_DNS_: "172.20.0.2#53"
Upstream Provider Comparison
| Provider | IPs | Features | Privacy |
|---|---|---|---|
| Cloudflare | 1.1.1.1, 1.0.0.1 | Fastest, malware filtering options | Purges logs in 24h |
| Quad9 | 9.9.9.9, 149.112.112.112 | Malware blocking built-in | Non-profit, no logging |
8.8.8.8, 8.8.4.4 | Most reliable | Logs queries | |
| Unbound | Your server IP | Full recursive, no third party | Maximum privacy |
| Technitium | Your server IP | Recursive + DNS-over-HTTPS | Self-controlled |
For maximum privacy, pair Pi-hole with a local Unbound instance — see the “Pairing With Unbound” section below.
Local DNS Records
Pi-hole can serve custom DNS entries for your local network, eliminating the need to edit /etc/hosts on every device.
Via Web UI
- Go to Local DNS > DNS Records
- Add entries:
nas.home.lan→192.168.1.100proxmox.home.lan→192.168.1.50jellyfin.home.lan→192.168.1.10
Via Configuration File
Create a custom dnsmasq configuration:
cat > /opt/pihole/custom-dns.conf << 'EOF'
# Local DNS entries
address=/nas.home.lan/192.168.1.100
address=/proxmox.home.lan/192.168.1.50
address=/jellyfin.home.lan/192.168.1.10
address=/.home.lan/192.168.1.10 # Wildcard: all *.home.lan → server
EOF
Mount it into the container:
volumes:
- pihole-data:/etc/pihole
- pihole-dnsmasq:/etc/dnsmasq.d
- ./custom-dns.conf:/etc/dnsmasq.d/05-custom-dns.conf:ro
CNAME Records
For pointing subdomains to other local hostnames:
cat > /opt/pihole/custom-cname.conf << 'EOF'
cname=nextcloud.home.lan,docker.home.lan
cname=grafana.home.lan,docker.home.lan
EOF
Mount as /etc/dnsmasq.d/06-custom-cname.conf:ro.
Conditional Forwarding
Conditional forwarding lets Pi-hole resolve local hostnames (like mypc.home.lan) by forwarding reverse DNS lookups to your router:
environment:
REV_SERVER: "true"
REV_SERVER_DOMAIN: "home.lan"
REV_SERVER_TARGET: "192.168.1.1"
REV_SERVER_CIDR: "192.168.1.0/24"
This means when Pi-hole receives a query for 192.168.1.47, it asks your router’s DNS, which knows the hostname from DHCP. Without this, Pi-hole can only show IP addresses in its query log — not device names.
DNSSEC Validation
Enable DNSSEC to verify DNS response authenticity:
environment:
DNSSEC: "true"
Pi-hole validates DNSSEC signatures on responses from upstream servers. If a response fails validation, Pi-hole returns SERVFAIL instead of a potentially spoofed answer.
Important: DNSSEC only works when your upstream DNS servers support it. Cloudflare (1.1.1.1) and Quad9 (9.9.9.9) both support DNSSEC. Google (8.8.8.8) supports it too. If using Unbound as upstream, it validates DNSSEC independently.
Pairing With Unbound (Recursive DNS)
The most private DNS setup: Pi-hole handles ad blocking, Unbound handles recursive resolution. No third-party DNS provider sees your queries.
Client → Pi-hole (ad blocking) → Unbound (recursive DNS) → Root servers
Deploy both with a shared Docker network:
services:
pihole:
image: pihole/pihole:2025.03.0
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
environment:
PIHOLE_DNS_: "172.20.0.2#53" # Unbound's IP on the shared network
DNSSEC: "false" # Unbound handles DNSSEC
networks:
dns:
ipv4_address: 172.20.0.3
volumes:
- pihole-data:/etc/pihole
- pihole-dnsmasq:/etc/dnsmasq.d
restart: unless-stopped
unbound:
image: mvance/unbound:1.22.0
networks:
dns:
ipv4_address: 172.20.0.2
restart: unless-stopped
networks:
dns:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
volumes:
pihole-data:
pihole-dnsmasq:
Disable DNSSEC in Pi-hole when using Unbound — Unbound validates DNSSEC independently, and double-validation can cause false failures.
See Network-Wide Ad Blocking for the full setup guide.
Making Pi-hole Your Network’s DNS
Router Configuration
The recommended approach — all devices automatically use Pi-hole:
- Open your router’s admin panel
- Find DHCP settings
- Set the primary DNS server to your Pi-hole server’s IP
- Remove or leave blank the secondary DNS (otherwise clients may bypass Pi-hole)
- Renew DHCP leases on clients (or reboot them)
Per-Device Configuration
For individual devices:
Linux:
echo "nameserver 192.168.1.10" | sudo tee /etc/resolv.conf
macOS: System Preferences > Network > Advanced > DNS > Add your server IP
Windows: Network adapter settings > IPv4 > DNS server addresses
iOS/Android: WiFi settings > Configure DNS > Manual > Add your server IP
Troubleshooting
Devices Can’t Resolve DNS After Setup
Symptom: Websites don’t load after pointing DNS at Pi-hole
Fix: Verify Pi-hole is reachable:
dig @192.168.1.10 google.com
If this works but devices can’t resolve, check your router’s DHCP settings are distributing the correct DNS IP.
Local DNS Entries Not Resolving
Symptom: Custom local DNS records return NXDOMAIN
Fix: Verify the custom config file is mounted correctly and Pi-hole can read it:
docker exec pihole cat /etc/dnsmasq.d/05-custom-dns.conf
docker exec pihole pihole restartdns
DNSSEC Causing Failures
Symptom: Some domains return SERVFAIL with DNSSEC enabled
Fix: Some domains have misconfigured DNSSEC records. Check a specific domain:
dig @127.0.0.1 example.com +dnssec
If legitimate sites fail, you may need to disable DNSSEC or switch to an upstream that handles DNSSEC validation (like Unbound).
Resource Requirements
| Resource | Value |
|---|---|
| RAM | ~100 MB idle, ~200 MB with large blocklists |
| CPU | Low — dnsmasq is highly efficient |
| Disk | ~200 MB for container + logs grow over time |
| Network | Minimal; all DNS traffic is tiny |
Verdict
If you’re already running Pi-hole for ad blocking, you have 80% of a solid network DNS server. Adding local DNS records, conditional forwarding, and DNSSEC turns it into a complete solution. Pair it with Unbound for recursive resolution and you’ve built a fully self-hosted DNS stack that no third party touches.
For users who want DNS server features without the ad blocking, Technitium offers a similar web-managed experience focused purely on DNS. For maximum flexibility with plugin-driven configuration, CoreDNS is the way to go.
FAQ
What’s the difference between this guide and the Pi-hole ad blocking guide?
The Pi-hole setup guide covers initial Docker deployment and ad blocking configuration. This guide covers using Pi-hole specifically as a DNS server — upstream configuration, local DNS records, conditional forwarding, DNSSEC, and pairing with recursive resolvers.
Should I disable my router’s DNS if Pi-hole is my DNS server?
Point your router’s DHCP to distribute Pi-hole’s IP as the DNS server. Don’t set a secondary DNS to your router or a public provider — clients will use the secondary to bypass Pi-hole.
Can Pi-hole do DNS-over-HTTPS or DNS-over-TLS?
Pi-hole itself doesn’t natively support encrypted DNS protocols. Use AdGuard Home if you need built-in DoH/DoT support, or pair Pi-hole with an upstream that encrypts (like Unbound with DoT forwarding or Cloudflare’s DoH endpoint via cloudflared).
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments