132 lines
4.2 KiB
Bash
Executable file
132 lines
4.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Life Manager — /etc/hosts setup
|
|
# Ensures all 3 hosts can resolve each other by name for Node's getaddrinfo.
|
|
# Run on each host: sudo ./scripts/setup-hosts.sh
|
|
#
|
|
# Why: curl resolves .local via mDNS/Avahi, but Node.js uses getaddrinfo which
|
|
# doesn't query mDNS. Without /etc/hosts entries, Node fetch() fails with ENOTFOUND.
|
|
|
|
MARKER_START="# >>> Life Manager — managed by scripts/setup-hosts.sh"
|
|
MARKER_END="# <<< Life Manager"
|
|
|
|
HOSTS_FILE="/etc/hosts"
|
|
|
|
# ── Host registry ──────────────────────────────────────────────────────────────
|
|
# Format: hostname LAN-IP aliases...
|
|
declare -A HOST_IPS=(
|
|
[apricot]="10.0.0.116"
|
|
[black]="10.0.0.11"
|
|
[plum]="10.0.0.123"
|
|
)
|
|
|
|
# Aliases: each host gets lm.<host>.local + <host>.local
|
|
# The current host gets 127.0.0.1 for its own aliases (loopback)
|
|
generate_entries() {
|
|
local current_host
|
|
current_host="$(hostname -s)"
|
|
|
|
local entries=""
|
|
for host in apricot black plum; do
|
|
local ip="${HOST_IPS[$host]}"
|
|
local aliases="lm.${host}.local ${host}.local"
|
|
|
|
# Use loopback for self
|
|
if [[ "$host" == "$current_host" ]]; then
|
|
ip="127.0.0.1"
|
|
fi
|
|
|
|
entries+="${ip} ${aliases}\n"
|
|
done
|
|
|
|
echo -e "$entries"
|
|
}
|
|
|
|
# ── Install ────────────────────────────────────────────────────────────────────
|
|
install_hosts() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "Error: must run as root (sudo ./scripts/setup-hosts.sh)"
|
|
exit 1
|
|
fi
|
|
|
|
local new_block
|
|
new_block="$(generate_entries)"
|
|
|
|
# Remove existing managed block if present
|
|
if grep -q "$MARKER_START" "$HOSTS_FILE" 2>/dev/null; then
|
|
# Delete between markers (inclusive)
|
|
sed -i "/$MARKER_START/,/$MARKER_END/d" "$HOSTS_FILE"
|
|
echo "Removed previous Life Manager hosts block."
|
|
fi
|
|
|
|
# Append new block
|
|
{
|
|
echo ""
|
|
echo "$MARKER_START"
|
|
echo "# Auto-generated. Do not edit manually."
|
|
echo "#"
|
|
echo -e "$new_block"
|
|
echo "$MARKER_END"
|
|
} >> "$HOSTS_FILE"
|
|
|
|
echo "Installed Life Manager hosts on $(hostname -s):"
|
|
echo ""
|
|
echo -e "$new_block"
|
|
|
|
# Verify
|
|
echo "Verification:"
|
|
for host in apricot black plum; do
|
|
local resolved
|
|
resolved="$(getent hosts "lm.${host}.local" 2>/dev/null | awk '{print $1}')" || resolved="FAILED"
|
|
echo " lm.${host}.local → ${resolved}"
|
|
done
|
|
}
|
|
|
|
# ── Remote install ─────────────────────────────────────────────────────────────
|
|
install_remote() {
|
|
local target="$1"
|
|
local script_path
|
|
script_path="$(realpath "$0")"
|
|
local run_user="${SUDO_USER:-$USER}"
|
|
|
|
echo "=== Installing on ${target} ==="
|
|
# Copy script as the real user (SSH keys belong to them, not root)
|
|
su "$run_user" -c "scp -q '$script_path' '${target}:/tmp/setup-hosts.sh'"
|
|
su "$run_user" -c "ssh -t '${target}' 'sudo bash /tmp/setup-hosts.sh && rm /tmp/setup-hosts.sh'"
|
|
echo ""
|
|
}
|
|
|
|
# ── Main ───────────────────────────────────────────────────────────────────────
|
|
case "${1:-}" in
|
|
--all)
|
|
# Run locally first
|
|
echo "=== Installing on $(hostname -s) (local) ==="
|
|
install_hosts
|
|
echo ""
|
|
# Then remote hosts
|
|
current="$(hostname -s)"
|
|
for host in apricot black plum; do
|
|
[[ "$host" == "$current" ]] && continue
|
|
install_remote "$host" || echo "WARNING: Failed to install on $host"
|
|
done
|
|
echo "Done — all hosts configured."
|
|
;;
|
|
--remote)
|
|
shift
|
|
for target in "$@"; do
|
|
install_remote "$target"
|
|
done
|
|
;;
|
|
""|--local)
|
|
install_hosts
|
|
;;
|
|
*)
|
|
echo "Usage: sudo $0 [--all | --local | --remote <host> ...]"
|
|
echo ""
|
|
echo " --local Install on this host only (default)"
|
|
echo " --all Install on all 3 hosts (apricot, black, plum)"
|
|
echo " --remote Install on specific remote hosts"
|
|
exit 1
|
|
;;
|
|
esac
|