4.6 KiB
Run fancy-dns outside Kubernetes
This Compose deployment follows deploy/k8s/00-config.yaml and
deploy/k8s/10-deployment.yaml. It builds the image from this checkout instead
of pulling registry.k6n.net/fancydns, avoiding a bootstrap dependency on the
cluster registry DNS.
Prepare and start
From the repository root:
mkdir -p deploy/compose/{data,zones,rpz,tls}
cp deploy/compose/.env.example deploy/compose/.env
Edit deploy/compose/.env (keep it private) and set a random API key as
FANCYDNS_API_KEY=<long-random-value>. Install the certificate and private key
for dns.k6n.net as deploy/compose/tls/fullchain.pem and
deploy/compose/tls/privkey.pem. Add the same zone files used by the cluster to
deploy/compose/zones/. Keep private key and .env out of source control.
The container runs as UID/GID 65532 with a read-only root filesystem, so make the persistent directory writable first, for example:
sudo chown -R 65532:65532 deploy/compose/data
docker compose --env-file deploy/compose/.env -f deploy/compose/compose.yaml build
docker compose --env-file deploy/compose/.env -f deploy/compose/compose.yaml run --rm fancy-dns -config /etc/fancy-dns/config.yaml -check
docker compose --env-file deploy/compose/.env -f deploy/compose/compose.yaml up -d
The DNS ports publish on all host interfaces: UDP/TCP 53, TCP 853, and TCP 443.
The admin API is published only on 127.0.0.1:8080; the embedded UI is disabled
by default for backup-resolver use. To enable it, set api.ui: true in
config.yaml and restart. Use an authenticated TLS reverse proxy for remote
access. Check that nothing already owns host port
53 before starting. The sample mounts TLS files and enables DoT and DoH, so the
files must exist before startup.
How configuration is shared
The repository is the source of truth, but there is currently no automatic
config distribution between Kubernetes and the bare-metal Compose host.
Kubernetes GitOps reconciles deploy/k8s from main (see gitops/README.md);
the bare-metal host must get the updated checkout and have Compose restarted.
Kubernetes gets its config from the ConfigMap in deploy/k8s/00-config.yaml;
Compose reads the checked-in deploy/compose/config.yaml and files under
deploy/compose/. Treat these as two deployment configs: commit reviewed
changes to both when a shared resolver setting changes. The Compose config now
includes the same local. forward zone to 10.10.0.1:53 as Kubernetes.
The shared inputs to keep aligned are upstreams/forward zones, resolver policy,
cache sizing/TTL, blocklist sources and actions, ACLs, local zone files, RPZ
rules, and the DoT/DoH certificate for the same public DNS name. Deployment
specific settings intentionally differ: listener container ports/storage paths
must match each deployment, and Compose uses API-key auth with the UI disabled
while Kubernetes uses OIDC. On bare metal the YAML, zone and RPZ files are
bind-mounted; Kubernetes stores config, zones and RPZ in ConfigMaps and TLS in
a Secret. Secrets should be provisioned separately on each system, not copied
into Git. The Compose API key is in its private .env file.
Do not share the data/ directory or copy its bbolt files while either server
is running. Cache snapshots and query logs are instance-local state. The
managed zones written by the console also live under this directory; edits
made on one instance do not appear on the other automatically. Make operator
zone changes in the source of truth and deploy them to both, or designate one
instance as the writer. Valkey clustering syncs cluster events/list leadership,
not these files or bbolt state.
The private forwarding target must remain reachable from both the Kubernetes pods and the bare-metal host. Verify that the bare-metal resolver has outbound access to its configured public upstreams before making it the cluster's registry resolver.
For registry recovery, configure the Kubernetes nodes' OS resolver and the
container runtime's registry DNS path to use this host's static IP directly
as a DNS server (with another independent resolver as fallback). Do not rely on
a hostname for the backup resolver, and do not make pulling this Compose image
depend on registry.k6n.net: this Compose file builds the image locally from
the repository checkout. A working route from the cluster nodes to the
bare-metal host on UDP/TCP 53 is required; allow it through the host firewall.
To update the local build after code changes, rebuild and recreate the container. The running server can hot-reload its YAML on SIGHUP, but Compose does not automatically send SIGHUP when bind-mounted files change.