Files
computer-playbook/scripts/system/network/dns/setup/linux.sh
T
kevinveenbirkenbachandClaude Opus 5 96df7ea0eb feat(env): give every checkout its own stack domain
Every stack answered to *.infinito.test, and the host resolver pointed that
zone at 127.0.0.1, so a worktree's stack on its own bind IP could not be opened
in a browser while the primary stack existed.

INFINITO_DOMAIN is now derived per checkout: main.infinito.test for the
primary one, and for a linked worktree its branch, lowercased with everything
outside a-z0-9_- turned into "-", below INFINITO_DNS_DOMAIN
(feature/store-i18n -> feature-store-i18n.infinito.test). The branch is read
from the worktree's gitdir HEAD instead of running git, because git refuses the
mounted checkout inside the stack container. GitHub and act runs keep the
static default, custom.env still wins.

The handler overrides the caller's value on purpose: inside the stack
container that value is the previous .env, which make setup rewrote on every
deploy, so the old domain kept feeding itself back into the next compose up.

make network-dns-setup routes each stack's domain to the INFINITO_BIND_IP in
that checkout's .env, with a local= line so AAAA answers NODATA instead of the
primary stack's ::1. It skips domains outside the base zone, which a stale
.env still carries, and fails when two checkouts claim one domain.
worktree-up prints the domain and the follow-up command.

Existing checkouts switch after make dotenv-force and a redeploy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 17:44:38 +02:00

111 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=scripts/system/network/dns/common.sh
source "${SCRIPT_DIR}/../common.sh"
echo ">>> Setting up local DNS for *.${DNS_DOMAIN} -> 127.0.0.1"
configure_via_hosts_file() {
echo ">>> Non-systemd environment detected -> configuring /etc/hosts fallback"
echo ">>> Hosts file: ${DNS_HOSTS_FILE}"
echo ">>> Host entries:"
dns_read_hosts_fallback_entries | sed 's/^/ /'
dns_write_hosts_fallback
dns_test_resolution
echo
echo ">>> Local DNS fallback configured for:"
dns_read_hosts_fallback_entries | sed 's/^/ /'
}
install_dnsmasq_if_missing() {
if command -v dnsmasq >/dev/null 2>&1; then
return 0
fi
echo ">>> dnsmasq not found -> installing"
if command -v pacman >/dev/null 2>&1; then
sudo pacman -S --noconfirm --needed dnsmasq
elif command -v apt-get >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y dnsmasq
elif command -v dnf >/dev/null 2>&1; then
sudo dnf install -y dnsmasq
else
echo "ERROR: Unsupported distro/package manager. Install dnsmasq manually."
exit 1
fi
}
if ! dns_systemd_is_operational; then
echo ">>> Skipping local DNS setup via systemd services: systemd service management is unavailable in this environment."
configure_via_hosts_file
exit 0
fi
configure_via_networkmanager_dnsmasq() {
echo ">>> Detected NetworkManager -> configuring NM dnsmasq plugin (recommended)"
install_dnsmasq_if_missing
if systemctl is-enabled --quiet dnsmasq 2>/dev/null || systemctl is-active --quiet dnsmasq 2>/dev/null; then
echo ">>> Disabling system dnsmasq to avoid conflicts with NetworkManager dnsmasq"
sudo systemctl disable --now dnsmasq || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error
fi
echo ">>> Writing NetworkManager dnsmasq config: ${DNS_NM_CONF}"
sudo mkdir -p "$(dirname "${DNS_NM_CONF}")"
cat <<EOF | sudo tee "${DNS_NM_CONF}" >/dev/null
[main]
dns=dnsmasq
EOF
echo ">>> Writing dnsmasq snippet for NetworkManager: ${DNS_NM_DNSMASQ_CONF}"
sudo mkdir -p "${DNS_NM_DNSMASQ_DIR}"
dns_dnsmasq_config | sudo tee "${DNS_NM_DNSMASQ_CONF}" >/dev/null
echo ">>> Restarting NetworkManager"
sudo systemctl restart NetworkManager
echo ">>> Resolver status"
cat /etc/resolv.conf || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error
}
configure_via_system_dnsmasq() {
echo ">>> NetworkManager not active -> configuring system dnsmasq (fallback)"
install_dnsmasq_if_missing
echo ">>> Writing system dnsmasq config: ${DNS_SYS_DNSMASQ_CONF}"
sudo mkdir -p /etc/dnsmasq.d
dns_dnsmasq_config | sudo tee "${DNS_SYS_DNSMASQ_CONF}" >/dev/null
echo ">>> Enabling and restarting dnsmasq service"
sudo systemctl enable dnsmasq --now
sudo systemctl restart dnsmasq
if command -v resolvectl >/dev/null 2>&1 && systemctl is-active --quiet systemd-resolved 2>/dev/null; then
echo ">>> Configuring systemd-resolved routing for ${DNS_DOMAIN}"
sudo resolvectl dns lo 127.0.0.1 || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error
sudo resolvectl domain lo "~${DNS_DOMAIN}" || true # nocheck: shell-or-true -- grandfathered: worked in practice; TODO: sharpen to catch only the exact tolerated error
else
echo ">>> systemd-resolved not active -> skipping resolvectl integration"
echo ">>> NOTE: Ensure your system resolver uses 127.0.0.1 to query dnsmasq."
fi
}
if systemctl is-active --quiet NetworkManager 2>/dev/null; then
configure_via_networkmanager_dnsmasq
else
configure_via_system_dnsmasq
fi
dns_test_resolution
echo
echo ">>> Local DNS configured for:"
echo " *.${DNS_DOMAIN} -> 127.0.0.1"
dns_stacks | awk '{ printf " *.%s -> %s\n", $1, $2 }'