Mastering Local Network Custom Domains: Pi-Hole, Cloudflare, and Docker Unleashed

February 9, 2025

Accessing local services via raw IP addresses like http://192.168.1.100 is clunky and insecure. By combining Pi-hole, Cloudflare, and Docker, you can assign memorable, secure custom domains (e.g., http://nas.yourdomain.lan) to internal services. This guide dives into four strategies for local DNS customization, complete with technical workflows, use cases, and trade-offs.

Case 1: Pi-Hole as a Local DNS Server

Technical Overview

Pi-hole acts as a network-wide DNS resolver, blocking ads and mapping custom domains to local IP addresses. Clients configured to use Pi-hole as their DNS server will resolve these domains internally.

Core Components:

  • Pi-hole Docker Container: Hosts DNS records for local domains.
  • Dnsmasq Configuration: Directs *.yourdomain.lan to internal IPs.

Example Setup

  1. Deploy Pi-hole via Docker Compose:

    # docker-compose.yml
    version: "3"
    services:
      pihole:
        image: pihole/pihole:latest
        ports:
          - "53:53/tcp"
          - "53:53/udp"
        environment:
          TZ: "America/New_York"
          WEBPASSWORD: "securepassword"
        volumes:
          - ./pihole-data:/etc/pihole
          - ./dnsmasq.d:/etc/dnsmasq.d
        restart: unless-stopped
  2. Add Local DNS Entries:
    Create a file ./dnsmasq.d/custom.conf with:

    address=/nas.yourdomain.lan/192.168.1.100
    address=/homeassistant.yourdomain.lan/192.168.1.101
  3. Configure Client Devices: Set Pi-hole’s IP as the DNS server on your router or individual devices.

Hypothesis: Queries for nas.yourdomain.lan will resolve to 192.168.1.100 internally.
Validation: Run nslookup nas.yourdomain.lan on a client device. The output should show the local IP.

Advantages

  • Blocks ads across the entire network.
  • Simple setup with Docker.
  • No dependency on external DNS providers.

Limitations

  • Manual management of DNS records.
  • Local-only resolution (no external access).
  • No built-in SSL certificate support.

Case 2: Cloudflare-Managed Domain with Split-Horizon DNS

Technical Overview

Use Cloudflare to manage a public domain while overriding DNS resolution locally. External users resolve to your public IP, while internal clients point to local IPs.

Core Components:

  • Cloudflare DNS: Hosts public DNS records.
  • Dynamic DNS (DDNS) Client: Updates Cloudflare with your public IP.
  • Pi-hole or Local Overrides: Redirects the domain internally.

Example Setup

  1. Deploy a Dynamic DNS Updater:
    Use ddclient in Docker to sync your public IP with Cloudflare:

    # docker-compose.yml
    services:
      ddclient:
        image: linuxserver/ddclient:latest
        environment:
          DDCLOUDFLARE_TOKEN: "your-api-token"
        volumes:
          - ./ddclient.conf:/config/ddclient.conf
        restart: unless-stopped

    Configure ddclient.conf:

    protocol=cloudflare  
    zone=yourdomain.com  
    subdomain=nas  
    password=your-api-token  
  2. Local DNS Override:
    Add nas.yourdomain.com to Pi-hole’s local DNS records or your OS hosts file:

    192.168.1.100 nas.yourdomain.com

Hypothesis: External requests to nas.yourdomain.com resolve to your public IP, while internal clients use the local IP.
Validation:

  • Externally: curl -I https://nas.yourdomain.com should return your public IP.
  • Internally: ping nas.yourdomain.com should resolve to 192.168.1.100.

Advantages

  • Uses a real domain with SSL support (via Cloudflare or Let’s Encrypt).
  • Dynamic IP updates for public access.
  • Centralized DNS management via Cloudflare.

Limitations

  • Requires split-DNS configuration (local vs. external).
  • Exposes services to the internet (requires security hardening).
  • Relies on Cloudflare API tokens.

