- Organized 252 files across project - Root directory: 187 → 2 files (98.9% reduction) - Moved configuration guides to docs/04-configuration/ - Moved troubleshooting guides to docs/09-troubleshooting/ - Moved quick start guides to docs/01-getting-started/ - Moved reports to reports/ directory - Archived temporary files - Generated comprehensive reports and documentation - Created maintenance scripts and guides All files organized according to established standards.
395 lines
15 KiB
Bash
Executable File
395 lines
15 KiB
Bash
Executable File
#!/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 ""
|
|
|