make all four network options work, including having no network at all

Option 1 no longer refuses. It assumes offscale is already running — installing
it is one command, documented on the site — and asks for its address and a key,
which is mechanically what option 2 does. The two share a branch because the
difference between them is what to say, not what to do: one is "you already have
a server", the other is "set one up first, here is where".

Option 4 is new: no private network. Presented as a real choice rather than a
failure to choose, with what it costs stated before it is taken and paged so it
is read rather than scrolled past:

  · anything reachable remotely has to be published deliberately and kept closed
    otherwise
  · TLS certificates are yours to obtain and renew
  · every exposed service needs its own authentication, since there is no longer
    a boundary in front of it
  · the machine will be found — anything on a public address is scanned within
    minutes

And the one that is specific to this platform rather than general advice:
ALLOW_ANY_ORIGIN defaults ON, which is deliberate and only defensible because
the tailnet is the perimeter. With no tailnet it must be set to false with an
HTTPS proxy in front, or Officer runs with a check disabled on an assumption that
is no longer true. The summary line says so, so it survives the run.

Declining option 4 redraws the menu rather than dropping to a bare prompt.
Tailscale is still installed when 4 is chosen, and the run says how to connect it
later.

Verified all four end to end with tailscale stubbed, plus the decline-and-choose-
again path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 20:32:27 +00:00
co-authored by Claude Opus 5
parent 06492c3297
commit c629a849d9
2 changed files with 71 additions and 21 deletions
+35 -6
View File
@@ -62,12 +62,13 @@ tailscale_network_menu() {
info "Which network should this machine join?" info "Which network should this machine join?"
echo "" echo ""
echo " [1] set up your own network — offscale" echo " [1] set up your own network — offscale"
echo " Your own coordination server, here on this machine. The protocol" echo " Your own coordination server. The protocol on the wire is"
echo " on the wire is Tailscale's and the encryption is WireGuard's;" echo " Tailscale's and the encryption is WireGuard's; offscale changes"
echo " offscale changes neither — it runs headscale's open-source code." echo " neither — it runs headscale's open-source code. What changes is"
echo " What changes is the work: one command to install, certificates" echo " the work: one command to install, certificates included, managed"
echo " included, managed from an app rather than a terminal, and" echo " from an app rather than a terminal, and enrolling a device is a"
echo " enrolling a device is a link and a tap." echo " link and a tap. Set it up first, then come back here with its"
echo " address and a key."
echo " https://officer.dev/infrastructure/offscale.html" echo " https://officer.dev/infrastructure/offscale.html"
echo "" echo ""
echo " [2] use a network you already run — headscale or offscale" echo " [2] use a network you already run — headscale or offscale"
@@ -79,6 +80,10 @@ tailscale_network_menu() {
echo " nothing to maintain, free for personal use; the trade is that" echo " nothing to maintain, free for personal use; the trade is that"
echo " the list of your machines lives with them." echo " the list of your machines lives with them."
echo "" echo ""
echo " [4] no private network at all"
echo " This machine is reached over the open internet, or not at all."
echo " Everything the tailnet was doing becomes yours to do."
echo ""
echo " [?] what are tailscale, headscale and offscale?" echo " [?] what are tailscale, headscale and offscale?"
echo "" echo ""
} }
@@ -180,6 +185,30 @@ TS_DEFAULT_CONTROL_URL="https://controlplane.tailscale.com"
# Moving a node between coordination servers is not something `up` will do while # Moving a node between coordination servers is not something `up` will do while
# it is logged in to one. Logging out first is the documented way, and doing it # it is logged in to one. Logging out first is the documented way, and doing it
# unasked would be worse than saying so. # unasked would be worse than saying so.
# What choosing "no private network" actually hands you, said before it is
# chosen rather than discovered afterwards.
tailscale_none_warning() {
echo " Without a tailnet, everything it was doing becomes yours:"
echo ""
echo " · Anything you want to reach remotely has to be published to the"
echo " open internet deliberately, and kept closed otherwise."
echo " · TLS certificates are yours to obtain and to keep renewed."
echo " · Every exposed service needs its own authentication, because"
echo " there is no longer a network boundary in front of it."
echo " · This machine will be found. Anything listening on a public"
echo " address is scanned within minutes and attacked continuously."
echo ""
echo " For Officer specifically, one setting stops being safe:"
echo ""
echo " ALLOW_ANY_ORIGIN defaults ON, which means origin checking is off"
echo " unless it is explicitly set to false. That default is deliberate"
echo " and it is only defensible because the tailnet is the perimeter."
echo " With no tailnet you must set ALLOW_ANY_ORIGIN=false and put an"
echo " HTTPS reverse proxy in front of the platform, or it is running"
echo " with a check disabled that was disabled on the assumption you"
echo " are making false."
}
tailscale_needs_logout() { tailscale_needs_logout() {
local current="$1" target="$2" local current="$1" target="$2"
[[ -n "$current" && -n "$target" && "$current" != "$target" ]] [[ -n "$current" && -n "$target" && "$current" != "$target" ]]
+36 -15
View File
@@ -446,21 +446,25 @@ if ! skip; then
TS_LOGIN_SERVER="" TS_LOGIN_SERVER=""
TS_PLANE="" TS_PLANE=""
while [[ -z "$TS_PLANE" ]]; do while [[ -z "$TS_PLANE" ]]; do
if ! read -rp " Which one? (1/2/3/?): " TS_PLANE_CHOICE; then if ! read -rp " Which one? (1/2/3/4/?): " TS_PLANE_CHOICE; then
echo "" echo ""
fail "No answer." fail "No answer."
fi fi
case "$TS_PLANE_CHOICE" in case "$TS_PLANE_CHOICE" in
1) 1 | 2)
# TODO(pastilhas): what setting up your own offscale actually does. # Both end in the same place: a coordination server somebody runs.
warn "Setting up your own network is not built yet." # The difference is only whether they already have one, which changes
echo " Pick 2 if you already run one, or 3 for tailscale.com." # what to say, not what to do.
;; if [[ "$TS_PLANE_CHOICE" == "1" ]]; then
2) echo ""
# No default offered, deliberately. A coordination server URL is echo " Install offscale first — one command, per"
# somebody's private infrastructure, and a machine that joins the echo " https://officer.dev/infrastructure/offscale.html — then give"
# wrong one has joined a stranger's network. echo " this machine its address and a key."
read -rp " URL of your server (e.g. https://headscale.example.com): " TS_LOGIN_SERVER || fail "No answer." fi
# No default offered. 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 " Address of your server (e.g. https://headscale.example.com): " TS_LOGIN_SERVER || fail "No answer."
if [[ "$TS_LOGIN_SERVER" =~ ^https?:// ]]; then if [[ "$TS_LOGIN_SERVER" =~ ^https?:// ]]; then
TS_PLANE="self-hosted" TS_PLANE="self-hosted"
else else
@@ -468,16 +472,32 @@ if ! skip; then
fi fi
;; ;;
3) TS_PLANE="tailscale" ;; 3) TS_PLANE="tailscale" ;;
"?") 4)
echo "" echo ""
tailscale_networks_help | page warn "No private network — do this at your own risk."
echo "" echo ""
tailscale_network_menu tailscale_none_warning | page
echo ""
if confirm "Continue with no private network?" n; then
TS_PLANE="none"
else
echo ""
tailscale_network_menu
fi
;; ;;
*) warn "Pick 1, 2, 3 or ?." ;; *) warn "Pick 1, 2, 3, 4 or ?." ;;
esac esac
done done
if [[ "$TS_PLANE" == "none" ]]; then
warn "no private network — Tailscale is installed but not connected"
echo " Connect it later with: sudo tailscale up"
echo " Remember ALLOW_ANY_ORIGIN=false and an HTTPS proxy in front of Officer."
SUMMARY+=("Tailscale: NOT connected by choice — no private network, ALLOW_ANY_ORIGIN must be set false")
TS_CONNECT=false
fi
if [[ "$TS_CONNECT" != false ]]; then
echo "" echo ""
info "How should this machine authenticate?" info "How should this machine authenticate?"
if [[ "$TS_PLANE" == "tailscale" ]]; then if [[ "$TS_PLANE" == "tailscale" ]]; then
@@ -587,6 +607,7 @@ if ! skip; then
ERRORS+=("Tailscale: up did not complete") ERRORS+=("Tailscale: up did not complete")
SUMMARY+=("Tailscale: NOT connected") SUMMARY+=("Tailscale: NOT connected")
fi fi
fi
fi fi
fi fi
step_ok step_ok