diff --git a/scripts/setup/machine-setup/lib/base.sh b/scripts/setup/machine-setup/lib/base.sh index 8fce9a5e..a02b1ccd 100644 --- a/scripts/setup/machine-setup/lib/base.sh +++ b/scripts/setup/machine-setup/lib/base.sh @@ -212,11 +212,17 @@ confirm() { # Second argument flips the default. Most questions here are "do the thing you # already asked for" and Enter should mean yes; a few are genuine extras, where # defaulting to yes would have people agreeing to them by reflex. - local default="${2:-y}" answer prompt + local default="${2:-y}" + # Third is the name of a function that explains the question. Where one is + # given, `?` becomes an answer — so the explanation is available to whoever + # wants it without being in the way of whoever does not. + local help_fn="${3:-}" + local answer prompt [[ "${ASSUME_YES:-}" == "1" ]] && { [[ "$default" == "y" ]] && return 0 || return 1; } if [[ "$default" == "y" ]]; then prompt="[Y/n]"; else prompt="[y/N]"; fi + [[ -n "$help_fn" ]] && prompt="${prompt%]}/?]" while true; do # EOF is not a yes. Without this an unattended run without ASSUME_YES would @@ -229,7 +235,16 @@ confirm() { case "$answer" in y | Y | yes | Yes) return 0 ;; n | N | no | No) return 1 ;; - *) warn "Answer y or n." ;; + "?") + if [[ -n "$help_fn" ]]; then + echo "" + "$help_fn" + echo "" + else + warn "Answer y or n." + fi + ;; + *) warn "Answer y or n${help_fn:+, or ? for what this is}." ;; esac done } diff --git a/scripts/setup/machine-setup/lib/tailscale.sh b/scripts/setup/machine-setup/lib/tailscale.sh index 91ddcec5..89d8c2a8 100644 --- a/scripts/setup/machine-setup/lib/tailscale.sh +++ b/scripts/setup/machine-setup/lib/tailscale.sh @@ -33,6 +33,28 @@ MACHINE_SETUP_TAILSCALE_LOADED=1 TS_EXIT_SYSCTL=/etc/sysctl.d/99-tailscale-exit.conf TS_DISPATCHER=/etc/networkd-dispatcher/routable.d/50-tailscale-exit +# Printed only when asked for. The section leads with the question rather than +# with ten lines of explanation: somebody who runs Tailscale already does not need +# to be told what it is, and somebody who does not can type ?. +tailscale_help() { + echo " Tailscale is a private network between your own machines, over" + echo " WireGuard. Every device you enrol gets a stable 100.x address and" + echo " can reach every other, wherever they are — through NAT, across" + echo " providers, without either end having a public address." + echo "" + echo " Nothing is published to the open internet to make that work: no" + echo " port forwarding, no exposed ports, no holes in the firewall." + echo "" + echo " For Officer it is not a convenience. The platform is built assuming" + echo " the tailnet IS the perimeter — ALLOW_ANY_ORIGIN defaults on, and" + echo " that is only defensible because the machine is not reachable from" + echo " outside in the first place. A valid token plus the tailnet is the" + echo " lock; without the tailnet it is one layer short of its design." + echo "" + echo " It is installed at this point in the run, before anything that can" + echo " lock you out of the machine, so there is always a second way in." +} + tailscale_is_installed() { command -v tailscale &>/dev/null; } # NeedsLogin, Running, Stopped, NoState… Read before acting, because the original's diff --git a/scripts/setup/machine-setup/machine-setup.sh b/scripts/setup/machine-setup/machine-setup.sh index a8995319..649bb11d 100755 --- a/scripts/setup/machine-setup/machine-setup.sh +++ b/scripts/setup/machine-setup/machine-setup.sh @@ -406,21 +406,12 @@ fi step "Tailscale" if ! skip; then echo "" - info "Tailscale — a private network between your machines, over WireGuard" - echo " Every device you enrol gets a stable 100.x address and can reach" - echo " every other, wherever they are. Nothing is published to the open" - echo " internet: no port forwarding, no exposed ports, no firewall holes." - echo "" - echo " For Officer this is not a convenience. The platform is built assuming" - echo " the tailnet IS the perimeter — ALLOW_ANY_ORIGIN defaults on, and that" - echo " is only defensible because the machine is not reachable from outside" - echo " in the first place. Installed here, before anything that can lock you" - echo " out, so there is always a second way in." + info "Tailscale — a private network between your machines" if ! tailscale_is_installed; then + echo " not installed on this machine" echo "" - echo " not installed" - if confirm "Install Tailscale?"; then + if confirm "Install Tailscale?" y tailscale_help; then tailscale_install tailscale_is_installed && ok "$(tailscale version 2>/dev/null | head -1) installed" else @@ -443,7 +434,7 @@ if ! skip; then echo "" echo " Already connected. Reconnecting is only needed to change the" echo " control plane or what this node advertises." - confirm "Reconfigure it?" n || TS_CONNECT=false + confirm "Reconfigure it?" n tailscale_help || TS_CONNECT=false fi if [[ "$TS_CONNECT" == false ]]; then