August 23, 2026

Pi-hole and the DNS Sinkhole Mechanism

How Pi-hole works as a DNS sinkhole: the query path through FTL and Gravity, a Docker Compose deployment, its real strengths, and its limits on a single-machine homelab.

Most ads and trackers appear because of DNS: a device asks for a domain address, and the answer comes back like any other domain. Pi-hole exploits exactly that. As a DNS sinkhole in the middle of the network, it sinks queries to blocked domains before the answer reaches the device. This article covers the mechanism, a Docker Compose deployment, its limits.

Why a DNS Sinkhole

Blocking ads at the DNS level has one big advantage: one deployment covers the whole network. Smartphones, PCs, and Smart TVs need no browser extension, and blocking happens before traffic enters the device. Pi-hole plays two roles: it blocks advertising and telemetry domains centrally for every device, and it maps local domains to internal service IPs so services are reachable by clean names. That makes Pi-hole a Tier 1 network dependency — if it dies, every device loses DNS resolution, not just ad-blocking.

Architecture: FTL, Gravity, and the Query Path

Modern Pi-hole (v6) is three parts:

  • pihole-FTL: the DNS resolver forked from dnsmasq, with the FTL engine (Faster Than Light) combining resolver, API, and query statistics in one process.
  • Web interface: browser dashboard for configuration, monitoring, and list management.
  • Core scripts: the pihole command (pihole -g, pihole status, pihole disable, …).

The query path is short. FTL receives a query from a client, checks the cache, then checks the domainlist and gravity tables in /etc/pihole/gravity.db (SQLite). If the domain is marked as blocked, FTL answers directly according to the blocking mode — default NULL returns 0.0.0.0 (or ::), so the client never opens a connection to the ad server. Clean domains go to the configured upstream resolver (FTLCONF_dns_upstreams), and the answer is cached.

Gravity is the blocklist collector. pihole -g downloads subscribed adlists, merges them, strips comments and duplicates, and stores one unique list in the gravity table — weekly, automatically, in the Docker image.

Deployment with Docker Compose

Standard Docker Compose setup:

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    network_mode: "host"
    environment:
      TZ: "Asia/Makassar"
      FTLCONF_webserver_api_password: "change_secure_password"
    volumes:
      - ./etc-pihole:/etc/pihole
      - ./etc-dnsmasq.d:/etc/dnsmasq.d
    restart: unless-stopped

Note: v6 images use FTLCONF_* variables — dashboard password is set via FTLCONF_webserver_api_password (WEBPASSWORD is gone). The ./etc-pihole volume stores gravity.db; dnsmasq files in /etc/dnsmasq.d are read by v6 only with FTLCONF_misc_etc_dnsmasq_d enabled. Host mode lets FTL see each client’s real IP for accurate reporting and blocking.

Operations and Security

  • The dashboard shows a query log, top domains, and top clients to see each device’s queries.
  • Privacy levels control query log verbosity.
  • Daily CLI: pihole status (health), pihole disable (pause blocking), pihole -g (manual Gravity refresh), docker logs -f pihole (container logs).
  • The dashboard is password-protected (placeholder change_secure_password); do not expose it to the internet.
  • On hosts with systemd-resolved, the 127.0.0.53:53 stub must be disabled to free port 53.

Backup & Recovery (Teleporter)

Pi-hole settings are easy to back up with the built-in Teleporter feature:

  • Navigate to Settings -> Teleporter -> Backup.
  • The downloaded .tar.gz archive contains all adlists, local DNS records, allow/deny lists, and settings.
  • On container failure, deploy a fresh container and import the backup via Teleporter.

What Works Well

  • Network-wide blocking without extensions: Smart TVs and IoT need no adblock.
  • Scheduled Gravity refresh: blocklist updates run weekly in the Docker image, no intervention needed.
  • Fewer outgoing queries: FTL keeps the fastest upstream for 1000 queries or 10 minutes, cutting outbound query volume.
  • Local DNS records: internal names map to homelab service IPs for clean access between services.
  • Built-in cache and stats: answers are cached; the dashboard gives visibility into each device’s DNS behavior.

Trade-offs and Limitations

  • Single point of failure: if Pi-hole goes down, DNS stops for the whole network. A secondary resolver or router fallback is needed.
  • DNS-level only: ads served from the same domain as content (e.g., YouTube ads) cannot be blocked without blocking the service itself.
  • Bypassable: browsers or devices using DNS-over-HTTPS (encrypted DNS) send queries straight to a DoH resolver and skip Pi-hole; some IoT devices ship hardcoded resolvers.
  • False positives: aggressive blocklists hit legitimate domains; manual allowlisting is needed from time to time.
  • Not full content control: DNS only — Pi-hole sees no HTTPS payload and is not a firewall.

Conclusion

On a single-machine homelab, Pi-hole is still worth running as the first ad-blocking layer and internal resolver. Its value shows most on devices that cannot take extensions and in managing internal domain names. But it is not a complete solution: single point of failure, first-party ads, and DoH paths remain. The discipline it demands lies not in the install but in DNS fallback and ongoing allowlist review.

References