#!/bin/sh # stub.sh - stage one of the seat bootstrap (ADR 0041), served publicly at # https://seat.bartosek.io: curl -fsSL https://seat.bartosek.io | sh # Joins the tailnet unless already reachable, fetches stage two over it, # verifies the pinned SHA-256, runs it. Public: holds no secret. The pin is # written by scripts/release.sh from SHA256SUMS; never edit it by hand. set -eu EXPECTED_SHA256=f2590d01a8525c16b9bc88899741bdd952a6acfd282f67e19a161a697249305d SEAT=https://seat.bartosek.io die() { code=$1; shift; echo "seat: $*" >&2; exit "$code"; } verify() { # verify FILE -> 0 iff its sha256 is EXPECTED_SHA256 if command -v sha256sum >/dev/null; then h=$(sha256sum "$1"); else h=$(shasum -a 256 "$1"); fi [ "${h%% *}" = "$EXPECTED_SHA256" ] } daemon_up() { $SUDO tailscale status --json >/dev/null 2>&1; } # 0 even when logged out start_tailscaled() { # one tailscaled per network namespace (WSL2: per Windows host) daemon_up && return 0 if command -v systemctl >/dev/null && [ "$(systemctl is-system-running 2>/dev/null)" != offline ]; then $SUDO systemctl enable --now tailscaled else # no systemd (e.g. WSL without it) $SUDO sh -c 'nohup tailscaled --state=/var/lib/tailscale/tailscaled.state >/var/log/tailscaled.log 2>&1 &' fi i=0; until daemon_up; do i=$((i + 1)); [ "$i" -lt 10 ] \ || die 1 "tailscaled not running after 10s (see /var/log/tailscaled.log or journalctl -u tailscaled)"; sleep 1; done } join() { case $(uname -s) in Linux) command -v tailscale >/dev/null || curl -fsSL https://tailscale.com/install.sh | sh start_tailscaled ;; Darwin) SUDO=; command -v tailscale >/dev/null \ || die 2 "install Tailscale first (App Store, or: brew install --cask tailscale), then rerun" ;; *) die 2 "unsupported OS: $(uname -s)" ;; esac if ! tailscale status >/dev/null 2>&1; then echo "seat: joining the tailnet - open the URL below and confirm with your passkey" $SUDO tailscale up --login-server=https://headscale.bartosek.io fi tailscale status >/dev/null 2>&1 || die 1 "tailscale is not logged in" } main() { SUDO=sudo; [ "$(id -u)" = 0 ] && SUDO= if curl -fsS -o /dev/null --max-time 5 "$SEAT/healthz" 2>/dev/null; then echo "seat: tailnet already reachable, skipping Tailscale" else join; fi i=0 # the name flips to its tailnet address once MagicDNS takes over until curl -fsS -o /dev/null "$SEAT/healthz" 2>/dev/null; do i=$((i + 1)); [ "$i" -lt 30 ] || die 1 "$SEAT/healthz not reachable over the tailnet after 60s" sleep 2 done tmp=$(mktemp); trap 'rm -f "$tmp"' EXIT curl -fsS -o "$tmp" "$SEAT/install-seat.sh" || die 1 "cannot fetch stage two" verify "$tmp" || die 3 "REFUSED: stage two does not match the pinned sha256 $EXPECTED_SHA256" echo "seat: stage two verified ($EXPECTED_SHA256)" sh "$tmp" "$@" } main "$@"