#!/bin/sh
# alloy-mesh-up — start the mesh daemon, then sign in, under one escalation.
#
# `tailscale up` talks to tailscaled over a local socket and does nothing on its
# own behalf. etc/systemd/system-preset/50-alloy.preset ships
# `disable tailscaled.service`, deliberately: joining a mesh reaches out to a
# control server and is a question the machine should be asked rather than
# assume. So on a fresh install the daemon is not running, and a sign-in that
# runs `tailscale up` alone escalates, takes the user's password, and then fails
# reading a socket nothing is listening on. That is the whole bug this exists to
# close, and it failed *after* the password, which is the expensive place to
# fail: the user has already paid the one cost the screen asked them for.
#
# Enrolling IS the opt-in the preset is waiting for, so this enables the unit
# rather than merely starting it. A mesh that evaporates at the next boot is not
# a mesh anyone asked for, and the preset's comment already names enrollment as
# where the unit is meant to come on.
#
# Why a script and not two commands from the console. Both halves need root, and
# two `run0` invocations are two polkit questions unless the caching happens to
# hold. One file is one prompt. It is also why this is not `run0 sh -c '...'`
# from the console: crates/alloy/src/cli.rs holds Invocation as argv precisely so
# a command is executed exactly as displayed, with no shell and no quoting
# round-trip, and --login-server carries a value the user typed. Passing it as
# argv to "$@" keeps that property.
#
# Every argument is forwarded to `tailscale up` untouched.
#
# The two real commands are echoed before they run. The console's log pane shows
# this script's path rather than what it drives, and mesh.rs is explicit that the
# abstraction must not conceal which tool is running, so the terminal the user
# was just handed says it.

set -eu

echo "+ systemctl enable --now tailscaled.service"
systemctl enable --now tailscaled.service

# Not a fixed sleep. `tailscale up` fails on a socket that exists but is not yet
# answering, and `systemctl --now` returns when the unit is active rather than
# when tailscaled has finished opening it. Ten tries at a tenth of a second is
# a second of patience for something that normally takes one round.
i=0
while [ "$i" -lt 10 ]; do
    tailscale status >/dev/null 2>&1 && break
    # `status` exits non-zero on a running daemon that is merely logged out,
    # which is the state this script is always in. Distinguish "not answering"
    # from "answering that there is nothing to report" by asking for the version,
    # which needs the socket and not an account.
    tailscale version --daemon >/dev/null 2>&1 && break
    i=$((i + 1))
    sleep 0.1
done

echo "+ tailscale up $*"
exec tailscale up "$@"
