Skip to main content

max / alloy

2.8 KB · 57 lines History Blame Raw
1 #!/bin/sh
2 # alloy-mesh-up — start the mesh daemon, then sign in, under one escalation.
3 #
4 # `tailscale up` talks to tailscaled over a local socket and does nothing on its
5 # own behalf. etc/systemd/system-preset/50-alloy.preset ships
6 # `disable tailscaled.service`, deliberately: joining a mesh reaches out to a
7 # control server and is a question the machine should be asked rather than
8 # assume. So on a fresh install the daemon is not running, and a sign-in that
9 # runs `tailscale up` alone escalates, takes the user's password, and then fails
10 # reading a socket nothing is listening on. That is the whole bug this exists to
11 # close, and it failed *after* the password, which is the expensive place to
12 # fail: the user has already paid the one cost the screen asked them for.
13 #
14 # Enrolling IS the opt-in the preset is waiting for, so this enables the unit
15 # rather than merely starting it. A mesh that evaporates at the next boot is not
16 # a mesh anyone asked for, and the preset's comment already names enrollment as
17 # where the unit is meant to come on.
18 #
19 # Why a script and not two commands from the console. Both halves need root, and
20 # two `run0` invocations are two polkit questions unless the caching happens to
21 # hold. One file is one prompt. It is also why this is not `run0 sh -c '...'`
22 # from the console: crates/alloy/src/cli.rs holds Invocation as argv precisely so
23 # a command is executed exactly as displayed, with no shell and no quoting
24 # round-trip, and --login-server carries a value the user typed. Passing it as
25 # argv to "$@" keeps that property.
26 #
27 # Every argument is forwarded to `tailscale up` untouched.
28 #
29 # The two real commands are echoed before they run. The console's log pane shows
30 # this script's path rather than what it drives, and mesh.rs is explicit that the
31 # abstraction must not conceal which tool is running, so the terminal the user
32 # was just handed says it.
33
34 set -eu
35
36 echo "+ systemctl enable --now tailscaled.service"
37 systemctl enable --now tailscaled.service
38
39 # Not a fixed sleep. `tailscale up` fails on a socket that exists but is not yet
40 # answering, and `systemctl --now` returns when the unit is active rather than
41 # when tailscaled has finished opening it. Ten tries at a tenth of a second is
42 # a second of patience for something that normally takes one round.
43 i=0
44 while [ "$i" -lt 10 ]; do
45 tailscale status >/dev/null 2>&1 && break
46 # `status` exits non-zero on a running daemon that is merely logged out,
47 # which is the state this script is always in. Distinguish "not answering"
48 # from "answering that there is nothing to report" by asking for the version,
49 # which needs the socket and not an account.
50 tailscale version --daemon >/dev/null 2>&1 && break
51 i=$((i + 1))
52 sleep 0.1
53 done
54
55 echo "+ tailscale up $*"
56 exec tailscale up "$@"
57