- 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.
213 lines
7.3 KiB
Bash
Executable File
213 lines
7.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# Configure Cloudflare DNS and SSL via API using .env credentials
|
|
# This script does NOT require container access - only Cloudflare API
|
|
|
|
set -euo pipefail
|
|
|
|
# Colors
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
RED='\033[0;31m'
|
|
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"; }
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ENV_FILE="${ENV_FILE:-$SCRIPT_DIR/../.env}"
|
|
|
|
# Configuration
|
|
DOMAIN="${DOMAIN:-d-bis.org}"
|
|
EXPLORER_DOMAIN="explorer.d-bis.org"
|
|
EXPLORER_IP="${EXPLORER_IP:-192.168.11.140}"
|
|
TUNNEL_TOKEN="eyJhIjoiNTJhZDU3YTcxNjcxYzVmYzAwOWVkZjA3NDQ2NTgxOTYiLCJ0IjoiYjAyZmUxZmUtY2I3ZC00ODRlLTkwOWItN2NjNDEyOThlYmU4IiwicyI6Ik5HTmtOV0kwWXpNdFpUVmxaUzAwTVRFMkxXRXdNMk10WlRJNU1ETTFaRFF4TURBMiJ9"
|
|
|
|
echo ""
|
|
log_info "═══════════════════════════════════════════════════════════"
|
|
log_info " CLOUDFLARE DNS & SSL CONFIGURATION (API)"
|
|
log_info "═══════════════════════════════════════════════════════════"
|
|
echo ""
|
|
|
|
# Load .env
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
log_error ".env file not found: $ENV_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
set -a
|
|
source "$ENV_FILE"
|
|
set +a
|
|
|
|
# Get credentials
|
|
CLOUDFLARE_API_TOKEN="${CLOUDFLARE_API_TOKEN:-}"
|
|
CLOUDFLARE_API_KEY="${CLOUDFLARE_API_KEY:-}"
|
|
CLOUDFLARE_EMAIL="${CLOUDFLARE_EMAIL:-}"
|
|
CLOUDFLARE_ZONE_ID="${CLOUDFLARE_ZONE_ID:-}"
|
|
CLOUDFLARE_ACCOUNT_ID="${CLOUDFLARE_ACCOUNT_ID:-}"
|
|
|
|
# Determine auth method
|
|
AUTH_HEADERS=()
|
|
if [ -n "$CLOUDFLARE_API_TOKEN" ]; then
|
|
AUTH_HEADERS=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
|
|
log_success "Using API Token"
|
|
elif [ -n "$CLOUDFLARE_API_KEY" ] && [ -n "$CLOUDFLARE_EMAIL" ]; then
|
|
CLOUDFLARE_API_KEY=$(echo "$CLOUDFLARE_API_KEY" | tr -d '"')
|
|
CLOUDFLARE_EMAIL=$(echo "$CLOUDFLARE_EMAIL" | tr -d '"')
|
|
AUTH_HEADERS=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY")
|
|
log_success "Using API Key"
|
|
else
|
|
log_error "No Cloudflare credentials found"
|
|
exit 1
|
|
fi
|
|
|
|
# Extract tunnel ID from token
|
|
log_info "Extracting tunnel ID from token..."
|
|
TUNNEL_ID=$(echo "$TUNNEL_TOKEN" | base64 -d 2>/dev/null | jq -r '.TunnelID // empty' 2>/dev/null || echo "")
|
|
if [ -z "$TUNNEL_ID" ]; then
|
|
# Try alternative extraction
|
|
TUNNEL_ID=$(echo "$TUNNEL_TOKEN" | base64 -d 2>/dev/null | jq -r '.t // empty' 2>/dev/null || echo "")
|
|
fi
|
|
|
|
if [ -z "$TUNNEL_ID" ]; then
|
|
log_warn "Could not extract tunnel ID from token"
|
|
log_info "You may need to get tunnel ID from: cloudflared tunnel list"
|
|
TUNNEL_ID="<tunnel-id>"
|
|
else
|
|
log_success "Tunnel ID: $TUNNEL_ID"
|
|
fi
|
|
|
|
# Get Zone ID
|
|
if [ -z "$CLOUDFLARE_ZONE_ID" ]; then
|
|
log_info "Getting 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")
|
|
|
|
CLOUDFLARE_ZONE_ID=$(echo "$ZONE_RESPONSE" | jq -r '.result[0].id // empty' 2>/dev/null || echo "")
|
|
|
|
if [ -z "$CLOUDFLARE_ZONE_ID" ] || [ "$CLOUDFLARE_ZONE_ID" = "null" ]; then
|
|
log_error "Failed to get zone ID"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
log_success "Zone ID: $CLOUDFLARE_ZONE_ID"
|
|
|
|
# Get Account ID
|
|
if [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
|
|
log_info "Getting account ID..."
|
|
ACCOUNT_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts" \
|
|
"${AUTH_HEADERS[@]}" \
|
|
-H "Content-Type: application/json")
|
|
|
|
CLOUDFLARE_ACCOUNT_ID=$(echo "$ACCOUNT_RESPONSE" | jq -r '.result[0].id // empty' 2>/dev/null || echo "")
|
|
fi
|
|
|
|
if [ -n "$CLOUDFLARE_ACCOUNT_ID" ]; then
|
|
log_success "Account ID: $CLOUDFLARE_ACCOUNT_ID"
|
|
fi
|
|
|
|
# Configure DNS
|
|
log_info "Configuring DNS record..."
|
|
TARGET="${TUNNEL_ID}.cfargotunnel.com"
|
|
|
|
# Check existing record
|
|
EXISTING=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/dns_records?name=$EXPLORER_DOMAIN" \
|
|
"${AUTH_HEADERS[@]}" \
|
|
-H "Content-Type: application/json")
|
|
|
|
RECORD_ID=$(echo "$EXISTING" | jq -r '.result[0].id // empty' 2>/dev/null || echo "")
|
|
|
|
DNS_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 "Updating existing DNS record..."
|
|
DNS_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/dns_records/$RECORD_ID" \
|
|
"${AUTH_HEADERS[@]}" \
|
|
-H "Content-Type: application/json" \
|
|
--data "$DNS_DATA")
|
|
else
|
|
log_info "Creating new DNS record..."
|
|
DNS_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/dns_records" \
|
|
"${AUTH_HEADERS[@]}" \
|
|
-H "Content-Type: application/json" \
|
|
--data "$DNS_DATA")
|
|
fi
|
|
|
|
if echo "$DNS_RESPONSE" | jq -e '.success' >/dev/null 2>&1; then
|
|
log_success "DNS record configured: $EXPLORER_DOMAIN → $TARGET (🟠 Proxied)"
|
|
else
|
|
ERROR=$(echo "$DNS_RESPONSE" | jq -r '.errors[0].message // "Unknown error"' 2>/dev/null || echo "API call failed")
|
|
log_error "DNS configuration failed: $ERROR"
|
|
echo "$DNS_RESPONSE" | jq '.' 2>/dev/null || echo "$DNS_RESPONSE"
|
|
exit 1
|
|
fi
|
|
|
|
# Configure Tunnel Route (if account ID available)
|
|
if [ -n "$CLOUDFLARE_ACCOUNT_ID" ] && [ "$TUNNEL_ID" != "<tunnel-id>" ]; then
|
|
log_info "Configuring tunnel route..."
|
|
|
|
TUNNEL_CONFIG=$(jq -n \
|
|
--arg hostname "$EXPLORER_DOMAIN" \
|
|
--arg service "http://$EXPLORER_IP:80" \
|
|
'{
|
|
config: {
|
|
ingress: [
|
|
{
|
|
hostname: $hostname,
|
|
service: $service
|
|
},
|
|
{
|
|
service: "http_status:404"
|
|
}
|
|
]
|
|
}
|
|
}')
|
|
|
|
TUNNEL_UPDATE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/cfd_tunnel/$TUNNEL_ID/configurations" \
|
|
"${AUTH_HEADERS[@]}" \
|
|
-H "Content-Type: application/json" \
|
|
--data "$TUNNEL_CONFIG")
|
|
|
|
if echo "$TUNNEL_UPDATE" | jq -e '.success' >/dev/null 2>&1; then
|
|
log_success "Tunnel route configured: $EXPLORER_DOMAIN → http://$EXPLORER_IP:80"
|
|
else
|
|
ERROR=$(echo "$TUNNEL_UPDATE" | jq -r '.errors[0].message // "Unknown error"' 2>/dev/null || echo "API call failed")
|
|
log_warn "Tunnel route configuration failed: $ERROR"
|
|
log_info "Configure manually in Cloudflare Zero Trust dashboard"
|
|
fi
|
|
else
|
|
log_warn "Tunnel route requires manual configuration"
|
|
fi
|
|
|
|
# SSL is automatic with Cloudflare proxy
|
|
log_success "SSL/TLS: Automatic (Cloudflare Universal SSL enabled)"
|
|
|
|
# Verify
|
|
log_info "Waiting for DNS propagation (10 seconds)..."
|
|
sleep 10
|
|
|
|
PUBLIC_HTTP=$(curl -s -o /dev/null -w "%{http_code}" "https://$EXPLORER_DOMAIN/api/v2/stats" 2>&1)
|
|
if [ "$PUBLIC_HTTP" = "200" ]; then
|
|
log_success "Public URL: HTTP 200 - Working!"
|
|
else
|
|
log_warn "Public URL: HTTP $PUBLIC_HTTP (may need more time for propagation)"
|
|
fi
|
|
|
|
echo ""
|
|
log_success "Configuration complete!"
|
|
echo ""
|
|
|