diff --git a/scripts/setup/machine-setup/lib/base.sh b/scripts/setup/machine-setup/lib/base.sh index b74fddb3..d7b08e0e 100644 --- a/scripts/setup/machine-setup/lib/base.sh +++ b/scripts/setup/machine-setup/lib/base.sh @@ -230,43 +230,18 @@ default_iface() { ip route get 8.8.8.8 2>/dev/null | awk '{for (i = 1; i <= NF; i++) if ($i == "dev") {print $(i + 1); exit}}' } -# A default for the question below — a suggestion the user confirms, never a -# decision taken on their behalf. -# -# The signal that separates homelab from vps is whether this machine's own -# address is in RFC1918 space. That is a better test than asking whether it is -# virtualised, because a homelab is very often a VM on Proxmox and would be -# misread as rented; and it is the same fact that decides most of what the role -# is consulted for — whether the address is yours to pin, and whether the box is -# exposed to the open internet. -guess_machine_role() { - # Nothing here is a server. It is the machine you are sitting at. - if [[ "$OS" == "macos" ]]; then - echo dev - return - fi - - # A graphical session means someone sits at this one too. - if [[ -n "${DISPLAY:-}" ]] || systemctl list-unit-files 2>/dev/null | grep -qE '^(gdm3?|sddm|lightdm)\.service'; then - echo dev - return - fi - - local ip - ip="$(ip -4 addr show "$(default_iface)" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1)" - case "$ip" in - 10.* | 192.168.* | 172.1[6-9].* | 172.2[0-9].* | 172.3[01].*) echo homelab ;; - "") echo homelab ;; # no address to judge by: assume the safer of the two - *) echo vps ;; - esac -} - # Ask what this machine is, unless the environment already said. # # Asked in pre-flight rather than at the point of use so that the run knows its # own shape before it starts: the steps that care are spread from swap through to # the firewall, and being asked "is this a VPS?" for the fourth time halfway down # a provisioning run is how people start answering without reading. +# +# NO DEFAULT, deliberately, and it is the only question in the script like that. +# A guessed default is right often enough to be trusted and wrong in exactly the +# case that costs the most: pinning a static IP on a rented box, or leaving the +# firewall open on one. Every branch downstream is about what this machine is +# exposed to, so it is worth one deliberate keystroke rather than an Enter. ask_machine_role() { if [[ -n "$MACHINE_ROLE" ]]; then case "$MACHINE_ROLE" in @@ -275,30 +250,28 @@ ask_machine_role() { esac fi - local guess choice - guess="$(guess_machine_role)" - echo "" - info "What is this machine?" + info "What is this machine? Several later steps depend on the answer." echo " [1] homelab — yours, on a network you control" echo " [2] vps — rented, public IP, provider's DHCP and console" echo " [3] dev — a laptop or desktop you sit at" echo "" - case "$guess" in - homelab) choice=1 ;; - vps) choice=2 ;; - dev) choice=3 ;; - esac - - prompt_value MACHINE_ROLE_CHOICE "Pick a number" "$choice" - - case "$MACHINE_ROLE_CHOICE" in - 1 | homelab) MACHINE_ROLE=homelab ;; - 2 | vps) MACHINE_ROLE=vps ;; - 3 | dev) MACHINE_ROLE=dev ;; - *) fail "Not one of the options: '$MACHINE_ROLE_CHOICE'" ;; - esac + local choice + while [[ -z "$MACHINE_ROLE" ]]; do + # A failed read means EOF, not a wrong answer — without this the loop would + # spin forever when stdin is closed, which is how an unattended run hangs. + if ! read -rp " Which one? (1/2/3): " choice; then + fail "No answer, and this question has no default. Set MACHINE_ROLE=homelab|vps|dev to answer it ahead of time." + fi + case "$choice" in + 1 | homelab) MACHINE_ROLE=homelab ;; + 2 | vps) MACHINE_ROLE=vps ;; + 3 | dev) MACHINE_ROLE=dev ;; + "") warn "There is no default here — pick 1, 2 or 3." ;; + *) warn "Not one of the options: '$choice'" ;; + esac + done } # Convenience for the steps that branch on it.