#!/usr/bin/env bash # Complete Cloudflare configuration for Blockscout Explorer # Attempts API configuration, falls back to manual instructions set -euo pipefail DOMAIN="${DOMAIN:-d-bis.org}" EXPLORER_DOMAIN="explorer.d-bis.org" EXPLORER_IP="${EXPLORER_IP:-192.168.11.140}" EXPLORER_PORT="${EXPLORER_PORT:-80}" TUNNEL_ID="${TUNNEL_ID:-10ab22da-8ea3-4e2e-a896-27ece2211a05}" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_section() { echo -e "${CYAN}════════════════════════════════════════${NC}"; } SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="${ENV_FILE:-$SCRIPT_DIR/../.env}" log_section log_info "Cloudflare Configuration for Blockscout Explorer" log_section echo "" log_info "Domain: $EXPLORER_DOMAIN" log_info "Target: http://$EXPLORER_IP:$EXPLORER_PORT" log_info "Tunnel ID: $TUNNEL_ID" echo "" # Load environment variables if .env exists if [ -f "$ENV_FILE" ]; then source "$ENV_FILE" fi CLOUDFLARE_API_TOKEN="${CLOUDFLARE_API_TOKEN:-}" CLOUDFLARE_API_KEY="${CLOUDFLARE_API_KEY:-}" CLOUDFLARE_EMAIL="${CLOUDFLARE_EMAIL:-}" # Check if we can use API (support both API Token and API Key methods) USE_API=false AUTH_METHOD="" if [ -n "$CLOUDFLARE_API_TOKEN" ]; then USE_API=true AUTH_METHOD="token" log_info "API Token found - attempting automated configuration..." elif [ -n "$CLOUDFLARE_API_KEY" ] && [ -n "$CLOUDFLARE_EMAIL" ]; then USE_API=true AUTH_METHOD="key" log_info "API Key + Email found - attempting automated configuration..." else log_warn "No API credentials found - will provide manual instructions" fi # Set auth headers based on method if [ "$AUTH_METHOD" = "token" ]; then AUTH_HEADER="Authorization: Bearer $CLOUDFLARE_API_TOKEN" elif [ "$AUTH_METHOD" = "key" ]; then AUTH_HEADER="X-Auth-Email: $CLOUDFLARE_EMAIL X-Auth-Key: $CLOUDFLARE_API_KEY" fi # Function to configure DNS via API configure_dns_api() { local zone_id="$1" local target="${TUNNEL_ID}.cfargotunnel.com" log_info "Configuring DNS record via API..." # Build curl headers based on auth method local curl_headers=(-H "Content-Type: application/json") if [ "$AUTH_METHOD" = "token" ]; then curl_headers+=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN") elif [ "$AUTH_METHOD" = "key" ]; then curl_headers+=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL") curl_headers+=(-H "X-Auth-Key: $CLOUDFLARE_API_KEY") fi # Check if record exists (any type) local response=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records?name=$EXPLORER_DOMAIN" \ "${curl_headers[@]}") local record_id=$(echo "$response" | jq -r '.result[0].id // empty' 2>/dev/null || echo "") local existing_type=$(echo "$response" | jq -r '.result[0].type // empty' 2>/dev/null || echo "") local data=$(jq -n \ --arg name "explorer" \ --arg target "$target" \ '{ type: "CNAME", name: $name, content: $target, proxied: true, ttl: 1 }') if [ -n "$record_id" ] && [ "$record_id" != "null" ]; then log_info "Found existing DNS record (type: ${existing_type:-unknown}, ID: $record_id)" if [ "$existing_type" != "CNAME" ]; then log_warn "Existing record is type $existing_type, deleting and creating CNAME..." curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id" \ "${curl_headers[@]}" >/dev/null 2>&1 log_info "Creating new CNAME record..." response=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records" \ "${curl_headers[@]}" \ --data "$data") else log_info "Updating existing CNAME record..." response=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id" \ "${curl_headers[@]}" \ --data "$data") fi else log_info "Creating new DNS record..." response=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records" \ "${curl_headers[@]}" \ --data "$data") fi if echo "$response" | jq -e '.success' >/dev/null 2>&1; then log_success "DNS record configured successfully" return 0 else local error=$(echo "$response" | jq -r '.errors[0].message // "Unknown error"' 2>/dev/null || echo "API call failed") log_error "Failed to configure DNS: $error" return 1 fi } # Try API configuration if credentials available if [ "$USE_API" = "true" ]; then log_section log_info "Step 1: Getting Zone ID" log_section # Use provided ZONE_ID if available, otherwise fetch it if [ -n "${CLOUDFLARE_ZONE_ID:-}" ]; then ZONE_ID="$CLOUDFLARE_ZONE_ID" log_info "Using provided Zone ID: $ZONE_ID" else # Build curl command based on auth method if [ "$AUTH_METHOD" = "token" ]; then ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \ -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ -H "Content-Type: application/json" | jq -r '.result[0].id // empty' 2>/dev/null || echo "") elif [ "$AUTH_METHOD" = "key" ]; then ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \ -H "X-Auth-Email: $CLOUDFLARE_EMAIL" \ -H "X-Auth-Key: $CLOUDFLARE_API_KEY" \ -H "Content-Type: application/json" | jq -r '.result[0].id // empty' 2>/dev/null || echo "") fi fi if [ -n "$ZONE_ID" ] && [ "$ZONE_ID" != "null" ]; then log_success "Zone ID: $ZONE_ID" log_section log_info "Step 2: Configuring DNS Record" log_section if configure_dns_api "$ZONE_ID"; then log_success "DNS configuration complete via API!" DNS_CONFIGURED=true else log_warn "API DNS configuration failed, falling back to manual" DNS_CONFIGURED=false fi else log_error "Failed to get zone ID" DNS_CONFIGURED=false fi else DNS_CONFIGURED=false fi # Tunnel route configuration (always requires manual or complex API) log_section log_info "Step 3: Tunnel Route Configuration" log_section log_warn "Tunnel route configuration requires manual setup in Cloudflare Zero Trust Dashboard" echo "" log_info "Instructions:" echo "" echo "1. Go to: https://one.dash.cloudflare.com/" echo "2. Navigate to: Zero Trust → Networks → Tunnels" echo "3. Select your tunnel (ID: $TUNNEL_ID)" echo "4. Click 'Configure' → 'Public Hostnames'" echo "5. Click 'Add a public hostname'" echo "6. Configure:" echo " - Subdomain: explorer" echo " - Domain: $DOMAIN" echo " - Service: http://$EXPLORER_IP:$EXPLORER_PORT" echo " - Type: HTTP" echo "7. Click 'Save hostname'" echo "" # Manual DNS instructions if API didn't work if [ "$DNS_CONFIGURED" != "true" ]; then log_section log_info "Step 2: DNS Record Configuration (Manual)" log_section log_info "Go to: https://dash.cloudflare.com/" log_info "Navigate to: $DOMAIN → DNS → Records → Add record" echo "" echo "Configure:" echo " Type: CNAME" echo " Name: explorer" echo " Target: ${TUNNEL_ID}.cfargotunnel.com" echo " Proxy status: 🟠 Proxied (orange cloud) - REQUIRED" echo " TTL: Auto" echo "" log_warn "IMPORTANT: Proxy must be enabled (orange cloud) for tunnel to work!" echo "" fi # Summary log_section log_info "Configuration Summary" log_section if [ "$DNS_CONFIGURED" = "true" ]; then log_success "DNS Record: ✅ Configured via API" else log_warn "DNS Record: ⚠️ Needs manual configuration" fi log_warn "Tunnel Route: ⚠️ Needs manual configuration" echo "" log_info "Configuration Details:" echo " Domain: $EXPLORER_DOMAIN" echo " DNS Target: ${TUNNEL_ID}.cfargotunnel.com" echo " Tunnel Service: http://$EXPLORER_IP:$EXPLORER_PORT" echo "" # Verification instructions log_section log_info "Verification" log_section log_info "After configuration, wait 1-5 minutes for DNS propagation, then test:" echo "" echo " curl -I https://$EXPLORER_DOMAIN" echo " curl https://$EXPLORER_DOMAIN/health" echo "" if [ "$DNS_CONFIGURED" = "true" ]; then log_success "Configuration complete! DNS configured, tunnel route pending manual setup." else log_warn "Configuration pending. Please complete DNS and tunnel route setup manually." fi echo ""