Files
esh-pfi-infrastructure/stacks/adguard-ana/compose.yaml
T
vh b8003c73ae feat(dns): fleet .internal naming — git-sourced, agent-managed, three resolvers
Names for fleet hosts so addresses stop needing to be memorised. Built because
IPv6 makes that hopeless — and, more to the point, because v6 addresses are
derived rather than assigned, so they cannot reliably be written down once and
trusted either.

  dns/internal.yaml     source of truth: 38 hosts + 4 service aliases
  scripts/dns-sync.py   reconciles AdGuard resolvers against it
  stacks/adguard-ana/   the colo's resolver, which did not exist

Naming is <host>.<site>.internal with sites ana/esh/nh3 (operator's call).
.internal is ICANN-reserved for this; .local is reserved for mDNS, which is
why searxng.pfi.local was a collision that merely happened to work.

Same posture as deploy-stack.sh: file is intent, resolvers are derived state,
you see a diff before anything changes. Every name is published to every
resolver, so the site label says where a host IS, not who knows about it.

Two properties that matter:
- Authority is scoped to the ZONE, not the resolver. ESH carries hand-made
  esteban.net rewrites predating this; they are read, ignored and preserved.
  Resolver-wide authority would have silently deleted them.
- Within .internal it IS authoritative, so UI-added names get removed. That is
  the point — one place to look.

Colo gap closed: ana-docker had no resolver at all (hosts went straight to
1.1.1.1). Its AdGuard runs API on 8053 because 8080/3000 were taken, so the
port is carried per-site in the yaml rather than assumed by the script. It
ships with no blocklists — a false positive on a server network breaks
service-to-service calls for no upside.

Auth is a dedicated infra-ops AdGuard user, not the operator's account,
password vaulted at nh3-dev/adguard-infra-ops-password. Pre-change configs
backed up on each resolver. Both resolvers stayed answering across the restart.

searxng.pfi.local -> searxng.ana.internal, with the old Host() kept alongside
so nothing breaks mid-migration. matrix.pfi.local deliberately NOT migrated: a
Matrix server_name is baked into every user id, room id and signing key, so
renaming it rebuilds the homeserver's identity rather than changing a DNS name.

The v6 column is empty and correct — no fleet host has a global v6 address
yet. The file documents why addresses must be pinned statically before they go
in, since a record that silently stops matching is worse than no record.
2026-08-19 01:10:55 -07:00

57 lines
2.1 KiB
YAML

# adguard-ana — the Anaheim colo's resolver.
#
# Stood up 2026-08-19 to close the gap found while designing the .internal
# naming scheme: ESH and NH3 each had an AdGuard, but colo hosts were
# resolving straight against 1.1.1.1, so the colo had no way to answer for
# internal names at all.
#
# ⚠️ PORTS DIFFER FROM THE OTHER TWO SITES. ana-docker is a busy host: :8080
# and :3000 are already taken (langfuse and friends), so AdGuard's web UI and
# API live on :8053 here, not :8080. Anything that talks to this API — notably
# scripts/dns-sync.py — reads the port from dns/internal.yaml rather than
# assuming the ESH/NH3 value.
#
# ⚠️ THIS IS NOT YET THE COLO'S RESOLVER-OF-RECORD. Standing the service up and
# repointing a whole site's DNS are two different changes with two different
# blast radii. Colo hosts still use 1.1.1.1; the cutover is a separate,
# operator-approved step. Until then this answers only what asks it directly.
#
# ESH and NH3 run their own, older, unmanaged compose files. They were left
# alone deliberately — adopting three live resolvers into this repo while also
# introducing a new naming system is two risky changes at once. Worth doing
# later, as its own piece of work.
name: adguard-ana
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: ${AG_CONTAINER:-adguardhome}
restart: unless-stopped
ports:
- "${AG_DNS_PORT:-53}:53/tcp"
- "${AG_DNS_PORT:-53}:53/udp"
# Web UI + REST API. 8053, not 8080 — see the note above.
- "${AG_WEB_PORT:-8053}:80/tcp"
volumes:
- adguard_work:/opt/adguardhome/work
- adguard_conf:/opt/adguardhome/conf
networks:
- tnet
labels:
- homepage.group=Service Networking
- homepage.name=AdGuard (ANA)
- homepage.icon=mdi-dns
- homepage.description=DNS resolver + .internal zone (colo)
- homepage.href=http://10.250.50.70:${AG_WEB_PORT:-8053}
- homepage.siteMonitor=http://10.250.50.70:${AG_WEB_PORT:-8053}
volumes:
adguard_work: {}
adguard_conf: {}
networks:
tnet:
name: traefik-net
external: true