#!/bin/bash set -euo pipefail # ============================================================ # Jefflix VPN Setup Script # Run this on the Netcup RS 8000 server (ssh netcup) # ============================================================ echo "========================================" echo " Jefflix VPN Setup (Headscale/Tailscale)" echo "========================================" echo "" # --- Phase 1: Backups --- echo "[Phase 1] Creating backups..." cp /root/cloudflared/config.yml /root/cloudflared/config.yml.backup-jefflix-vpn cp /opt/apps/headscale-deploy/config/config.yaml /opt/apps/headscale-deploy/config/config.yaml.backup-jefflix-vpn cp -r /root/traefik/config/ /root/traefik/config-backup-jefflix-vpn/ 2>/dev/null || true echo " ✓ Backups created" # --- Phase 1b: Create Headscale users --- echo "" echo "[Phase 1b] Creating Headscale users..." docker exec headscale headscale users create server 2>/dev/null || echo " (user 'server' already exists)" docker exec headscale headscale users create jefflix 2>/dev/null || echo " (user 'jefflix' already exists)" echo " ✓ Users ready" # --- Phase 2: Install Tailscale --- echo "" echo "[Phase 2] Installing Tailscale..." if command -v tailscale &>/dev/null; then echo " Tailscale already installed: $(tailscale version)" else curl -fsSL https://tailscale.com/install.sh | sh echo " ✓ Tailscale installed" fi # Generate pre-auth key and join tailnet echo "" echo " Generating pre-auth key..." PREAUTH_KEY=$(docker exec headscale headscale preauthkeys create --user server --reusable=false --expiration 1h 2>&1 | tail -1) echo " Pre-auth key: $PREAUTH_KEY" echo "" echo " Joining tailnet..." tailscale up \ --login-server=https://vpn.jeffemmett.com \ --authkey="$PREAUTH_KEY" \ --hostname=netcup-rs8000 \ --accept-dns=false # Get the Tailscale IP TAILSCALE_IP=$(tailscale ip -4) echo " ✓ Joined tailnet with IP: $TAILSCALE_IP" # --- Phase 3: Deploy CoreDNS --- echo "" echo "[Phase 3] Deploying CoreDNS for *.jefflix.lol..." mkdir -p /opt/apps/jefflix-dns # Write Corefile with the actual Tailscale IP cat > /opt/apps/jefflix-dns/Corefile < /opt/apps/jefflix-dns/docker-compose.yml </dev/null || echo "FAILED") if [ "$DIG_RESULT" = "$TAILSCALE_IP" ]; then echo " ✓ DNS test passed: movies.jefflix.lol -> $TAILSCALE_IP" else echo " ⚠ DNS test returned: $DIG_RESULT (expected $TAILSCALE_IP)" echo " Check CoreDNS logs: docker logs jefflix-dns" fi # --- Phase 4: Configure Headscale split DNS --- echo "" echo "[Phase 4] Configuring Headscale split DNS..." HEADSCALE_CONFIG="/opt/apps/headscale-deploy/config/config.yaml" # Check if split DNS is already configured if grep -q "jefflix.lol" "$HEADSCALE_CONFIG"; then echo " Split DNS for jefflix.lol already in config, skipping" else # Add split DNS section to the nameservers block # This uses sed to add the split DNS config after the global nameservers sed -i '/nameservers:/,/^[^ ]/ { /global:/,/^ [^ ]/ { /- 1.0.0.1/a\ split:\n jefflix.lol:\n - '"${TAILSCALE_IP}"' } }' "$HEADSCALE_CONFIG" echo " ✓ Split DNS added to Headscale config" fi # Restart Headscale cd /opt/apps/headscale-deploy && docker compose restart headscale echo " ✓ Headscale restarted" sleep 3 # Verify Headscale is healthy docker exec headscale headscale nodes list >/dev/null 2>&1 && echo " ✓ Headscale healthy" || echo " ⚠ Headscale may need attention" echo "" echo "========================================" echo " Setup Complete (Phases 1-4)" echo "========================================" echo "" echo "Server Tailscale IP: $TAILSCALE_IP" echo "CoreDNS: running on $TAILSCALE_IP:53" echo "Split DNS: jefflix.lol -> $TAILSCALE_IP" echo "" echo "NEXT STEPS:" echo " 1. Connect YOUR device to the tailnet and test:" echo " tailscale up --login-server=https://vpn.jeffemmett.com" echo " dig movies.jefflix.lol (should return $TAILSCALE_IP)" echo " curl http://movies.jefflix.lol (should return Jellyfin)" echo "" echo " 2. Once confirmed working, run cutover.sh to remove public access" echo " 3. Then onboard users with pre-auth keys" echo ""