#!/bin/bash # Tailscale Installation and Connection Script for Linux (with hardcoded auth key and optional custom login server) # This script installs Tailscale (if not present) and connects using a hardcoded auth key # Optionally supports custom login server (Headscale) - leave LOGIN_SERVER empty to use default Tailscale server # WARNING: This file contains sensitive auth key and should NOT be committed to Git # Usage: ./install.sh set -e # Exit on any error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Custom login server (Headscale) - OPTIONAL: Set to your Headscale server URL or leave empty to use default Tailscale server # Example: LOGIN_SERVER="https://headscale.ovncr.vn" # Leave empty to use default Tailscale server: LOGIN_SERVER="" LOGIN_SERVER="https://headscale.ovncr.vn" # Auth key - REPLACE WITH YOUR ACTUAL AUTH KEY AUTH_KEY="26a0091c3f1aefa116faf081e25e1d488e33038d478e7cbd" # Logging functions log_info() { printf "${GREEN}[INFO]${NC} %s\n" "$1" } log_warn() { printf "${YELLOW}[WARN]${NC} %s\n" "$1" } log_error() { printf "${RED}[ERROR]${NC} %s\n" "$1" } # Check if running as root or with sudo check_root() { if [ "$(id -u)" -ne 0 ]; then log_error "This script must be run as root or with sudo" exit 1 fi } # Detect Linux distribution detect_distro() { if [ -f /etc/os-release ]; then . /etc/os-release DISTRO=$ID VERSION=$VERSION_ID else log_error "Cannot detect Linux distribution. /etc/os-release not found." exit 1 fi log_info "Detected distribution: $DISTRO $VERSION" } # Check if Tailscale is already installed is_tailscale_installed() { # Check if tailscale command exists if command -v tailscale >/dev/null 2>&1; then return 0 fi # Check if tailscaled service exists and is properly installed if systemctl list-unit-files 2>/dev/null | grep -q "^tailscaled.service"; then # Verify the service file actually exists if [ -f /etc/systemd/system/tailscaled.service ] || [ -f /usr/lib/systemd/system/tailscaled.service ] || [ -f /lib/systemd/system/tailscaled.service ]; then return 0 fi fi return 1 } # Install Tailscale based on distribution install_tailscale() { log_info "Installing Tailscale..." case $DISTRO in ubuntu|debian|kali) log_info "Using apt package manager" export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq curl gnupg curl -fsSL https://tailscale.com/install.sh | sh ;; rhel|centos|fedora|rocky|almalinux) log_info "Using yum/dnf package manager" if command -v dnf >/dev/null 2>&1; then dnf install -y curl curl -fsSL https://tailscale.com/install.sh | sh elif command -v yum >/dev/null 2>&1; then yum install -y curl curl -fsSL https://tailscale.com/install.sh | sh else log_error "Neither dnf nor yum found" exit 1 fi ;; arch|manjaro) log_info "Using pacman package manager" pacman -Sy --noconfirm curl curl -fsSL https://tailscale.com/install.sh | sh ;; *) log_error "Unsupported distribution: $DISTRO" log_info "Please install Tailscale manually from https://tailscale.com/download" exit 1 ;; esac log_info "Tailscale installation completed" } # Enable and start Tailscale service setup_service() { log_info "Setting up Tailscale service..." # Check if service exists if ! systemctl list-unit-files 2>/dev/null | grep -q "^tailscaled.service"; then log_error "tailscaled service not found. Tailscale may not be installed correctly." log_info "Attempting to reinstall Tailscale..." install_tailscale # Reload systemd after installation systemctl daemon-reload sleep 2 fi # Enable service to start on boot if systemctl enable tailscaled 2>/dev/null; then log_info "Tailscale service enabled for auto-start on boot" else # Check if already enabled if systemctl is-enabled tailscaled >/dev/null 2>&1; then log_info "Tailscale service is already enabled" else log_warn "Failed to enable tailscaled service" fi fi # Start the service if systemctl start tailscaled 2>/dev/null; then log_info "Tailscale service started" else # Check if already running if systemctl is-active --quiet tailscaled 2>/dev/null; then log_info "Tailscale service is already running" else log_warn "Failed to start tailscaled service" fi fi # Wait for service to be ready log_info "Waiting for Tailscale service to be ready..." sleep 3 # Verify service is running if systemctl is-active --quiet tailscaled 2>/dev/null; then log_info "Tailscale service is running" else log_error "Tailscale service failed to start" systemctl status tailscaled || true exit 1 fi } # Validate login server URL (only if provided) validate_login_server() { # If LOGIN_SERVER is empty, skip validation (will use default Tailscale server) if [ -z "$LOGIN_SERVER" ]; then log_info "No custom login server specified, will use default Tailscale server" return 0 fi if ! echo "$LOGIN_SERVER" | grep -qE "^https?://"; then log_error "Invalid login server URL format. URL should start with http:// or https://" exit 1 fi log_info "Login server validated: $LOGIN_SERVER" } # Validate auth key validate_auth_key() { if [ "$AUTH_KEY" = "YOUR_AUTH_KEY_HERE" ]; then log_error "Auth key not configured. Please replace YOUR_AUTH_KEY_HERE with your actual Tailscale auth key." exit 1 fi if [ -z "$AUTH_KEY" ]; then log_error "Auth key cannot be empty" exit 1 fi # When using custom login server (Headscale), auth keys may not have tskey-auth- prefix # Only validate format for standard Tailscale auth keys if [ -n "$LOGIN_SERVER" ] && [ "$LOGIN_SERVER" != "https://login.tailscale.com" ]; then log_info "Using custom login server, skipping standard auth key format validation" elif ! echo "$AUTH_KEY" | grep -q "^tskey-auth-"; then log_error "Invalid auth key format. Auth key should start with 'tskey-auth-'" exit 1 fi log_info "Auth key validated" } # Disconnect from Tailscale if already connected disconnect_tailscale() { log_info "Checking current Tailscale connection status..." # Check if Tailscale is already connected if tailscale status >/dev/null 2>&1; then local status_output=$(tailscale status 2>/dev/null | head -1) if [ -n "$status_output" ] && echo "$status_output" | grep -qE "^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+"; then log_warn "Tailscale is already connected. Disconnecting to switch account..." tailscale down sleep 2 # Remove state to fully reset connection and switch to new account log_info "Removing Tailscale state to fully reset connection..." rm -f /var/lib/tailscale/tailscaled.state systemctl restart tailscaled sleep 3 # Verify service is running after restart if systemctl is-active --quiet tailscaled 2>/dev/null; then log_info "Tailscale service restarted successfully" else log_warn "Tailscale service may not be ready yet" fi fi fi } # Connect to Tailscale with auth key connect_tailscale() { log_info "Connecting to Tailscale..." # Disconnect if already connected disconnect_tailscale # Connect using auth key (and optionally custom login server) if [ -n "$LOGIN_SERVER" ]; then log_info "Using custom login server: $LOGIN_SERVER" if tailscale up --force-reauth --login-server="$LOGIN_SERVER" --authkey="$AUTH_KEY" --accept-routes --accept-dns; then log_info "Successfully connected to Tailscale!" # Display Tailscale status log_info "Tailscale status:" tailscale status else log_error "Failed to connect to Tailscale" log_error "Please check your login server URL and auth key and try again" exit 1 fi else log_info "Using default Tailscale server" if tailscale up --force-reauth --authkey="$AUTH_KEY" --accept-routes --accept-dns; then log_info "Successfully connected to Tailscale!" # Display Tailscale status log_info "Tailscale status:" tailscale status else log_error "Failed to connect to Tailscale" log_error "Please check your auth key and try again" exit 1 fi fi } # Main execution main() { log_info "Starting Tailscale installation and connection script..." check_root detect_distro if is_tailscale_installed; then log_info "Tailscale is already installed" else install_tailscale fi setup_service validate_login_server validate_auth_key connect_tailscale log_info "Script completed successfully!" } # Run main function main