Interactive recovery tool for the AdGuard-Home-only DNS setup. Useful when AGH fails to start at boot and systemd-resolved is masked.
115 lines
3.3 KiB
Bash
Executable File
115 lines
3.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# dns-rescue.sh — emergency DNS recovery on a machine where AdGuard Home is the
|
|
# sole local resolver (systemd-resolved is masked). If AGH fails to start, this
|
|
# machine has no DNS until you intervene. Run this script from a TTY login.
|
|
#
|
|
# Author: Justin Moore
|
|
# Version: 0.1.0
|
|
|
|
set -u
|
|
|
|
RESOLV=/etc/resolv.conf
|
|
FALLBACK=1.1.1.1
|
|
|
|
require_root() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "Re-running with sudo..."
|
|
exec sudo -E "$0" "$@"
|
|
fi
|
|
}
|
|
|
|
show_status() {
|
|
echo "=== /etc/resolv.conf ==="
|
|
cat "$RESOLV" 2>/dev/null || echo "(missing!)"
|
|
echo
|
|
echo "=== AdGuard Home service ==="
|
|
systemctl is-active adguardhome 2>&1 | head -1
|
|
systemctl is-enabled adguardhome 2>&1 | head -1
|
|
echo
|
|
echo "=== Last 15 AGH log lines (this boot) ==="
|
|
journalctl -u adguardhome -b --no-pager -n 15 2>&1 | tail -15
|
|
echo
|
|
echo "=== Port 53 listeners ==="
|
|
ss -lntu 2>/dev/null | awk '/:53 /{print}' | head -5
|
|
echo
|
|
echo "=== Masked resolved units ==="
|
|
systemctl is-enabled systemd-resolved.service systemd-resolved-varlink.socket systemd-resolved-monitor.socket 2>&1 | paste -d' ' - - - -
|
|
}
|
|
|
|
add_fallback_dns() {
|
|
if grep -q "nameserver $FALLBACK" "$RESOLV" 2>/dev/null; then
|
|
echo "$FALLBACK is already in $RESOLV — nothing to do."
|
|
return
|
|
fi
|
|
echo "nameserver $FALLBACK" >> "$RESOLV"
|
|
echo "Added fallback nameserver $FALLBACK to $RESOLV."
|
|
echo "Test:"
|
|
getent hosts archlinux.org && echo " DNS now resolves."
|
|
}
|
|
|
|
restart_agh() {
|
|
systemctl restart adguardhome
|
|
sleep 1
|
|
systemctl is-active adguardhome
|
|
journalctl -u adguardhome -b --no-pager -n 10 | tail -10
|
|
}
|
|
|
|
unmask_resolved() {
|
|
cat <<MSG
|
|
This rolls back the local-DNS setup partway:
|
|
- unmasks systemd-resolved + its varlink/monitor sockets
|
|
- starts systemd-resolved (will bind 127.0.0.53:53)
|
|
- does NOT change /etc/resolv.conf, NetworkManager dropin, or nsswitch.conf
|
|
|
|
Use this if AGH itself is broken and you want resolved back as a stopgap.
|
|
You will still need to point /etc/resolv.conf at 127.0.0.53 (or let NM regenerate it)
|
|
to actually use resolved.
|
|
|
|
MSG
|
|
read -rp "Proceed? [y/N] " ans
|
|
[[ "$ans" =~ ^[Yy]$ ]] || { echo "Cancelled."; return; }
|
|
systemctl unmask systemd-resolved.service systemd-resolved-varlink.socket systemd-resolved-monitor.socket
|
|
systemctl start systemd-resolved
|
|
systemctl status systemd-resolved --no-pager -n 5
|
|
}
|
|
|
|
menu() {
|
|
cat <<MENU
|
|
|
|
DNS rescue menu:
|
|
1) Show DNS status (resolv.conf, AGH state, log, port 53)
|
|
2) Add $FALLBACK as a temporary fallback nameserver
|
|
3) Restart AdGuard Home and tail its log
|
|
4) Unmask + start systemd-resolved (heavier rollback)
|
|
5) Open editor on /etc/resolv.conf
|
|
q) Quit
|
|
MENU
|
|
read -rp "> " choice
|
|
case "$choice" in
|
|
1) show_status ;;
|
|
2) add_fallback_dns ;;
|
|
3) restart_agh ;;
|
|
4) unmask_resolved ;;
|
|
5) "${EDITOR:-vi}" "$RESOLV" ;;
|
|
q|Q) exit 0 ;;
|
|
*) echo "Unknown choice." ;;
|
|
esac
|
|
}
|
|
|
|
require_root "$@"
|
|
|
|
if [[ $# -gt 0 ]]; then
|
|
case "$1" in
|
|
status) show_status ;;
|
|
fallback) add_fallback_dns ;;
|
|
restart) restart_agh ;;
|
|
unmask) unmask_resolved ;;
|
|
*) echo "Usage: $0 [status|fallback|restart|unmask] (no arg = interactive menu)"; exit 2 ;;
|
|
esac
|
|
exit 0
|
|
fi
|
|
|
|
show_status
|
|
while true; do menu; done
|