From 6a29c39b74ef3d6c3e8370f290f1f6d1b7aa52a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 12 Aug 2026 19:41:43 +0000 Subject: [PATCH] restructure the Tailscale network choice, with offscale left to be written MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four options, in the order you gave: 1 set up your own network (offscale) 2 use a network you already run (headscale, offscale) 3 the easy route (tailscale.com) ? what are tailscale, headscale and offscale? ? prints the long answer and then shows the options again, rather than dropping the reader back at a bare prompt having forgotten what they were choosing between. The explanation frames all three as one question — who keeps the list of your machines and hands out the keys — and says plainly that the coordination server never carries traffic, since that is the thing people assume it does. Tailscale and headscale are written. OFFSCALE is a marked placeholder, and so is what option 1 actually does; both are yours to fill in and the run says so rather than pretending. Option 3 is the plain flow: no --login-server at all, and the auth-key prompt says what that means — leave it blank and Tailscale prints a link that either creates the account or adds this machine to an existing one. Option 2 keeps the "no suggested URL" rule, because a coordination server URL is somebody's private infrastructure. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/setup/machine-setup/lib/tailscale.sh | 39 +++++++++++++ scripts/setup/machine-setup/machine-setup.sh | 60 +++++++++++++++----- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/scripts/setup/machine-setup/lib/tailscale.sh b/scripts/setup/machine-setup/lib/tailscale.sh index 89d8c2a8..a64a0128 100644 --- a/scripts/setup/machine-setup/lib/tailscale.sh +++ b/scripts/setup/machine-setup/lib/tailscale.sh @@ -55,6 +55,45 @@ tailscale_help() { echo " lock you out of the machine, so there is always a second way in." } +# The long answer, printed when somebody types ?. Covers all three names, +# because the menu offers all three and two of them are not words anyone outside +# this project would know. +tailscale_networks_help() { + echo " Tailscale, headscale and offscale are three answers to one question:" + echo " who keeps the list of your machines and hands out the keys they use" + echo " to find each other." + echo "" + echo " The network itself is the same in all three cases. Machines talk" + echo " directly to each other over WireGuard, encrypted end to end. What" + echo " differs is only the coordination server — the thing that knows which" + echo " machines are yours. It never carries your traffic." + echo "" + echo " TAILSCALE" + echo " The company's own coordination server. Nothing to run, nothing to" + echo " maintain, free for personal use. You sign in with an existing" + echo " identity and your machines appear in their admin console." + echo " The trade is that the list of your machines lives with them." + echo "" + echo " HEADSCALE" + echo " An open-source coordination server you run yourself. The same" + echo " Tailscale clients connect to it, so the machines behave identically;" + echo " the difference is that nobody else holds the list. The cost is that" + echo " it is now a service you host, and it needs to be reachable." + echo "" + echo " OFFSCALE" + # TODO(pastilhas): your words. What offscale is, how it relates to headscale, + # and what "set up your own network" actually does for someone choosing 1. + echo " [ to be written ]" + echo "" + echo " FOR OFFICER" + echo " Whichever you pick, the tailnet is what Officer treats as its" + echo " perimeter. ALLOW_ANY_ORIGIN defaults on, and that is only" + echo " defensible because the machine is not reachable from the open" + echo " internet in the first place. Installed at this point in the run," + echo " before anything that can lock you out, so there is always a second" + echo " 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 649bb11d..b723ac15 100755 --- a/scripts/setup/machine-setup/machine-setup.sh +++ b/scripts/setup/machine-setup/machine-setup.sh @@ -441,38 +441,66 @@ if ! skip; then SUMMARY+=("Tailscale: connected, unchanged ($(tailscale_ip))") else echo "" - info "Which control plane?" - echo " [1] Tailscale's own service (tailscale.com)" - echo " [2] a self-hosted headscale" + info "Which network should this machine join?" echo "" + echo " [1] set up your own network (offscale)" + echo " [2] use a network you already run (headscale, offscale)" + echo " [3] the easy route (tailscale.com)" + echo " [?] what are tailscale, headscale and offscale?" + echo "" + TS_LOGIN_SERVER="" TS_PLANE="" while [[ -z "$TS_PLANE" ]]; do - if ! read -rp " Which one? (1/2) [1]: " TS_PLANE_CHOICE; then + if ! read -rp " Which one? (1/2/3/?): " TS_PLANE_CHOICE; then echo "" fail "No answer." fi - case "${TS_PLANE_CHOICE:-1}" in - 1) TS_PLANE="tailscale" ;; + case "$TS_PLANE_CHOICE" in + 1) + # TODO(pastilhas): what setting up your own offscale actually does. + warn "Setting up your own network is not built yet." + echo " Pick 2 if you already run one, or 3 for tailscale.com." + ;; 2) - # No default offered. A control-plane URL is somebody's private - # infrastructure, and a machine that joins the wrong tailnet has - # joined a stranger's network. - read -rp " headscale URL (e.g. https://headscale.example.com): " TS_LOGIN_SERVER || fail "No answer." + # No default offered, deliberately. A coordination server URL is + # somebody's private infrastructure, and a machine that joins the + # wrong one has joined a stranger's network. + read -rp " URL of your server (e.g. https://headscale.example.com): " TS_LOGIN_SERVER || fail "No answer." if [[ "$TS_LOGIN_SERVER" =~ ^https?:// ]]; then - TS_PLANE="headscale" + TS_PLANE="self-hosted" else warn "That needs to be a full URL, starting with https://" fi ;; - *) warn "Pick 1 or 2." ;; + 3) TS_PLANE="tailscale" ;; + "?") + echo "" + tailscale_networks_help + echo "" + info "Which network should this machine join?" + echo "" + echo " [1] set up your own network (offscale)" + echo " [2] use a network you already run (headscale, offscale)" + echo " [3] the easy route (tailscale.com)" + echo " [?] what are tailscale, headscale and offscale?" + echo "" + ;; + *) warn "Pick 1, 2, 3 or ?." ;; esac done echo "" info "How should this machine authenticate?" - echo " An auth key enrols it without a browser. Leaving this blank is" - echo " fine — Tailscale then prints a URL to open, and waits for you." + if [[ "$TS_PLANE" == "tailscale" ]]; then + echo " Leave this blank and Tailscale prints a link to open in a" + echo " browser. Signing in there creates the account if you do not" + echo " have one, or adds this machine to it if you do." + echo " An auth key, if you have minted one, skips the browser." + else + echo " An auth key enrols this machine without a browser. Leaving it" + echo " blank prints a link to open against your own server instead." + fi echo "" read -rp " Auth key (blank for the browser flow): " TS_AUTHKEY || fail "No answer." @@ -516,7 +544,9 @@ if ! skip; then echo "" TS_ARGS=(up --timeout=60s) - [[ "$TS_PLANE" == "headscale" ]] && TS_ARGS+=(--login-server "$TS_LOGIN_SERVER") + # Only a self-hosted server needs pointing at. Option 3 is the default + # coordination server, which means passing no --login-server at all. + [[ "$TS_PLANE" == "self-hosted" ]] && TS_ARGS+=(--login-server "$TS_LOGIN_SERVER") # Never passed empty. `--authkey ""` silently falls back to the interactive # flow and blocks forever, which is exactly how the original hung. [[ -n "$TS_AUTHKEY" ]] && TS_ARGS+=(--authkey "$TS_AUTHKEY")