Case 3: Hybrid Setup (Pi-hole + Cloudflare + Reverse Proxy)

Technical Overview

Combine Pi-hole for local DNS resolution with Cloudflare for external traffic, and a reverse proxy (e.g., Nginx) for SSL termination.

Core Components:

  • Pi-hole: Local DNS overrides.
  • Cloudflare: Public DNS and SSL proxy.
  • Reverse Proxy: Routes traffic and manages SSL certificates.

Example Setup

  1. Pi-hole Local DNS: Map nas.yourdomain.com to 192.168.1.100.
  2. Cloudflare DNS: Create an A record for nas.yourdomain.com pointing to your public IP.
  3. Reverse Proxy with Docker:
    Use nginx-proxy-manager to handle SSL:
    # docker-compose.yml
    services:
      nginx-proxy:
        image: jc21/nginx-proxy-manager:latest
        ports:
          - "80:80"
          - "443:443"
          - "81:81"
        volumes:
          - ./nginx-data:/data
        restart: unless-stopped
    Configure the proxy to forward nas.yourdomain.com to 192.168.1.100:80 and request a Let’s Encrypt SSL certificate.

Hypothesis: Internal clients access nas.yourdomain.com directly via LAN, while external clients connect securely through Cloudflare and the reverse proxy.
Validation:

  • Internally: https://nas.yourdomain.com should bypass Cloudflare and use the local IP.
  • Externally: The same URL should show a valid SSL certificate and route through Cloudflare.

Advantages

  • Unified domain for internal and external access.
  • SSL encryption for all traffic.
  • Combines ad-blocking with public DNS benefits.

Limitations

  • Complex setup with multiple components.
  • Requires port forwarding and public IP configuration.
  • Potential latency for external users.

Case 4: Custom DNS Server with Docker

Technical Overview

Deploy a lightweight DNS server (e.g., CoreDNS or dnsmasq) in Docker for granular control over local domains.

Example Setup

  1. Deploy CoreDNS with Docker:

    # docker-compose.yml
    services:
      coredns:
        image: coredns/coredns:latest
        command: -conf /Corefile
        ports:
          - "53:53/udp"
        volumes:
          - ./Corefile:/Corefile
        restart: unless-stopped
  2. Configure CoreDNS:
    Create Corefile to map local domains and forward external queries:

    yourdomain.lan {
      file /etc/coredns/db.yourdomain.lan
      log
    }
    
    . {
      forward . 8.8.8.8
      cache
    }
  3. Add Local DNS Records:
    Define db.yourdomain.lan with entries like:

    nas.yourdomain.lan. IN A 192.168.1.100

Hypothesis: Queries for *.yourdomain.lan resolve locally, while other domains use Google DNS.
Validation: dig nas.yourdomain.lan should return 192.168.1.100, while dig example.com uses 8.8.8.8.

Advantages

  • Full control over DNS zones and records.
  • Lightweight and highly customizable.
  • Ideal for testing or complex network setups.

Limitations

  • No built-in ad-blocking or DHCP.
  • Manual SSL configuration required.
  • Steeper learning curve for DNS configuration.

Choosing the Right Approach

Scenario-Based Recommendations

  1. Home Lab Simplicity:
    Use Pi-hole alone for ad-blocking and basic local DNS.
  2. Real Domain with External Access:
    Cloudflare Dynamic DNS + split-horizon DNS for hybrid access.
  3. Enterprise-Grade Security:
    Hybrid Pi-hole + Cloudflare with a reverse proxy for SSL.
  4. Advanced Customization:
    Custom DNS Server for full control over zones and records.

Key Considerations

  • SSL: Use Cloudflare or a reverse proxy (e.g., Traefik, Nginx) for HTTPS.
  • Security: Avoid exposing sensitive services publicly; use VPNs or Tailscale.
  • Maintenance: Pi-hole and Cloudflare require updates for DNS records and API tokens.