Files
command-center/agent/managed-skills/dankclaw-pihole-lan-dns-record/SKILL.md
T

4.8 KiB

name, description
name description
dankclaw-pihole-lan-dns-record Add/repair a LAN DNS record for a new *.franksdank.cloud service on Dankclaw's Pi-hole v6 (hosts/custom.list + repo addn-hosts, plus the public Porkbun A record side) — and triage "LAN names stopped resolving" including the FTL boot-time record-load failure.

Dankclaw Pi-hole LAN DNS record

What this fixes

A new *.franksdank.cloud service resolves publicly (via Porkbun → franksdank.cloud A record → Caddy on Dankclaw 192.168.0.143) but does not resolve on the LAN. Pi-hole is the LAN DNS server (dankclaw_default bridge, published port 53) and serves local records only from files it imports.

Live truth

  • The repo owns the records. dankclaw/pihole/addn-hosts (hosts-style lines: 192.168.0.143 <name>) is copied by deploy-remote.sh to /home/dank/Containers/pihole/addn-hosts and bind-mounted read-only into the container at /etc/pihole/hosts/addn-hosts (Volume=/home/dank/Containers/pihole/addn-hosts:/etc/pihole/hosts/addn-hosts:ro in dankclaw/pihole/quadlet/pihole.container). Add the name there, in the repo, then deploy — that is the durable path. tests/pihole.bats validates every line (IPv4, LAN range, name suffix, Caddyfile cross-check).
  • /home/dank/Containers/pihole/etc-pihole/hosts/custom.list also exists on the host (older mechanism, mode 640 owned by the container uid, root reads it with sudo). It is not the repo's owner file — do not hand-edit it as the fix.
  • pihole.toml carries a dns.hosts = [ "192.168.0.143 …", … ] array too (FTL's own in-config records). Both sources exist; if LAN names fail, neither is being applied.
  • Pi-hole runs as a rootless quadlet named pihole — query it with podman exec pihole …, never sudo podman (per-user storage law).
  • pihole.franksdank.cloud resolves through Pi-hole itself (loop/edge), so a vhost record pointing at 192.168.0.143 is correct for every Caddy-fronted service.

Procedure (repo-first)

  1. Append the line to dankclaw/pihole/addn-hosts:
    192.168.0.143 <name>.franksdank.cloud
    
    One record per vhost; keep it in sync with the Caddyfile (the bats seam cross-checks the two).
  2. ./tests/run.sh (the pihole seam validates the file), commit, push.
  3. Deploy so the copy step runs: ./scripts/deploy.sh dankclaw --service pihole.
  4. Verify from the box: getent hosts <name>.franksdank.cloud → 192.168.0.143.
  5. Public edge record (optional; skip when every subscriber is LAN-only): Porkbun POST /api/v3/json with apikey/secretapikey/command=add/type=A/hostname=<name>/data=76.49.118.136 (see dankclaw-porkbun-edge).

Client-side proof (avoid the resolver trap):

sudo resolvectl flush-caches        # systemd-resolved otherwise keeps the negative cache
curl -sv --max-time 5 https://<name>.franksdank.cloud 2>&1 | grep 'Connected to'

Expected: Connected to <name>.franksdank.cloud (192.168.0.143) — LAN route, not the public IP.

Triage: every LAN name broke at once (2026-10-19 law)

Signature: all *.franksdank.cloud return NXDOMAIN / Playwright ERR_NAME_NOT_RESOLVED while external names still resolve. The external-OK/local-fail split is the tell: FTL is answering external names from cache and holds no local records at all after a container/host restart — the mounts and files are intact and readable inside the container (ls -l /etc/pihole/hosts/, grep -c . …/addn-hosts), dns.hosts in pihole.toml is complete. The mechanism is unestablished; do not go hunting for a lost file.

ssh dankclaw 'getent hosts grafana.franksdank.cloud'        # empty => FTL, not the client
ssh dankclaw 'podman exec pihole pihole restartdns reload'   # fixes it in seconds

Distinguish before acting: a single client failing while others work is FTL rate-limiting that client — podman exec pihole grep Rate-limiting /var/log/pihole/FTL.log; a 10.0.2.x client address is a pasta container's DNS forwarder (SNAT), not a machine. Full causal page: serverAppConfigs-docs/Infrastructure/Pi-hole.md (Records pitfall + Failure modes table).

Gotchas

  • Do NOT insert local records into SQLite. v6's gravity.db domain table has NO type=2 custom-DNS rows in this build.
  • pihole restartdns reload re-imports the hosts files and dns.hosts; that is the remedy for the boot-load failure above. Plain pihole restartdns also restarts the resolver — brief LAN-wide DNS blip.
  • dig @<ip> <name> from the workstation bypasses systemd-resolved — use it to check FTL's answer directly (+short @192.168.0.143).

Cross-reference

  • Fleet DNS flow: dankclaw/Caddyfile (Caddy binds :443 on the host, serves *.franksdank.cloud vhosts)
  • Pi-hole service page: serverAppConfigs-docs/Infrastructure/Pi-hole.md, flow page Infrastructure/LAN-DNS.md
  • Public edge: managed skill dankclaw-porkbun-edge