#!/usr/bin/env bash # Fix All Infrastructure Issues # Automates fixes for: DNS records, duplicate cleanup, tunnel configuration instructions # # Usage: ./scripts/fix-all-infrastructure-issues.sh set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" ENV_FILE="$PROJECT_ROOT/.env" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; } log_error() { echo -e "${RED}[✗]${NC} $1"; } # Tunnel ID from current configuration TUNNEL_ID="10ab22da-8ea3-4e2e-a896-27ece2211a05" TUNNEL_TARGET="${TUNNEL_ID}.cfargotunnel.com" DOMAIN="d-bis.org" CENTRAL_NGINX_IP="192.168.11.21" CENTRAL_NGINX_PORT="80" echo "" log_info "═══════════════════════════════════════════════════════════" log_info " FIXING ALL INFRASTRUCTURE ISSUES" log_info "═══════════════════════════════════════════════════════════" echo "" # Check for .env file if [ ! -f "$ENV_FILE" ]; then log_error ".env file not found at: $ENV_FILE" log_info "Please create .env file with Cloudflare credentials:" log_info " CLOUDFLARE_API_TOKEN=your-token" log_info " OR" log_info " CLOUDFLARE_API_KEY=your-key" log_info " CLOUDFLARE_EMAIL=your-email" log_info "" log_info "See: scripts/get-cloudflare-api-key.md for instructions" exit 1 fi # Source .env file source "$ENV_FILE" # Determine authentication method AUTH_HEADERS=() if [ -n "${CLOUDFLARE_API_TOKEN:-}" ]; then AUTH_HEADERS=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN") log_success "Using API Token authentication" elif [ -n "${CLOUDFLARE_API_KEY:-}" ] && [ -n "${CLOUDFLARE_EMAIL:-}" ]; then AUTH_HEADERS=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY") log_success "Using API Key authentication" else log_error "No Cloudflare credentials found in .env" exit 1 fi # Get Zone ID log_info "Getting Cloudflare Zone ID for $DOMAIN..." ZONE_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \ "${AUTH_HEADERS[@]}" \ -H "Content-Type: application/json") ZONE_ID=$(echo "$ZONE_RESPONSE" | jq -r '.result[0].id // empty' 2>/dev/null || echo "") if [ -z "$ZONE_ID" ] || [ "$ZONE_ID" = "null" ]; then log_error "Failed to get zone ID for $DOMAIN" echo "$ZONE_RESPONSE" | jq '.' 2>/dev/null || echo "$ZONE_RESPONSE" exit 1 fi log_success "Zone ID: $ZONE_ID" # Cloudflare API function cloudflare_api() { local method=$1 local endpoint=$2 local data=${3:-} if [ -n "$data" ]; then curl -s -X "$method" \ "https://api.cloudflare.com/client/v4/$endpoint" \ "${AUTH_HEADERS[@]}" \ -H "Content-Type: application/json" \ -d "$data" else curl -s -X "$method" \ "https://api.cloudflare.com/client/v4/$endpoint" \ "${AUTH_HEADERS[@]}" \ -H "Content-Type: application/json" fi } # Check if DNS record exists record_exists() { local record_type=$1 local record_name=$2 local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=$record_type&name=$record_name") echo "$response" | jq -e '.result | length > 0' > /dev/null 2>&1 } # Get DNS record ID get_record_id() { local record_type=$1 local record_name=$2 local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=$record_type&name=$record_name") echo "$response" | jq -r '.result[0].id // empty' } # Get all record IDs for a name (for duplicates) get_all_record_ids() { local record_type=$1 local record_name=$2 local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=$record_type&name=$record_name") echo "$response" | jq -r '.result[].id' } # Create or update DNS record create_or_update_dns() { local record_type=$1 local record_name=$2 local record_content=$3 local proxied=${4:-true} if record_exists "$record_type" "$record_name"; then log_info "Updating DNS record: $record_name ($record_type) → $record_content" local record_id=$(get_record_id "$record_type" "$record_name") local data=$(jq -n \ --arg type "$record_type" \ --arg name "$record_name" \ --arg content "$record_content" \ --argjson proxied "$proxied" \ '{ type: $type, name: $name, content: $content, ttl: 1, proxied: $proxied }') local response=$(cloudflare_api "PUT" "zones/$ZONE_ID/dns_records/$record_id" "$data") if echo "$response" | jq -e '.success' > /dev/null; then log_success "DNS record updated: $record_name" else log_error "Failed to update DNS record: $record_name" echo "$response" | jq -r '.errors[0].message' 2>/dev/null || echo "$response" return 1 fi else log_info "Creating DNS record: $record_name ($record_type) → $record_content" local data=$(jq -n \ --arg type "$record_type" \ --arg name "$record_name" \ --arg content "$record_content" \ --argjson proxied "$proxied" \ '{ type: $type, name: $name, content: $content, ttl: 1, proxied: $proxied }') local response=$(cloudflare_api "POST" "zones/$ZONE_ID/dns_records" "$data") if echo "$response" | jq -e '.success' > /dev/null; then log_success "DNS record created: $record_name" else log_error "Failed to create DNS record: $record_name" echo "$response" | jq -r '.errors[0].message' 2>/dev/null || echo "$response" return 1 fi fi } # Delete DNS record delete_dns_record() { local record_id=$1 local record_name=$2 log_info "Deleting DNS record: $record_name (ID: $record_id)" local response=$(cloudflare_api "DELETE" "zones/$ZONE_ID/dns_records/$record_id") if echo "$response" | jq -e '.success' > /dev/null; then log_success "DNS record deleted: $record_name" else log_error "Failed to delete DNS record: $record_name" echo "$response" | jq -r '.errors[0].message' 2>/dev/null || echo "$response" return 1 fi } # Remove duplicate A records (keep first, delete rest) remove_duplicate_a_records() { local record_name=$1 log_info "Checking for duplicate A records: $record_name" local record_ids=($(get_all_record_ids "A" "$record_name")) if [ ${#record_ids[@]} -gt 1 ]; then log_warn "Found ${#record_ids[@]} A records for $record_name" # Get all records to see which IP to keep local response=$(cloudflare_api "GET" "zones/$ZONE_ID/dns_records?type=A&name=$record_name") local records=$(echo "$response" | jq -r '.result[] | "\(.id)|\(.content)"') # Keep the first record, delete the rest local first=true while IFS='|' read -r record_id content; do if [ "$first" = true ]; then log_info "Keeping A record: $record_name → $content (ID: $record_id)" first=false else delete_dns_record "$record_id" "$record_name → $content" fi done <<< "$records" else log_success "No duplicates found for $record_name" fi } echo "" log_info "═══════════════════════════════════════════════════════════" log_info " STEP 1: CREATE MISSING DNS CNAME RECORDS" log_info "═══════════════════════════════════════════════════════════" echo "" # Missing DNS CNAME records to create declare -a MISSING_DNS=( "rpc-http-pub.d-bis.org" "rpc-ws-pub.d-bis.org" "rpc-http-prv.d-bis.org" "rpc-ws-prv.d-bis.org" "dbis-admin.d-bis.org" "dbis-api.d-bis.org" "dbis-api-2.d-bis.org" "mim4u.org" "www.mim4u.org" ) for domain in "${MISSING_DNS[@]}"; do create_or_update_dns "CNAME" "$domain" "$TUNNEL_TARGET" true sleep 0.5 # Rate limiting done echo "" log_info "═══════════════════════════════════════════════════════════" log_info " STEP 2: REMOVE DUPLICATE DNS A RECORDS" log_info "═══════════════════════════════════════════════════════════" echo "" # Domains with duplicate A records declare -a DUPLICATE_DOMAINS=( "besu.d-bis.org" "blockscout.d-bis.org" "explorer.d-bis.org" "d-bis.org" ) for domain in "${DUPLICATE_DOMAINS[@]}"; do remove_duplicate_a_records "$domain" sleep 0.5 # Rate limiting done echo "" log_info "═══════════════════════════════════════════════════════════" log_info " STEP 3: TUNNEL CONFIGURATION INSTRUCTIONS" log_info "═══════════════════════════════════════════════════════════" echo "" log_warn "Tunnel configuration must be done manually in Cloudflare dashboard" log_info "" log_info "Tunnel: rpc-http-pub.d-bis.org (ID: $TUNNEL_ID)" log_info "Status: Currently DOWN - needs configuration" log_info "" log_info "Action Required:" log_info "1. Go to: https://one.dash.cloudflare.com/" log_info "2. Navigate to: Zero Trust → Networks → Tunnels" log_info "3. Click on: rpc-http-pub.d-bis.org" log_info "4. Click: Configure → Public Hostnames" log_info "5. Update all HTTP endpoints to route to: http://${CENTRAL_NGINX_IP}:${CENTRAL_NGINX_PORT}" log_info "" log_info "HTTP Endpoints (route to central Nginx):" for domain in "explorer.d-bis.org" "rpc-http-pub.d-bis.org" "rpc-http-prv.d-bis.org" \ "dbis-admin.d-bis.org" "dbis-api.d-bis.org" "dbis-api-2.d-bis.org" \ "mim4u.org" "www.mim4u.org"; do log_info " - $domain → http://${CENTRAL_NGINX_IP}:${CENTRAL_NGINX_PORT}" done log_info "" log_info "WebSocket Endpoints (keep direct routing):" log_info " - rpc-ws-pub.d-bis.org → https://192.168.11.252:443" log_info " - rpc-ws-prv.d-bis.org → https://192.168.11.251:443" log_info "" echo "" log_info "═══════════════════════════════════════════════════════════" log_info " STEP 4: VERIFY NETWORK CONNECTIVITY" log_info "═══════════════════════════════════════════════════════════" echo "" # Test connectivity log_info "Testing network connectivity..." # Test pve2 → ml110 if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "ping -c 1 -W 2 192.168.11.10 >/dev/null 2>&1"; then log_success "Network: pve2 (192.168.11.12) → ml110 (192.168.11.10) ✓" else log_error "Network: pve2 (192.168.11.12) → ml110 (192.168.11.10) ✗" fi # Test central Nginx → RPC nodes if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.250:443/health >/dev/null 2>&1 || pct exec 105 -- curl -s -m 2 -k https://192.168.11.250:443/health >/dev/null 2>&1"; then log_success "Network: Central Nginx → RPC-1 (192.168.11.250) ✓" else log_warn "Network: Central Nginx → RPC-1 (192.168.11.250) - May need verification" fi if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 -k https://192.168.11.251:443/health >/dev/null 2>&1"; then log_success "Network: Central Nginx → RPC-2 (192.168.11.251) ✓" else log_warn "Network: Central Nginx → RPC-2 (192.168.11.251) - May need verification" fi if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 -k https://192.168.11.252:443/health >/dev/null 2>&1"; then log_success "Network: Central Nginx → RPC-3 (192.168.11.252) ✓" else log_warn "Network: Central Nginx → RPC-3 (192.168.11.252) - May need verification" fi # Test central Nginx → DBIS services if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.130:80 >/dev/null 2>&1"; then log_success "Network: Central Nginx → DBIS Frontend (192.168.11.130) ✓" else log_warn "Network: Central Nginx → DBIS Frontend (192.168.11.130) - May need verification" fi if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.150:3000/health >/dev/null 2>&1"; then log_success "Network: Central Nginx → DBIS API (192.168.11.150) ✓" else log_warn "Network: Central Nginx → DBIS API (192.168.11.150) - May need verification" fi # Test central Nginx → Blockscout if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.140:80/health >/dev/null 2>&1"; then log_success "Network: Central Nginx → Blockscout (192.168.11.140) ✓" else log_warn "Network: Central Nginx → Blockscout (192.168.11.140) - May need verification" fi # Test central Nginx → MIM if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.12 "pct exec 105 -- curl -s -m 2 http://192.168.11.19:80 >/dev/null 2>&1"; then log_success "Network: Central Nginx → MIM (192.168.11.19) ✓" else log_warn "Network: Central Nginx → MIM (192.168.11.19) - May need verification" fi echo "" log_info "═══════════════════════════════════════════════════════════" log_info " SUMMARY" log_info "═══════════════════════════════════════════════════════════" echo "" log_success "DNS CNAME records created/updated: ${#MISSING_DNS[@]}" log_success "Duplicate A records cleaned: ${#DUPLICATE_DOMAINS[@]}" log_warn "Tunnel configuration: Manual action required (see instructions above)" echo "" log_info "Next Steps:" log_info "1. ✅ DNS records updated" log_info "2. ⏳ Update Cloudflare tunnel configuration (manual)" log_info "3. ⏳ Wait 1-2 minutes for DNS propagation" log_info "4. ⏳ Test all endpoints" echo "" log_info "Test commands:" log_info " curl https://rpc-http-pub.d-bis.org -X POST -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":1}'" log_info " curl https://explorer.d-bis.org/api/v2/stats" log_info " curl https://dbis-admin.d-bis.org" log_info " curl https://mim4u.org" echo ""