#!/bin/bash
set -e
# Enable debugging if DEBUG=1
if [ "${DEBUG:-0}" = "1" ]; then
set -x
fi
# Tailscale settings
TS_VER="1.90.5"
TS_ARCH="arm64"
TS_TGZ="tailscale_${TS_VER}_${TS_ARCH}.tgz"
TS_URL="https://pkgs.tailscale.com/stable/${TS_TGZ}"
SERIAL_FILE="/home/root/rexusb/serial"
# Standard locations
BIN_DIR="/usr/bin"
STATE_DIR="/var/lib/tailscale"
SOCKET_DIR="/run/tailscale"
SYSTEMD_SERVICE="/etc/systemd/system/tailscaled.service"
DEFAULTS_FILE="/etc/default/tailscaled"
# Hardcoded auth key - replace with your actual key
AUTHKEY="tskey-auth-kDBxyp1FBu11CNT4"
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $1"; }
fail() { log "? $1"; exit 1; }
log "Creating required directories..."
mkdir -p "$STATE_DIR" "$SOCKET_DIR"
cd /tmp || fail "Could not change to /tmp"
log "Downloading ${TS_TGZ}..."
wget -q "$TS_URL" -O "$TS_TGZ" || fail "Failed to download Tailscale package"
log "Extracting package..."
tar -xzf "$TS_TGZ" || fail "Failed to extract Tailscale package"
TS_EXTRACTED_DIR=$(find . -maxdepth 1 -type d -name "tailscale_*_${TS_ARCH}" | head -n1)
[ -z "$TS_EXTRACTED_DIR" ] && fail "Could not find extracted Tailscale directory"
TS_EXTRACTED_DIR=${TS_EXTRACTED_DIR#./}
log "Installing tailscale binaries to $BIN_DIR..."
cp "$TS_EXTRACTED_DIR/tailscale" "$BIN_DIR/tailscale"
cp "$TS_EXTRACTED_DIR/tailscaled" "$BIN_DIR/tailscaled"
chmod +x "$BIN_DIR/tailscale" "$BIN_DIR/tailscaled"
[ ! -f "$SERIAL_FILE" ] && fail "Serial file not found: $SERIAL_FILE"
HOSTNAME=$(tr -d '\n\r' < "$SERIAL_FILE")
[ -z "$HOSTNAME" ] && fail "Hostname is empty!"
# Sanitize hostname
SANITIZED_HOSTNAME=$(echo "$HOSTNAME" | tr -cd 'a-zA-Z0-9')
[ "$SANITIZED_HOSTNAME" != "$HOSTNAME" ] && log "Sanitized hostname: $SANITIZED_HOSTNAME"
HOSTNAME="$SANITIZED_HOSTNAME"
[ ${#HOSTNAME} -gt 63 ] && HOSTNAME="${HOSTNAME:0:63}"
# Defaults file
log "Creating /etc/default/tailscaled..."
cat <<EOF > "$DEFAULTS_FILE"
# Extra options for tailscaled
#TAILSCALED_OPTS=""
EOF
# Fixed systemd service with CAP_SETGID
log "Creating systemd service at $SYSTEMD_SERVICE..."
cat <<EOF > "$SYSTEMD_SERVICE"
[Unit]
Description=Tailscale node agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=-/etc/default/tailscaled
ExecStart=/usr/bin/tailscaled \$TAILSCALED_OPTS --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
KillMode=process
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID
[Install]
WantedBy=multi-user.target
EOF
log "Reloading systemd and starting tailscaled..."
systemctl daemon-reexec || log "daemon-reexec failed, continuing"
systemctl daemon-reload || fail "Failed to reload systemd"
systemctl enable tailscaled.service || fail "Failed to enable service"
systemctl restart tailscaled.service || fail "Failed to start service"
# Wait for socket
MAX_WAIT=30
for i in $(seq 1 $MAX_WAIT); do
if [ -S /run/tailscale/tailscaled.sock ]; then
log "✓ Socket ready after $i seconds"
break
fi
log "Waiting for tailscaled to initialize... ($i/$MAX_WAIT)"
sleep 1
systemctl is-active --quiet tailscaled.service || fail "tailscaled died"
[ $i -eq $MAX_WAIT ] && fail "Timeout waiting for tailscaled socket"
done
log "Running tailscale up..."
# Disable Tailscale DNS management so we can use public DNS
tailscale --socket=/run/tailscale/tailscaled.sock up --authkey $AUTHKEY --ssh --hostname $HOSTNAME --accept-dns=false
# --- Permanent DNS fix ---
log "Configuring permanent DNS..."
cat <<EOF > /etc/resolv.conf
# Managed manually to avoid Tailscale overwrite
nameserver 8.8.8.8
nameserver 1.1.1.1
EOF
chmod 644 /etc/resolv.conf
log "DNS configured: $(cat /etc/resolv.conf)"
log "Installation complete!"
log "Check Tailscale status: tailscale --socket=/run/tailscale/tailscaled.sock status"