#!/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="" 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" != "" ]; 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 ""