tailscale-setup.sh
· 21 KiB · Bash
Исходник
#!/bin/bash
#═══════════════════════════════════════════════════════════════════════════════
# Professional Tailscale Setup Script
# Author: Федя Серафиев
# Description: Complete automated Tailscale setup for Proxmox LXC container
# Purpose: Secure access to home network and Docker containers from anywhere
# Version: 2.0
#═══════════════════════════════════════════════════════════════════════════════
set -e
#═══════════════════════════════════════════════════════════════════════════════
# Configuration
#═══════════════════════════════════════════════════════════════════════════════
# Your local network that you want to access remotely
LOCAL_NETWORK="10.110.110.0/24"
# Parameters (can be set via environment variables)
HOSTNAME="${HOSTNAME:-proxmox-vpn}"
EXIT_NODE="${EXIT_NODE:-true}"
SKIP_STEPS="${SKIP_STEPS:-}"
# Logging
LOG_FILE="/var/log/tailscale-setup.log"
exec > >(tee -a "$LOG_FILE") 2>&1
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m'
#═══════════════════════════════════════════════════════════════════════════════
# Helper Functions
#═══════════════════════════════════════════════════════════════════════════════
print_header() {
echo -e "\n${CYAN}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN}$1${NC}"
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}\n"
}
print_success() {
echo -e "${GREEN}✅ $1${NC}"
}
print_error() {
echo -e "${RED}❌ $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_info() {
echo -e "${BLUE}ℹ️ $1${NC}"
}
print_step() {
echo -e "${MAGENTA}➜ $1${NC}"
}
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
check_root() {
if [[ $EUID -ne 0 ]]; then
print_error "Този скрипт трябва да се изпълни като root!"
echo "Използвайте: sudo bash $0"
log_message "ERROR: Script run without root privileges"
exit 1
fi
log_message "Root check passed"
}
check_os() {
print_step "Проверка на операционната система..."
if [[ ! -f /etc/debian_version ]] && [[ ! -f /etc/ubuntu-release ]]; then
print_error "Този скрипт поддържа само Debian/Ubuntu системи"
log_message "ERROR: Unsupported OS detected"
exit 1
fi
OS_VERSION=$(lsb_release -d | cut -f2)
print_success "Поддържана OS: $OS_VERSION"
log_message "OS check passed: $OS_VERSION"
}
check_tun() {
print_step "Проверка на TUN устройството..."
if [ ! -e /dev/net/tun ]; then
print_error "TUN устройството не е налично!"
print_warning "В Proxmox: Container Options → Features → TUN (трябва да е активирано)"
log_message "ERROR: TUN device not available"
exit 1
fi
print_success "TUN устройството е налично"
log_message "TUN device check passed"
}
check_existing_routes() {
print_step "Проверка за съществуващи routes..."
if ip route show table 52 2>/dev/null | grep -q "$LOCAL_NETWORK"; then
print_warning "Route за $LOCAL_NETWORK вече съществува"
log_message "Existing route found for $LOCAL_NETWORK"
return 1
fi
print_success "Няма съществуващи routes за $LOCAL_NETWORK"
log_message "No existing routes found for $LOCAL_NETWORK"
return 0
}
should_skip_step() {
local step=$1
if [[ "$SKIP_STEPS" == *"$step"* ]]; then
log_message "Skipping step: $step"
return 0
fi
return 1
}
#═══════════════════════════════════════════════════════════════════════════════
# Main Installation Functions
#═══════════════════════════════════════════════════════════════════════════════
install_tailscale() {
if should_skip_step "install"; then
print_info "Прескачане на инсталацията на Tailscale"
return
fi
print_header "Инсталиране на Tailscale"
if command -v tailscale &>/dev/null; then
print_info "Tailscale вече е инсталиран"
tailscale version
log_message "Tailscale already installed"
return
fi
print_step "Добавяне на Tailscale repository..."
# Install using official repository (more secure than curl | sh)
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | \
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
print_step "Актуализиране на пакетите и инсталиране на Tailscale..."
apt-get update -qq
apt-get install -y tailscale
if [ $? -eq 0 ]; then
print_success "Tailscale е инсталиран успешно!"
log_message "Tailscale installed successfully"
tailscale version
else
print_error "Грешка при инсталирането на Tailscale"
log_message "ERROR: Tailscale installation failed"
exit 1
fi
}
configure_ip_forwarding() {
if should_skip_step "ip_forwarding"; then
print_info "Прескачане на IP forwarding конфигурацията"
return
fi
print_header "Конфигуриране на IP forwarding"
print_step "Активиране на IP forwarding..."
# Enable IPv4 forwarding (only if not already enabled)
if ! grep -q "net.ipv4.ip_forward = 1" /etc/sysctl.conf; then
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.conf
fi
if ! grep -q "net.ipv6.conf.all.forwarding = 1" /etc/sysctl.conf; then
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.conf
fi
# Apply changes
sysctl -p
print_success "IP forwarding е активирано"
log_message "IP forwarding configured"
}
setup_tailscale() {
if should_skip_step "setup"; then
print_info "Прескачане на Tailscale setup"
return
fi
print_header "Конфигуриране на Tailscale"
print_info "Конфигурационни параметри:"
echo -e " ${CYAN}Hostname:${NC} ${GREEN}$HOSTNAME${NC}"
echo -e " ${CYAN}Subnet:${NC} ${GREEN}$LOCAL_NETWORK${NC}"
echo -e " ${CYAN}Exit Node:${NC} ${GREEN}$EXIT_NODE${NC}"
echo ""
print_info "Сега ще се отвори браузър за автентикация в Tailscale"
print_info "Ако браузърът не се отвори автоматично, копирай линка от терминала"
echo ""
print_step "Стартиране на Tailscale като subnet router..."
print_warning "Важно: Тази машина ще рутира трафик за целия $LOCAL_NETWORK"
echo ""
# Build the command based on parameters
TS_CMD="tailscale up --advertise-routes=$LOCAL_NETWORK --accept-routes --hostname=$HOSTNAME"
if [ "$EXIT_NODE" = "true" ]; then
TS_CMD="$TS_CMD --advertise-exit-node"
fi
log_message "Executing Tailscale setup: $TS_CMD"
# Execute Tailscale setup
if eval "$TS_CMD"; then
print_success "Tailscale е конфигуриран успешно!"
log_message "Tailscale setup completed successfully"
else
print_error "Грешка при конфигурирането на Tailscale"
log_message "ERROR: Tailscale setup failed"
exit 1
fi
}
approve_routes() {
if should_skip_step "approve"; then
print_info "Прескачане на одобрението на routes"
return
fi
print_header "Важна стъпка - одобряване на subnet routes"
echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${YELLOW}ВАЖНО: Трябва да одобриш subnet routes в Tailscale Admin Console!${NC}"
echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}\n"
print_info "Следвай тези стъпки:"
echo -e "${CYAN}1.${NC} Отвори: ${GREEN}https://login.tailscale.com/admin/machines${NC}"
echo -e "${CYAN}2.${NC} Намери устройството ${GREEN}$HOSTNAME${NC}"
echo -e "${CYAN}3.${NC} Кликни на трите точки ${GREEN}(...)${NC} до името"
echo -e "${CYAN}4.${NC} Избери ${GREEN}Edit route settings...${NC}"
echo -e "${CYAN}5.${NC} Активирай ${GREEN}$LOCAL_NETWORK${NC} (subnet routes)"
if [ "$EXIT_NODE" = "true" ]; then
echo -e "${CYAN}6.${NC} Активирай ${GREEN}Use as exit node${NC}"
fi
echo ""
# Check if routes are already approved
if check_existing_routes; then
print_info "Routes все още не са одобрени. Чакам одобрение..."
else
print_success "Routes вече са одобрени!"
return
fi
read -p "Натисни Enter след като завършиш одобрението..."
# Verify routes were approved
if check_existing_routes; then
print_warning "Routes все още не са одобрени. Провери в Admin Console."
read -p "Натисни Enter, когато routes са одобрени, или Ctrl+C за изход..."
fi
print_success "Routes са одобрени"
log_message "Routes approved in Tailscale admin"
}
get_tailscale_info() {
print_header "Информация за Tailscale мрежата"
# Get Tailscale IP
TAILSCALE_IP=$(tailscale ip -4)
TAILSCALE_IP6=$(tailscale ip -6)
echo -e "${CYAN}Tailscale IPv4:${NC} ${GREEN}$TAILSCALE_IP${NC}"
echo -e "${CYAN}Tailscale IPv6:${NC} ${GREEN}$TAILSCALE_IP6${NC}"
echo -e "${CYAN}Hostname:${NC} ${GREEN}$HOSTNAME${NC}"
echo -e "${CYAN}Subnet Routes:${NC} ${GREEN}$LOCAL_NETWORK${NC}"
echo -e "${CYAN}Exit Node:${NC} ${GREEN}$EXIT_NODE${NC}"
echo ""
print_step "Показване на всички устройства в мрежата..."
tailscale status
log_message "Tailscale info displayed - IP: $TAILSCALE_IP"
}
create_management_script() {
print_header "Създаване на management скрипт"
cat > /usr/local/bin/tailscale-info <<'SCRIPT'
#!/bin/bash
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${CYAN}Tailscale Network Information${NC}"
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}\n"
echo -e "${GREEN}Your Tailscale IPs:${NC}"
echo -e " IPv4: $(tailscale ip -4)"
echo -e " IPv6: $(tailscale ip -6)"
echo ""
echo -e "${GREEN}Status:${NC}"
tailscale status
echo ""
echo -e "${GREEN}Advertised Routes:${NC}"
ip route show table 52 2>/dev/null || echo " No routes found"
echo ""
echo -e "${YELLOW}Useful commands:${NC}"
echo -e " ${CYAN}tailscale status${NC} - Show all devices"
echo -e " ${CYAN}tailscale ping <device>${NC} - Ping another device"
echo -e " ${CYAN}tailscale netcheck${NC} - Check connectivity"
echo -e " ${CYAN}tailscale up${NC} - Reconnect"
echo -e " ${CYAN}tailscale down${NC} - Disconnect"
echo -e " ${CYAN}tailscale logout${NC} - Logout"
SCRIPT
chmod +x /usr/local/bin/tailscale-info
print_success "Management скрипт създаден: tailscale-info"
log_message "Management script created: /usr/local/bin/tailscale-info"
}
test_connectivity() {
print_header "Тестване на връзката"
print_step "Проверка на Tailscale connectivity..."
tailscale netcheck
echo ""
# Test if we can ping ourselves
if TAILSCALE_IP=$(tailscale ip -4); then
print_step "Тестване на връзка до себе си ($TAILSCALE_IP)..."
if ping -c 2 -W 1 "$TAILSCALE_IP" &>/dev/null; then
print_success "Успешен ping до собствената Tailscale IP"
else
print_warning "Неуспешен ping до собствената Tailscale IP"
fi
fi
print_info "Tailscale е готов за употреба!"
log_message "Connectivity test completed"
}
print_final_summary() {
print_header "Инсталацията е завършена успешно! 🎉"
TAILSCALE_IP=$(tailscale ip -4)
echo -e "${GREEN}📊 Конфигурация:${NC}\n"
echo -e "${CYAN}Tailscale IP:${NC} ${GREEN}$TAILSCALE_IP${NC}"
echo -e "${CYAN}Subnet Router:${NC} ${GREEN}$LOCAL_NETWORK${NC}"
echo -e "${CYAN}Hostname:${NC} ${GREEN}$HOSTNAME${NC}"
echo -e "${CYAN}Exit Node:${NC} ${GREEN}$EXIT_NODE${NC}"
echo -e "${CYAN}Log File:${NC} ${GREEN}$LOG_FILE${NC}\n"
echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${YELLOW}📱 Следващи стъпки:${NC}\n"
echo -e "${CYAN}1. На телефона/лаптопа:${NC}"
echo -e " • Инсталирай Tailscale app от:"
echo -e " - iOS: ${GREEN}App Store${NC}"
echo -e " - Android: ${GREEN}Google Play${NC}"
echo -e " - Windows/Mac/Linux: ${GREEN}https://tailscale.com/download${NC}"
echo -e " • Логни се със ${GREEN}същия акаунт${NC}\n"
echo -e "${CYAN}2. Достъп до локалната мрежа:${NC}"
echo -e " • От телефона/лаптопа можеш директно да достъпваш:"
echo -e " ${GREEN}10.110.110.x${NC} - всички устройства в локалната мрежа"
echo -e " ${GREEN}$TAILSCALE_IP${NC} - този Proxmox контейнер\n"
echo -e "${CYAN}3. Достъп до Docker контейнери:${NC}"
echo -e " • Ако имаш Docker на ${GREEN}10.110.110.x${NC}"
echo -e " • Директно отваряш: ${GREEN}http://10.110.110.x:port${NC}\n"
if [ "$EXIT_NODE" = "true" ]; then
echo -e "${CYAN}4. Exit Node:${NC}"
echo -e " • За да използваш като VPN за целия интернет трафик:"
echo -e " • В Tailscale app: Settings → ${GREEN}Use exit node → $HOSTNAME${NC}\n"
fi
echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${YELLOW}🔧 Полезни команди:${NC}\n"
echo -e " ${GREEN}tailscale-info${NC} - Показва информация за мрежата"
echo -e " ${GREEN}tailscale status${NC} - Показва всички устройства"
echo -e " ${GREEN}tailscale ping <device>${NC} - Тества връзка до устройство"
echo -e " ${GREEN}tailscale netcheck${NC} - Проверява connectivity"
echo -e " ${GREEN}tailscale up${NC} - Свързва се отново"
echo -e " ${GREEN}tailscale down${NC} - Изключва се от мрежата\n"
echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${YELLOW}💡 Предимства пред OpenVPN:${NC}\n"
echo -e " ${GREEN}✓${NC} Не трябва статично IP"
echo -e " ${GREEN}✓${NC} Не трябва port forwarding"
echo -e " ${GREEN}✓${NC} Автоматично се reconnect-ва"
echo -e " ${GREEN}✓${NC} Работи от всяка мрежа (мобилни данни, WiFi)"
echo -e " ${GREEN}✓${NC} Peer-to-peer връзки (супер бърз)"
echo -e " ${GREEN}✓${NC} Базиран на WireGuard (модерна криптография)"
echo -e " ${GREEN}✓${NC} Безплатен за лична употреба (до 100 устройства)\n"
echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${YELLOW}🌐 Web Console:${NC}"
echo -e " ${GREEN}https://login.tailscale.com/admin${NC}\n"
echo -e "${YELLOW}📝 Лог файл:${NC}"
echo -e " ${GREEN}$LOG_FILE${NC}\n"
print_success "Готово! Enjoi your secure network! 🚀"
log_message "Setup completed successfully - Final IP: $TAILSCALE_IP"
}
print_usage() {
echo -e "${CYAN}Usage:${NC}"
echo -e " ${GREEN}sudo bash $0${NC}"
echo ""
echo -e "${CYAN}Environment variables:${NC}"
echo -e " ${GREEN}HOSTNAME${NC} - Tailscale hostname (default: proxmox-vpn)"
echo -e " ${GREEN}EXIT_NODE${NC} - Enable exit node (default: true)"
echo -e " ${GREEN}SKIP_STEPS${NC} - Skip specific steps (comma-separated)"
echo -e " Available: install, ip_forwarding, setup, approve"
echo ""
echo -e "${CYAN}Examples:${NC}"
echo -e " ${GREEN}sudo HOSTNAME=my-server EXIT_NODE=false bash $0${NC}"
echo -e " ${GREEN}sudo SKIP_STEPS=install,ip_forwarding bash $0${NC}"
echo ""
}
#═══════════════════════════════════════════════════════════════════════════════
# Main Execution
#═══════════════════════════════════════════════════════════════════════════════
main() {
print_header "🚀 Tailscale Professional Setup v2.0"
# Log start of script
log_message "=== Tailscale Setup Script Started ==="
log_message "Parameters - HOSTNAME: $HOSTNAME, EXIT_NODE: $EXIT_NODE, SKIP_STEPS: $SKIP_STEPS"
# Show usage if help requested
if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
print_usage
exit 0
fi
check_root
check_os
check_tun
install_tailscale
configure_ip_forwarding
setup_tailscale
approve_routes
get_tailscale_info
create_management_script
test_connectivity
print_final_summary
}
# Run main function with all arguments
main "$@"
| 1 | #!/bin/bash |
| 2 | |
| 3 | #═══════════════════════════════════════════════════════════════════════════════ |
| 4 | # Professional Tailscale Setup Script |
| 5 | # Author: Федя Серафиев |
| 6 | # Description: Complete automated Tailscale setup for Proxmox LXC container |
| 7 | # Purpose: Secure access to home network and Docker containers from anywhere |
| 8 | # Version: 2.0 |
| 9 | #═══════════════════════════════════════════════════════════════════════════════ |
| 10 | |
| 11 | set -e |
| 12 | |
| 13 | #═══════════════════════════════════════════════════════════════════════════════ |
| 14 | # Configuration |
| 15 | #═══════════════════════════════════════════════════════════════════════════════ |
| 16 | |
| 17 | # Your local network that you want to access remotely |
| 18 | LOCAL_NETWORK="10.110.110.0/24" |
| 19 | |
| 20 | # Parameters (can be set via environment variables) |
| 21 | HOSTNAME="${HOSTNAME:-proxmox-vpn}" |
| 22 | EXIT_NODE="${EXIT_NODE:-true}" |
| 23 | SKIP_STEPS="${SKIP_STEPS:-}" |
| 24 | |
| 25 | # Logging |
| 26 | LOG_FILE="/var/log/tailscale-setup.log" |
| 27 | exec > >(tee -a "$LOG_FILE") 2>&1 |
| 28 | |
| 29 | # Colors |
| 30 | RED='\033[0;31m' |
| 31 | GREEN='\033[0;32m' |
| 32 | YELLOW='\033[1;33m' |
| 33 | BLUE='\033[0;34m' |
| 34 | CYAN='\033[0;36m' |
| 35 | MAGENTA='\033[0;35m' |
| 36 | NC='\033[0m' |
| 37 | |
| 38 | #═══════════════════════════════════════════════════════════════════════════════ |
| 39 | # Helper Functions |
| 40 | #═══════════════════════════════════════════════════════════════════════════════ |
| 41 | |
| 42 | print_header() { |
| 43 | echo -e "\n${CYAN}═══════════════════════════════════════════════════════════════${NC}" |
| 44 | echo -e "${CYAN}$1${NC}" |
| 45 | echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}\n" |
| 46 | } |
| 47 | |
| 48 | print_success() { |
| 49 | echo -e "${GREEN}✅ $1${NC}" |
| 50 | } |
| 51 | |
| 52 | print_error() { |
| 53 | echo -e "${RED}❌ $1${NC}" |
| 54 | } |
| 55 | |
| 56 | print_warning() { |
| 57 | echo -e "${YELLOW}⚠️ $1${NC}" |
| 58 | } |
| 59 | |
| 60 | print_info() { |
| 61 | echo -e "${BLUE}ℹ️ $1${NC}" |
| 62 | } |
| 63 | |
| 64 | print_step() { |
| 65 | echo -e "${MAGENTA}➜ $1${NC}" |
| 66 | } |
| 67 | |
| 68 | log_message() { |
| 69 | echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" |
| 70 | } |
| 71 | |
| 72 | check_root() { |
| 73 | if [[ $EUID -ne 0 ]]; then |
| 74 | print_error "Този скрипт трябва да се изпълни като root!" |
| 75 | echo "Използвайте: sudo bash $0" |
| 76 | log_message "ERROR: Script run without root privileges" |
| 77 | exit 1 |
| 78 | fi |
| 79 | log_message "Root check passed" |
| 80 | } |
| 81 | |
| 82 | check_os() { |
| 83 | print_step "Проверка на операционната система..." |
| 84 | |
| 85 | if [[ ! -f /etc/debian_version ]] && [[ ! -f /etc/ubuntu-release ]]; then |
| 86 | print_error "Този скрипт поддържа само Debian/Ubuntu системи" |
| 87 | log_message "ERROR: Unsupported OS detected" |
| 88 | exit 1 |
| 89 | fi |
| 90 | |
| 91 | OS_VERSION=$(lsb_release -d | cut -f2) |
| 92 | print_success "Поддържана OS: $OS_VERSION" |
| 93 | log_message "OS check passed: $OS_VERSION" |
| 94 | } |
| 95 | |
| 96 | check_tun() { |
| 97 | print_step "Проверка на TUN устройството..." |
| 98 | |
| 99 | if [ ! -e /dev/net/tun ]; then |
| 100 | print_error "TUN устройството не е налично!" |
| 101 | print_warning "В Proxmox: Container Options → Features → TUN (трябва да е активирано)" |
| 102 | log_message "ERROR: TUN device not available" |
| 103 | exit 1 |
| 104 | fi |
| 105 | |
| 106 | print_success "TUN устройството е налично" |
| 107 | log_message "TUN device check passed" |
| 108 | } |
| 109 | |
| 110 | check_existing_routes() { |
| 111 | print_step "Проверка за съществуващи routes..." |
| 112 | |
| 113 | if ip route show table 52 2>/dev/null | grep -q "$LOCAL_NETWORK"; then |
| 114 | print_warning "Route за $LOCAL_NETWORK вече съществува" |
| 115 | log_message "Existing route found for $LOCAL_NETWORK" |
| 116 | return 1 |
| 117 | fi |
| 118 | |
| 119 | print_success "Няма съществуващи routes за $LOCAL_NETWORK" |
| 120 | log_message "No existing routes found for $LOCAL_NETWORK" |
| 121 | return 0 |
| 122 | } |
| 123 | |
| 124 | should_skip_step() { |
| 125 | local step=$1 |
| 126 | if [[ "$SKIP_STEPS" == *"$step"* ]]; then |
| 127 | log_message "Skipping step: $step" |
| 128 | return 0 |
| 129 | fi |
| 130 | return 1 |
| 131 | } |
| 132 | |
| 133 | #═══════════════════════════════════════════════════════════════════════════════ |
| 134 | # Main Installation Functions |
| 135 | #═══════════════════════════════════════════════════════════════════════════════ |
| 136 | |
| 137 | install_tailscale() { |
| 138 | if should_skip_step "install"; then |
| 139 | print_info "Прескачане на инсталацията на Tailscale" |
| 140 | return |
| 141 | fi |
| 142 | |
| 143 | print_header "Инсталиране на Tailscale" |
| 144 | |
| 145 | if command -v tailscale &>/dev/null; then |
| 146 | print_info "Tailscale вече е инсталиран" |
| 147 | tailscale version |
| 148 | log_message "Tailscale already installed" |
| 149 | return |
| 150 | fi |
| 151 | |
| 152 | print_step "Добавяне на Tailscale repository..." |
| 153 | |
| 154 | # Install using official repository (more secure than curl | sh) |
| 155 | curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.noarmor.gpg | \ |
| 156 | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null |
| 157 | |
| 158 | curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/jammy.tailscale-keyring.list | \ |
| 159 | tee /etc/apt/sources.list.d/tailscale.list >/dev/null |
| 160 | |
| 161 | print_step "Актуализиране на пакетите и инсталиране на Tailscale..." |
| 162 | apt-get update -qq |
| 163 | apt-get install -y tailscale |
| 164 | |
| 165 | if [ $? -eq 0 ]; then |
| 166 | print_success "Tailscale е инсталиран успешно!" |
| 167 | log_message "Tailscale installed successfully" |
| 168 | tailscale version |
| 169 | else |
| 170 | print_error "Грешка при инсталирането на Tailscale" |
| 171 | log_message "ERROR: Tailscale installation failed" |
| 172 | exit 1 |
| 173 | fi |
| 174 | } |
| 175 | |
| 176 | configure_ip_forwarding() { |
| 177 | if should_skip_step "ip_forwarding"; then |
| 178 | print_info "Прескачане на IP forwarding конфигурацията" |
| 179 | return |
| 180 | fi |
| 181 | |
| 182 | print_header "Конфигуриране на IP forwarding" |
| 183 | |
| 184 | print_step "Активиране на IP forwarding..." |
| 185 | |
| 186 | # Enable IPv4 forwarding (only if not already enabled) |
| 187 | if ! grep -q "net.ipv4.ip_forward = 1" /etc/sysctl.conf; then |
| 188 | echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.conf |
| 189 | fi |
| 190 | |
| 191 | if ! grep -q "net.ipv6.conf.all.forwarding = 1" /etc/sysctl.conf; then |
| 192 | echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.conf |
| 193 | fi |
| 194 | |
| 195 | # Apply changes |
| 196 | sysctl -p |
| 197 | |
| 198 | print_success "IP forwarding е активирано" |
| 199 | log_message "IP forwarding configured" |
| 200 | } |
| 201 | |
| 202 | setup_tailscale() { |
| 203 | if should_skip_step "setup"; then |
| 204 | print_info "Прескачане на Tailscale setup" |
| 205 | return |
| 206 | fi |
| 207 | |
| 208 | print_header "Конфигуриране на Tailscale" |
| 209 | |
| 210 | print_info "Конфигурационни параметри:" |
| 211 | echo -e " ${CYAN}Hostname:${NC} ${GREEN}$HOSTNAME${NC}" |
| 212 | echo -e " ${CYAN}Subnet:${NC} ${GREEN}$LOCAL_NETWORK${NC}" |
| 213 | echo -e " ${CYAN}Exit Node:${NC} ${GREEN}$EXIT_NODE${NC}" |
| 214 | echo "" |
| 215 | |
| 216 | print_info "Сега ще се отвори браузър за автентикация в Tailscale" |
| 217 | print_info "Ако браузърът не се отвори автоматично, копирай линка от терминала" |
| 218 | echo "" |
| 219 | |
| 220 | print_step "Стартиране на Tailscale като subnet router..." |
| 221 | print_warning "Важно: Тази машина ще рутира трафик за целия $LOCAL_NETWORK" |
| 222 | echo "" |
| 223 | |
| 224 | # Build the command based on parameters |
| 225 | TS_CMD="tailscale up --advertise-routes=$LOCAL_NETWORK --accept-routes --hostname=$HOSTNAME" |
| 226 | |
| 227 | if [ "$EXIT_NODE" = "true" ]; then |
| 228 | TS_CMD="$TS_CMD --advertise-exit-node" |
| 229 | fi |
| 230 | |
| 231 | log_message "Executing Tailscale setup: $TS_CMD" |
| 232 | |
| 233 | # Execute Tailscale setup |
| 234 | if eval "$TS_CMD"; then |
| 235 | print_success "Tailscale е конфигуриран успешно!" |
| 236 | log_message "Tailscale setup completed successfully" |
| 237 | else |
| 238 | print_error "Грешка при конфигурирането на Tailscale" |
| 239 | log_message "ERROR: Tailscale setup failed" |
| 240 | exit 1 |
| 241 | fi |
| 242 | } |
| 243 | |
| 244 | approve_routes() { |
| 245 | if should_skip_step "approve"; then |
| 246 | print_info "Прескачане на одобрението на routes" |
| 247 | return |
| 248 | fi |
| 249 | |
| 250 | print_header "Важна стъпка - одобряване на subnet routes" |
| 251 | |
| 252 | echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" |
| 253 | echo -e "${YELLOW}ВАЖНО: Трябва да одобриш subnet routes в Tailscale Admin Console!${NC}" |
| 254 | echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}\n" |
| 255 | |
| 256 | print_info "Следвай тези стъпки:" |
| 257 | echo -e "${CYAN}1.${NC} Отвори: ${GREEN}https://login.tailscale.com/admin/machines${NC}" |
| 258 | echo -e "${CYAN}2.${NC} Намери устройството ${GREEN}$HOSTNAME${NC}" |
| 259 | echo -e "${CYAN}3.${NC} Кликни на трите точки ${GREEN}(...)${NC} до името" |
| 260 | echo -e "${CYAN}4.${NC} Избери ${GREEN}Edit route settings...${NC}" |
| 261 | echo -e "${CYAN}5.${NC} Активирай ${GREEN}$LOCAL_NETWORK${NC} (subnet routes)" |
| 262 | |
| 263 | if [ "$EXIT_NODE" = "true" ]; then |
| 264 | echo -e "${CYAN}6.${NC} Активирай ${GREEN}Use as exit node${NC}" |
| 265 | fi |
| 266 | |
| 267 | echo "" |
| 268 | |
| 269 | # Check if routes are already approved |
| 270 | if check_existing_routes; then |
| 271 | print_info "Routes все още не са одобрени. Чакам одобрение..." |
| 272 | else |
| 273 | print_success "Routes вече са одобрени!" |
| 274 | return |
| 275 | fi |
| 276 | |
| 277 | read -p "Натисни Enter след като завършиш одобрението..." |
| 278 | |
| 279 | # Verify routes were approved |
| 280 | if check_existing_routes; then |
| 281 | print_warning "Routes все още не са одобрени. Провери в Admin Console." |
| 282 | read -p "Натисни Enter, когато routes са одобрени, или Ctrl+C за изход..." |
| 283 | fi |
| 284 | |
| 285 | print_success "Routes са одобрени" |
| 286 | log_message "Routes approved in Tailscale admin" |
| 287 | } |
| 288 | |
| 289 | get_tailscale_info() { |
| 290 | print_header "Информация за Tailscale мрежата" |
| 291 | |
| 292 | # Get Tailscale IP |
| 293 | TAILSCALE_IP=$(tailscale ip -4) |
| 294 | TAILSCALE_IP6=$(tailscale ip -6) |
| 295 | |
| 296 | echo -e "${CYAN}Tailscale IPv4:${NC} ${GREEN}$TAILSCALE_IP${NC}" |
| 297 | echo -e "${CYAN}Tailscale IPv6:${NC} ${GREEN}$TAILSCALE_IP6${NC}" |
| 298 | echo -e "${CYAN}Hostname:${NC} ${GREEN}$HOSTNAME${NC}" |
| 299 | echo -e "${CYAN}Subnet Routes:${NC} ${GREEN}$LOCAL_NETWORK${NC}" |
| 300 | echo -e "${CYAN}Exit Node:${NC} ${GREEN}$EXIT_NODE${NC}" |
| 301 | echo "" |
| 302 | |
| 303 | print_step "Показване на всички устройства в мрежата..." |
| 304 | tailscale status |
| 305 | |
| 306 | log_message "Tailscale info displayed - IP: $TAILSCALE_IP" |
| 307 | } |
| 308 | |
| 309 | create_management_script() { |
| 310 | print_header "Създаване на management скрипт" |
| 311 | |
| 312 | cat > /usr/local/bin/tailscale-info <<'SCRIPT' |
| 313 | #!/bin/bash |
| 314 | |
| 315 | GREEN='\033[0;32m' |
| 316 | CYAN='\033[0;36m' |
| 317 | YELLOW='\033[1;33m' |
| 318 | NC='\033[0m' |
| 319 | |
| 320 | echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}" |
| 321 | echo -e "${CYAN}Tailscale Network Information${NC}" |
| 322 | echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}\n" |
| 323 | |
| 324 | echo -e "${GREEN}Your Tailscale IPs:${NC}" |
| 325 | echo -e " IPv4: $(tailscale ip -4)" |
| 326 | echo -e " IPv6: $(tailscale ip -6)" |
| 327 | echo "" |
| 328 | |
| 329 | echo -e "${GREEN}Status:${NC}" |
| 330 | tailscale status |
| 331 | echo "" |
| 332 | |
| 333 | echo -e "${GREEN}Advertised Routes:${NC}" |
| 334 | ip route show table 52 2>/dev/null || echo " No routes found" |
| 335 | echo "" |
| 336 | |
| 337 | echo -e "${YELLOW}Useful commands:${NC}" |
| 338 | echo -e " ${CYAN}tailscale status${NC} - Show all devices" |
| 339 | echo -e " ${CYAN}tailscale ping <device>${NC} - Ping another device" |
| 340 | echo -e " ${CYAN}tailscale netcheck${NC} - Check connectivity" |
| 341 | echo -e " ${CYAN}tailscale up${NC} - Reconnect" |
| 342 | echo -e " ${CYAN}tailscale down${NC} - Disconnect" |
| 343 | echo -e " ${CYAN}tailscale logout${NC} - Logout" |
| 344 | SCRIPT |
| 345 | |
| 346 | chmod +x /usr/local/bin/tailscale-info |
| 347 | |
| 348 | print_success "Management скрипт създаден: tailscale-info" |
| 349 | log_message "Management script created: /usr/local/bin/tailscale-info" |
| 350 | } |
| 351 | |
| 352 | test_connectivity() { |
| 353 | print_header "Тестване на връзката" |
| 354 | |
| 355 | print_step "Проверка на Tailscale connectivity..." |
| 356 | tailscale netcheck |
| 357 | |
| 358 | echo "" |
| 359 | |
| 360 | # Test if we can ping ourselves |
| 361 | if TAILSCALE_IP=$(tailscale ip -4); then |
| 362 | print_step "Тестване на връзка до себе си ($TAILSCALE_IP)..." |
| 363 | if ping -c 2 -W 1 "$TAILSCALE_IP" &>/dev/null; then |
| 364 | print_success "Успешен ping до собствената Tailscale IP" |
| 365 | else |
| 366 | print_warning "Неуспешен ping до собствената Tailscale IP" |
| 367 | fi |
| 368 | fi |
| 369 | |
| 370 | print_info "Tailscale е готов за употреба!" |
| 371 | log_message "Connectivity test completed" |
| 372 | } |
| 373 | |
| 374 | print_final_summary() { |
| 375 | print_header "Инсталацията е завършена успешно! 🎉" |
| 376 | |
| 377 | TAILSCALE_IP=$(tailscale ip -4) |
| 378 | |
| 379 | echo -e "${GREEN}📊 Конфигурация:${NC}\n" |
| 380 | echo -e "${CYAN}Tailscale IP:${NC} ${GREEN}$TAILSCALE_IP${NC}" |
| 381 | echo -e "${CYAN}Subnet Router:${NC} ${GREEN}$LOCAL_NETWORK${NC}" |
| 382 | echo -e "${CYAN}Hostname:${NC} ${GREEN}$HOSTNAME${NC}" |
| 383 | echo -e "${CYAN}Exit Node:${NC} ${GREEN}$EXIT_NODE${NC}" |
| 384 | echo -e "${CYAN}Log File:${NC} ${GREEN}$LOG_FILE${NC}\n" |
| 385 | |
| 386 | echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" |
| 387 | echo -e "${YELLOW}📱 Следващи стъпки:${NC}\n" |
| 388 | |
| 389 | echo -e "${CYAN}1. На телефона/лаптопа:${NC}" |
| 390 | echo -e " • Инсталирай Tailscale app от:" |
| 391 | echo -e " - iOS: ${GREEN}App Store${NC}" |
| 392 | echo -e " - Android: ${GREEN}Google Play${NC}" |
| 393 | echo -e " - Windows/Mac/Linux: ${GREEN}https://tailscale.com/download${NC}" |
| 394 | echo -e " • Логни се със ${GREEN}същия акаунт${NC}\n" |
| 395 | |
| 396 | echo -e "${CYAN}2. Достъп до локалната мрежа:${NC}" |
| 397 | echo -e " • От телефона/лаптопа можеш директно да достъпваш:" |
| 398 | echo -e " ${GREEN}10.110.110.x${NC} - всички устройства в локалната мрежа" |
| 399 | echo -e " ${GREEN}$TAILSCALE_IP${NC} - този Proxmox контейнер\n" |
| 400 | |
| 401 | echo -e "${CYAN}3. Достъп до Docker контейнери:${NC}" |
| 402 | echo -e " • Ако имаш Docker на ${GREEN}10.110.110.x${NC}" |
| 403 | echo -e " • Директно отваряш: ${GREEN}http://10.110.110.x:port${NC}\n" |
| 404 | |
| 405 | if [ "$EXIT_NODE" = "true" ]; then |
| 406 | echo -e "${CYAN}4. Exit Node:${NC}" |
| 407 | echo -e " • За да използваш като VPN за целия интернет трафик:" |
| 408 | echo -e " • В Tailscale app: Settings → ${GREEN}Use exit node → $HOSTNAME${NC}\n" |
| 409 | fi |
| 410 | |
| 411 | echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" |
| 412 | echo -e "${YELLOW}🔧 Полезни команди:${NC}\n" |
| 413 | echo -e " ${GREEN}tailscale-info${NC} - Показва информация за мрежата" |
| 414 | echo -e " ${GREEN}tailscale status${NC} - Показва всички устройства" |
| 415 | echo -e " ${GREEN}tailscale ping <device>${NC} - Тества връзка до устройство" |
| 416 | echo -e " ${GREEN}tailscale netcheck${NC} - Проверява connectivity" |
| 417 | echo -e " ${GREEN}tailscale up${NC} - Свързва се отново" |
| 418 | echo -e " ${GREEN}tailscale down${NC} - Изключва се от мрежата\n" |
| 419 | |
| 420 | echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" |
| 421 | echo -e "${YELLOW}💡 Предимства пред OpenVPN:${NC}\n" |
| 422 | echo -e " ${GREEN}✓${NC} Не трябва статично IP" |
| 423 | echo -e " ${GREEN}✓${NC} Не трябва port forwarding" |
| 424 | echo -e " ${GREEN}✓${NC} Автоматично се reconnect-ва" |
| 425 | echo -e " ${GREEN}✓${NC} Работи от всяка мрежа (мобилни данни, WiFi)" |
| 426 | echo -e " ${GREEN}✓${NC} Peer-to-peer връзки (супер бърз)" |
| 427 | echo -e " ${GREEN}✓${NC} Базиран на WireGuard (модерна криптография)" |
| 428 | echo -e " ${GREEN}✓${NC} Безплатен за лична употреба (до 100 устройства)\n" |
| 429 | |
| 430 | echo -e "${YELLOW}═══════════════════════════════════════════════════════════════${NC}" |
| 431 | echo -e "${YELLOW}🌐 Web Console:${NC}" |
| 432 | echo -e " ${GREEN}https://login.tailscale.com/admin${NC}\n" |
| 433 | |
| 434 | echo -e "${YELLOW}📝 Лог файл:${NC}" |
| 435 | echo -e " ${GREEN}$LOG_FILE${NC}\n" |
| 436 | |
| 437 | print_success "Готово! Enjoi your secure network! 🚀" |
| 438 | log_message "Setup completed successfully - Final IP: $TAILSCALE_IP" |
| 439 | } |
| 440 | |
| 441 | print_usage() { |
| 442 | echo -e "${CYAN}Usage:${NC}" |
| 443 | echo -e " ${GREEN}sudo bash $0${NC}" |
| 444 | echo "" |
| 445 | echo -e "${CYAN}Environment variables:${NC}" |
| 446 | echo -e " ${GREEN}HOSTNAME${NC} - Tailscale hostname (default: proxmox-vpn)" |
| 447 | echo -e " ${GREEN}EXIT_NODE${NC} - Enable exit node (default: true)" |
| 448 | echo -e " ${GREEN}SKIP_STEPS${NC} - Skip specific steps (comma-separated)" |
| 449 | echo -e " Available: install, ip_forwarding, setup, approve" |
| 450 | echo "" |
| 451 | echo -e "${CYAN}Examples:${NC}" |
| 452 | echo -e " ${GREEN}sudo HOSTNAME=my-server EXIT_NODE=false bash $0${NC}" |
| 453 | echo -e " ${GREEN}sudo SKIP_STEPS=install,ip_forwarding bash $0${NC}" |
| 454 | echo "" |
| 455 | } |
| 456 | |
| 457 | #═══════════════════════════════════════════════════════════════════════════════ |
| 458 | # Main Execution |
| 459 | #═══════════════════════════════════════════════════════════════════════════════ |
| 460 | |
| 461 | main() { |
| 462 | print_header "🚀 Tailscale Professional Setup v2.0" |
| 463 | |
| 464 | # Log start of script |
| 465 | log_message "=== Tailscale Setup Script Started ===" |
| 466 | log_message "Parameters - HOSTNAME: $HOSTNAME, EXIT_NODE: $EXIT_NODE, SKIP_STEPS: $SKIP_STEPS" |
| 467 | |
| 468 | # Show usage if help requested |
| 469 | if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then |
| 470 | print_usage |
| 471 | exit 0 |
| 472 | fi |
| 473 | |
| 474 | check_root |
| 475 | check_os |
| 476 | check_tun |
| 477 | |
| 478 | install_tailscale |
| 479 | configure_ip_forwarding |
| 480 | setup_tailscale |
| 481 | approve_routes |
| 482 | get_tailscale_info |
| 483 | create_management_script |
| 484 | test_connectivity |
| 485 | |
| 486 | print_final_summary |
| 487 | } |
| 488 | |
| 489 | # Run main function with all arguments |
| 490 | main "$@" |