You've already forked directdnsonly
feat: add NSD backend and Topology C (multi-instance with peer sync) 🏗️
- New NSDBackend: zone files + nsd-control reload, zone registration via nsd.conf.d include file; mirrors BIND backend interface exactly - BackendRegistry now supports type "nsd"; config defaults for nsd.zones_dir and nsd.nsd_conf - Dockerfile installs both NSD and BIND9 — entrypoint detects configured backend type(s) and starts only the required daemon; CoreDNS MySQL deployments start neither - docker/nsd.conf: minimal NSD base config with remote-control and zones.conf include - entrypoint.sh: reads config file + env vars to determine which daemon to start; runs nsd-control-setup on first boot - 20 new NSD backend tests (117 total, all passing) - README: Topology C (multi-instance + peer sync) documented as most robust HA option; NSD config reference; updated topology comparison table; NSD env-var-only compose examples; version 2.5.0
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
set -e
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Detect whether any bind backend is configured and enabled.
|
||||
# Detect which DNS backend type(s) are configured and enabled.
|
||||
# Uses the same config search order as the application itself.
|
||||
# ---------------------------------------------------------------------------
|
||||
BIND_ENABLED=$(python3 - <<'EOF'
|
||||
detect_backend_types() {
|
||||
python3 - <<'EOF'
|
||||
import yaml, sys, os
|
||||
|
||||
config_paths = [
|
||||
@@ -17,6 +18,10 @@ config_paths = [
|
||||
"/app/config/app.yaml",
|
||||
]
|
||||
|
||||
# Also honour env-var-only deployments (no config file)
|
||||
bind_env = os.environ.get("DADNS_DNS_BACKENDS_BIND_ENABLED", "").lower() == "true"
|
||||
nsd_env = os.environ.get("DADNS_DNS_BACKENDS_NSD_ENABLED", "").lower() == "true"
|
||||
|
||||
config = {}
|
||||
for path in config_paths:
|
||||
if os.path.exists(path):
|
||||
@@ -25,20 +30,62 @@ for path in config_paths:
|
||||
break
|
||||
|
||||
backends = config.get("dns", {}).get("backends", {})
|
||||
has_bind = bind_env
|
||||
has_nsd = nsd_env
|
||||
for cfg in backends.values():
|
||||
if isinstance(cfg, dict) and cfg.get("type") == "bind" and cfg.get("enabled", False):
|
||||
print("true")
|
||||
sys.exit(0)
|
||||
print("false")
|
||||
EOF
|
||||
)
|
||||
if not isinstance(cfg, dict) or not cfg.get("enabled", False):
|
||||
continue
|
||||
btype = cfg.get("type", "")
|
||||
if btype == "bind":
|
||||
has_bind = True
|
||||
elif btype == "nsd":
|
||||
has_nsd = True
|
||||
|
||||
if [ "$BIND_ENABLED" = "true" ]; then
|
||||
echo "[entrypoint] BIND backend enabled — starting named"
|
||||
/usr/sbin/named -u bind -f &
|
||||
else
|
||||
echo "[entrypoint] No BIND backend configured — skipping named"
|
||||
types = []
|
||||
if has_bind:
|
||||
types.append("bind")
|
||||
if has_nsd:
|
||||
types.append("nsd")
|
||||
print(" ".join(types) if types else "none")
|
||||
EOF
|
||||
}
|
||||
|
||||
BACKEND_TYPES=$(detect_backend_types)
|
||||
echo "[entrypoint] Detected DNS backend type(s): ${BACKEND_TYPES:-none}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Start BIND if a bind backend is configured
|
||||
# ---------------------------------------------------------------------------
|
||||
if echo "$BACKEND_TYPES" | grep -qw "bind"; then
|
||||
if command -v named >/dev/null 2>&1; then
|
||||
echo "[entrypoint] Starting BIND (named)"
|
||||
/usr/sbin/named -u bind -f &
|
||||
else
|
||||
echo "[entrypoint] WARNING: bind backend configured but 'named' not found — skipping"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start the application
|
||||
# ---------------------------------------------------------------------------
|
||||
# Start NSD if an nsd backend is configured
|
||||
# ---------------------------------------------------------------------------
|
||||
if echo "$BACKEND_TYPES" | grep -qw "nsd"; then
|
||||
if command -v nsd >/dev/null 2>&1; then
|
||||
echo "[entrypoint] Starting NSD"
|
||||
# Ensure nsd-control keys exist (generated on first run)
|
||||
if [ ! -f /etc/nsd/nsd_server.key ]; then
|
||||
nsd-control-setup 2>/dev/null || true
|
||||
fi
|
||||
/usr/sbin/nsd -d -c /etc/nsd/nsd.conf &
|
||||
else
|
||||
echo "[entrypoint] WARNING: nsd backend configured but 'nsd' not found — skipping"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$BACKEND_TYPES" = "none" ] || [ -z "$BACKEND_TYPES" ]; then
|
||||
echo "[entrypoint] No local DNS daemon required (CoreDNS MySQL or similar)"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Start the directdnsonly application
|
||||
# ---------------------------------------------------------------------------
|
||||
exec python -m directdnsonly
|
||||
|
||||
20
docker/nsd.conf
Normal file
20
docker/nsd.conf
Normal file
@@ -0,0 +1,20 @@
|
||||
# NSD base configuration for directdnsonly containers.
|
||||
# Zone stanzas are written to /etc/nsd/nsd.conf.d/zones.conf by the NSD
|
||||
# backend and auto-included via the glob below.
|
||||
|
||||
server:
|
||||
server-count: 1
|
||||
ip-address: 0.0.0.0
|
||||
port: 53
|
||||
username: nsd
|
||||
zonesdir: /etc/nsd/zones
|
||||
verbosity: 1
|
||||
# Log to stderr so Docker captures it
|
||||
logfile: ""
|
||||
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: 127.0.0.1
|
||||
control-port: 8952
|
||||
|
||||
include: /etc/nsd/nsd.conf.d/*.conf
|
||||
Reference in New Issue
Block a user