saltylab-firmware/jetson/scripts/headscale-auth-helper.sh
sl-jetson 062c05cac0 feat: Add Issue #502 - Headscale VPN auto-connect on Orin
Configure Jetson Orin with Tailscale client connecting to Headscale
coordination server at tailscale.vayrette.com:8180. Device registers
as 'saltylab-orin' with persistent auth key for unattended login.

Features:
- systemd auto-start and restart on WiFi drops
- Persistent auth key storage at /opt/saltybot/tailscale-auth.key
- SSH + HTTP access over Tailscale tailnet (encrypted WireGuard)
- IP forwarding enabled for relay/exit node capability
- WiFi resilience with aggressive restart policy
- MQTT reporting of VPN status, IP, and connection type

Components added:
- jetson/scripts/setup-tailscale.sh: Tailscale package installation
- jetson/scripts/headscale-auth-helper.sh: Auth key management utility
- jetson/systemd/tailscale-vpn.service: systemd service unit
- jetson/docs/headscale-vpn-setup.md: Comprehensive setup documentation
- saltybot_cellular/vpn_status_node.py: ROS2 node for MQTT reporting

Updated:
- jetson/systemd/install_systemd.sh: Include tailscale-vpn.service
- jetson/scripts/setup-jetson.sh: Add Tailscale setup steps

Access patterns:
- SSH: ssh user@saltylab-orin.tail12345.ts.net
- HTTP: http://saltylab-orin.tail12345.ts.net:port
- Direct IP: 100.x.x.x (Tailscale allocated address)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-06 10:25:04 -05:00

132 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# headscale-auth-helper.sh — Manage Headscale auth key persistence
# Generates, stores, and validates auth keys for unattended Tailscale login
# Usage:
# sudo bash headscale-auth-helper.sh generate
# sudo bash headscale-auth-helper.sh validate
# sudo bash headscale-auth-helper.sh show
# sudo bash headscale-auth-helper.sh revoke
set -euo pipefail
HEADSCALE_SERVER="https://tailscale.vayrette.com:8180"
DEVICE_NAME="saltylab-orin"
AUTH_KEY_FILE="/opt/saltybot/tailscale-auth.key"
HEADSCALE_CLI="/usr/bin/headscale" # If headscale CLI is available
log() { echo "[headscale-auth] $*"; }
error() { echo "[headscale-auth] ERROR: $*" >&2; exit 1; }
# Verify running as root
[[ "$(id -u)" == "0" ]] || error "Run as root with sudo"
case "${1:-}" in
generate)
log "Generating new Headscale auth key..."
log "This requires access to Headscale admin console."
log ""
log "Manual steps:"
log " 1. SSH to Headscale server"
log " 2. Run: headscale preauthkeys create --expiration 2160h --user default"
log " 3. Copy the key"
log " 4. Paste when prompted:"
read -rsp "Enter auth key: " key
echo ""
if [ -z "$key" ]; then
error "Auth key cannot be empty"
fi
mkdir -p "$(dirname "${AUTH_KEY_FILE}")"
echo "$key" > "${AUTH_KEY_FILE}"
chmod 600 "${AUTH_KEY_FILE}"
log "Auth key saved to ${AUTH_KEY_FILE}"
log "Next: sudo systemctl restart tailscale-vpn"
;;
validate)
log "Validating auth key..."
if [ ! -f "${AUTH_KEY_FILE}" ]; then
error "Auth key file not found: ${AUTH_KEY_FILE}"
fi
key=$(cat "${AUTH_KEY_FILE}")
if [ -z "$key" ]; then
error "Auth key is empty"
fi
if [[ ! "$key" =~ ^tskey_ ]]; then
error "Invalid auth key format (should start with tskey_)"
fi
log "✓ Auth key format valid"
log " File: ${AUTH_KEY_FILE}"
log " Key: ${key:0:10}..."
;;
show)
log "Auth key status:"
if [ ! -f "${AUTH_KEY_FILE}" ]; then
log " Status: NOT CONFIGURED"
log " Run: sudo bash headscale-auth-helper.sh generate"
else
key=$(cat "${AUTH_KEY_FILE}")
log " Status: CONFIGURED"
log " Key: ${key:0:15}..."
# Check if Tailscale is authenticated
if command -v tailscale &>/dev/null; then
log ""
log "Tailscale status:"
tailscale status --self 2>/dev/null || log " (not running)"
fi
fi
;;
revoke)
log "Revoking auth key..."
if [ ! -f "${AUTH_KEY_FILE}" ]; then
error "Auth key file not found"
fi
key=$(cat "${AUTH_KEY_FILE}")
read -rp "Revoke key ${key:0:15}...? [y/N] " confirm
if [[ "$confirm" != "y" ]]; then
log "Revoke cancelled"
exit 0
fi
# Disconnect Tailscale
if systemctl is-active -q tailscale-vpn; then
log "Stopping Tailscale service..."
systemctl stop tailscale-vpn
fi
# Remove key file
rm -f "${AUTH_KEY_FILE}"
log "Auth key revoked and removed"
log "Run: sudo bash headscale-auth-helper.sh generate"
;;
*)
cat << 'EOF'
Usage: sudo bash headscale-auth-helper.sh <command>
Commands:
generate - Prompt for new Headscale auth key and save it
validate - Validate existing auth key format
show - Display auth key status and Tailscale connection
revoke - Revoke and remove the stored auth key
Examples:
sudo bash headscale-auth-helper.sh generate
sudo bash headscale-auth-helper.sh show
sudo bash headscale-auth-helper.sh revoke
EOF
exit 1
;;
esac