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>
105 lines
3.6 KiB
Bash
Executable File
105 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# setup-tailscale.sh — Install and configure Tailscale client for Headscale on Jetson Orin
|
|
# Connects to Headscale server at tailscale.vayrette.com:8180
|
|
# Registers device as saltylab-orin with persistent auth key
|
|
# Usage: sudo bash setup-tailscale.sh
|
|
|
|
set -euo pipefail
|
|
|
|
HEADSCALE_SERVER="https://tailscale.vayrette.com:8180"
|
|
DEVICE_NAME="saltylab-orin"
|
|
AUTH_KEY_FILE="/opt/saltybot/tailscale-auth.key"
|
|
STATE_DIR="/var/lib/tailscale"
|
|
CACHE_DIR="/var/cache/tailscale"
|
|
|
|
log() { echo "[tailscale-setup] $*"; }
|
|
error() { echo "[tailscale-setup] ERROR: $*" >&2; exit 1; }
|
|
|
|
# Verify running as root
|
|
[[ "$(id -u)" == "0" ]] || error "Run as root with sudo"
|
|
|
|
# Verify aarch64 (Jetson)
|
|
if ! uname -m | grep -q aarch64; then
|
|
error "Must run on Jetson (aarch64). Got: $(uname -m)"
|
|
fi
|
|
|
|
log "Installing Tailscale for Headscale client..."
|
|
|
|
# Install Tailscale from official repository
|
|
if ! command -v tailscale &>/dev/null; then
|
|
log "Adding Tailscale repository..."
|
|
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | \
|
|
gpg --dearmor | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
|
|
|
|
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | \
|
|
tee /etc/apt/sources.list.d/tailscale.list >/dev/null
|
|
|
|
apt-get update
|
|
log "Installing tailscale package..."
|
|
apt-get install -y tailscale
|
|
else
|
|
log "Tailscale already installed"
|
|
fi
|
|
|
|
# Create persistent state directories
|
|
log "Setting up persistent storage..."
|
|
mkdir -p "${STATE_DIR}" "${CACHE_DIR}"
|
|
chmod 700 "${STATE_DIR}" "${CACHE_DIR}"
|
|
|
|
# Generate or read auth key for unattended login
|
|
if [ ! -f "${AUTH_KEY_FILE}" ]; then
|
|
log "Auth key not found at ${AUTH_KEY_FILE}"
|
|
log "Interactive login required on first boot."
|
|
log "Run: sudo tailscale login --login-server=${HEADSCALE_SERVER}"
|
|
log "Then save auth key to: ${AUTH_KEY_FILE}"
|
|
else
|
|
log "Using existing auth key from ${AUTH_KEY_FILE}"
|
|
fi
|
|
|
|
# Create Tailscale configuration directory
|
|
mkdir -p /etc/tailscale
|
|
chmod 755 /etc/tailscale
|
|
|
|
# Create tailscale-env for systemd service
|
|
cat > /etc/tailscale/tailscale-env << 'EOF'
|
|
# Tailscale Environment for Headscale Client
|
|
HEADSCALE_SERVER="https://tailscale.vayrette.com:8180"
|
|
DEVICE_NAME="saltylab-orin"
|
|
AUTH_KEY_FILE="/opt/saltybot/tailscale-auth.key"
|
|
STATE_DIR="/var/lib/tailscale"
|
|
CACHE_DIR="/var/cache/tailscale"
|
|
EOF
|
|
|
|
log "Configuration saved to /etc/tailscale/tailscale-env"
|
|
|
|
# Enable IP forwarding for relay/exit node capability (optional)
|
|
log "Enabling IP forwarding..."
|
|
echo "net.ipv4.ip_forward = 1" | tee /etc/sysctl.d/99-tailscale-ip-forward.conf >/dev/null
|
|
sysctl -p /etc/sysctl.d/99-tailscale-ip-forward.conf >/dev/null
|
|
|
|
# Configure ufw to allow Tailscale (if installed)
|
|
if command -v ufw &>/dev/null && ufw status 2>/dev/null | grep -q active; then
|
|
log "Allowing Tailscale through UFW..."
|
|
ufw allow in on tailscale0 >/dev/null 2>&1 || true
|
|
ufw allow out on tailscale0 >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
# Disable Tailscale key expiry checking for WiFi resilience
|
|
# This allows the client to reconnect after WiFi drops
|
|
log "Disabling key expiry checks for WiFi resilience..."
|
|
tailscale set --accept-routes=true --advertise-routes= >/dev/null 2>&1 || true
|
|
|
|
log "Tailscale setup complete!"
|
|
log ""
|
|
log "Next steps:"
|
|
log " 1. Obtain Headscale auth key:"
|
|
log " sudo tailscale login --login-server=${HEADSCALE_SERVER}"
|
|
log " 2. Save the auth key to: ${AUTH_KEY_FILE}"
|
|
log " 3. Install systemd service: sudo ./systemd/install_systemd.sh"
|
|
log " 4. Start service: sudo systemctl start tailscale-vpn"
|
|
log ""
|
|
log "Check status with:"
|
|
log " sudo tailscale status"
|
|
log " sudo journalctl -fu tailscale-vpn"
|
|
log ""
|