tracker/scripts/tailscale.sh
#!/usr/bin/env bash
# Expose the tracker to the tailnet with `tailscale serve`.
#
# scripts/tailscale.sh on # forward tailnet port $PORT to the tracker
# scripts/tailscale.sh off # stop forwarding
# scripts/tailscale.sh status # show the serve config and the URL
#
# Uses raw TCP forwarding (`serve --tcp`), not HTTP serve: HTTP serve routes by
# hostname, so it only answers on the MagicDNS name, and MagicDNS is off in our
# tailnet. TCP forwarding answers on the Tailscale IP and passes the live-update
# stream (Server-Sent Events) through unbuffered.
#
# Works with Tailscale inside WSL or on the Windows host. With WSL2 in NAT mode,
# Windows reaches the tracker through WSL's localhost forwarding, which here
# listens on ::1 only, so the target is "localhost" (not 127.0.0.1).
set -euo pipefail
PORT="${PORT:-8099}"
TS="${TAILSCALE:-}"
if [[ -z "$TS" ]]; then
if command -v tailscale >/dev/null 2>&1; then
TS=tailscale
elif [[ -x "/mnt/c/Program Files/Tailscale/tailscale.exe" ]]; then
TS="/mnt/c/Program Files/Tailscale/tailscale.exe"
else
echo "tailscale not found: install it in WSL or on Windows, or set TAILSCALE=/path/to/tailscale" >&2
exit 1
fi
fi
url() {
local ip
ip="$("$TS" ip -4 | tr -d '\r' | head -1)"
echo "http://${ip}:${PORT}/"
}
case "${1:-status}" in
on)
if ! curl -sf -m 3 "http://localhost:${PORT}/healthz" >/dev/null; then
echo "warning: the tracker is not answering on localhost:${PORT}; start it with: cd tracker && go run ." >&2
fi
"$TS" serve --bg --tcp="$PORT" "tcp://localhost:${PORT}" | tr -d '\r'
echo "Tracker on the tailnet: $(url)"
;;
off)
"$TS" serve --tcp="$PORT" off | tr -d '\r'
;;
status)
"$TS" serve status | tr -d '\r'
echo "URL: $(url)"
;;
*)
echo "usage: $0 on|off|status" >&2
exit 2
;;
esac