magicciv/scripts/lan/subscribe-black-dns.sh
Natalie c88e136469 fix(@projects): 🐛 update deployment and guide workflows
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-10 03:38:03 -07:00

134 lines
5 KiB
Bash
Executable file

#!/usr/bin/env bash
# Subscribe the current host to black.lan's LAN DNS.
#
# Why this exists:
# black.lan (10.0.0.11) runs dnsmasq with `address=/black.lan/10.0.0.11`
# — a wildcard rule that resolves every *.black.lan hostname to black's
# LAN IP. The DNS server is already reachable because DHCP hands 10.0.0.11
# out as one of the assigned DNS servers. The piece still missing on
# Linux hosts with mDNS disabled is a **resolver routing-domain policy**
# that tells systemd-resolved "forward *.black.lan queries to my DNS
# servers instead of treating them as mDNS / refusing them."
#
# macOS handles this natively via /etc/resolver/black.lan. Linux needs
# a drop-in file for systemd-resolved.
#
# What this does (idempotent — safe to re-run):
# * Linux + systemd-resolved: writes
# /etc/systemd/resolved.conf.d/black-local.conf
# with `Domains=~black.lan` + `DNS=10.0.0.11`, then reloads resolved.
# * macOS: writes
# /etc/resolver/black.lan
# with `nameserver 10.0.0.11` so the macOS resolver routes black.lan
# lookups to dnsmasq. No daemon reload needed.
# * Windows / BSD / other: prints a manual remediation hint.
#
# Verify after running:
# getent hosts mc.next.black.lan # Linux
# scutil --dns | grep -A2 black.lan # macOS
# curl -sk https://mc.next.black.lan/ -o /dev/null -w '%{http_code}\n'
#
# Usage:
# bash scripts/lan/subscribe-black-dns.sh # locally
# ssh <host> 'bash -s' < scripts/lan/subscribe-black-dns.sh # remote
#
# Re-run any time after black.lan's IP or DNS-server layout changes.
set -euo pipefail
readonly BLACK_IP='10.0.0.11'
readonly BLACK_DOMAIN='black.lan'
readonly RESOLVED_DROP_IN='/etc/systemd/resolved.conf.d/black-local.conf'
readonly MACOS_RESOLVER_FILE='/etc/resolver/black.lan'
log() { printf '\033[0;34m[subscribe-black-dns]\033[0m %s\n' "$*"; }
ok() { printf '\033[0;32m[subscribe-black-dns] ✓\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m[subscribe-black-dns] !\033[0m %s\n' "$*"; }
fail() { printf '\033[0;31m[subscribe-black-dns] ✗\033[0m %s\n' "$*" >&2; exit 1; }
probe_dns() {
# Return 0 if `mc.next.black.lan` resolves via the host's normal
# resolver path. macOS's /etc/resolver/ mechanism isn't visible to
# NSS-based tools (getent / host / nslookup in some configs), so on
# Darwin we have to use dscacheutil which IS aware of it.
case "$(uname -s)" in
Darwin)
dscacheutil -q host -a name mc.next.black.lan 2>/dev/null \
| grep -q "^ip_address: "
;;
*)
getent hosts mc.next.black.lan >/dev/null 2>&1 \
|| host mc.next.black.lan >/dev/null 2>&1
;;
esac
}
configure_linux_systemd_resolved() {
if ! command -v systemctl >/dev/null 2>&1; then
fail "systemctl not found — this script's Linux branch assumes systemd."
fi
if ! systemctl is-active --quiet systemd-resolved; then
warn "systemd-resolved is not active; skipping routing-domain drop-in."
warn "Configure your resolver manually: point *.${BLACK_DOMAIN} at ${BLACK_IP}."
return 0
fi
local payload
payload="$(cat <<EOF
# Managed by scripts/lan/subscribe-black-dns.sh — routing-domain override so
# *.${BLACK_DOMAIN} queries reach black's dnsmasq instead of being refused
# as mDNS. Regenerate by re-running the script; do not hand-edit.
[Resolve]
DNS=${BLACK_IP}
Domains=~${BLACK_DOMAIN}
EOF
)"
if [ -f "$RESOLVED_DROP_IN" ] && [ "$(cat "$RESOLVED_DROP_IN")" = "$payload" ]; then
ok "already subscribed (${RESOLVED_DROP_IN} up to date)"
else
log "writing ${RESOLVED_DROP_IN}"
sudo mkdir -p "$(dirname "$RESOLVED_DROP_IN")"
printf '%s\n' "$payload" | sudo tee "$RESOLVED_DROP_IN" >/dev/null
log "reloading systemd-resolved"
sudo systemctl reload systemd-resolved
ok "systemd-resolved reloaded"
fi
}
configure_macos_resolver() {
local payload="nameserver ${BLACK_IP}"
if [ -f "$MACOS_RESOLVER_FILE" ] && grep -qx "$payload" "$MACOS_RESOLVER_FILE"; then
ok "already subscribed (${MACOS_RESOLVER_FILE} up to date)"
return 0
fi
log "writing ${MACOS_RESOLVER_FILE}"
sudo mkdir -p "$(dirname "$MACOS_RESOLVER_FILE")"
printf '%s\n' "$payload" | sudo tee "$MACOS_RESOLVER_FILE" >/dev/null
ok "macOS resolver file installed (no daemon reload needed)"
}
verify() {
if probe_dns; then
ok "mc.next.black.lan resolves via this host's resolver"
else
warn "mc.next.black.lan still doesn't resolve — check that black (${BLACK_IP}) is reachable:"
warn " ping -c 1 ${BLACK_IP}"
warn " dig @${BLACK_IP} mc.${BLACK_DOMAIN}"
fi
}
main() {
log "host: $(hostname) · OS: $(uname -s)"
case "$(uname -s)" in
Linux) configure_linux_systemd_resolved ;;
Darwin) configure_macos_resolver ;;
*) fail "Unsupported OS: $(uname -s). Route *.${BLACK_DOMAIN} to ${BLACK_IP} via your resolver of choice." ;;
esac
verify
}
main "$@"