#!/bin/bash set -euo pipefail # Cloudflare Tunnel Configuration Script CLOUDFLARE_API_TOKEN="${CLOUDFLARE_API_TOKEN:-}" ZONE_ID="${ZONE_ID:-}" ACCOUNT_ID="${ACCOUNT_ID:-}" log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" >&2 } error() { log "ERROR: $*" exit 1 } check_prerequisites() { if [ -z "${CLOUDFLARE_API_TOKEN}" ]; then error "CLOUDFLARE_API_TOKEN environment variable is required" fi if [ -z "${ZONE_ID}" ]; then error "ZONE_ID environment variable is required" fi if [ -z "${ACCOUNT_ID}" ]; then error "ACCOUNT_ID environment variable is required" fi if ! command -v cloudflared &> /dev/null; then error "cloudflared is not installed. Install it first." fi } create_tunnel() { local tunnel_name=$1 log "Creating Cloudflare tunnel: ${tunnel_name}" # Create tunnel via API TUNNEL_ID=$(curl -s -X POST \ -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \ -H "Content-Type: application/json" \ "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/cfd_tunnel" \ -d "{\"name\":\"${tunnel_name}\",\"config_src\":\"local\"}" \ | jq -r '.result.id') if [ -z "${TUNNEL_ID}" ] || [ "${TUNNEL_ID}" = "null" ]; then error "Failed to create tunnel ${tunnel_name}" fi log "Tunnel created with ID: ${TUNNEL_ID}" echo "${TUNNEL_ID}" } get_tunnel_token() { local tunnel_id=$1 log "Getting tunnel token for ${tunnel_id}..." TOKEN=$(curl -s -X GET \ -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \ "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/cfd_tunnel/${tunnel_id}/token" \ | jq -r '.result.token') if [ -z "${TOKEN}" ] || [ "${TOKEN}" = "null" ]; then error "Failed to get tunnel token" fi echo "${TOKEN}" } configure_dns() { local hostname=$1 local tunnel_id=$2 log "Configuring DNS for ${hostname}..." # Create CNAME record curl -s -X POST \ -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \ -H "Content-Type: application/json" \ "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \ -d "{ \"type\": \"CNAME\", \"name\": \"${hostname}\", \"content\": \"${tunnel_id}.cfargotunnel.com\", \"ttl\": 1, \"proxied\": true }" > /dev/null log "DNS record created for ${hostname}" } setup_control_plane_tunnel() { log "Setting up control plane tunnel..." TUNNEL_ID=$(create_tunnel "control-plane-tunnel") TUNNEL_TOKEN=$(get_tunnel_token "${TUNNEL_ID}") log "Control plane tunnel token: ${TUNNEL_TOKEN}" log "Save this token securely and use it when running cloudflared on control plane nodes" # Configure DNS for control plane services configure_dns "portal" "${TUNNEL_ID}" configure_dns "rancher" "${TUNNEL_ID}" configure_dns "argocd" "${TUNNEL_ID}" configure_dns "grafana" "${TUNNEL_ID}" configure_dns "vault" "${TUNNEL_ID}" configure_dns "keycloak" "${TUNNEL_ID}" } setup_proxmox_tunnels() { local sites=("site-1" "site-2" "site-3") for site in "${sites[@]}"; do log "Setting up tunnel for ${site}..." TUNNEL_ID=$(create_tunnel "proxmox-${site}-tunnel") TUNNEL_TOKEN=$(get_tunnel_token "${TUNNEL_ID}") log "${site} tunnel token: ${TUNNEL_TOKEN}" log "Save this token and use it when running setup-proxmox-agents.sh on ${site} nodes" done } main() { log "Starting Cloudflare tunnel configuration..." check_prerequisites setup_control_plane_tunnel setup_proxmox_tunnels log "" log "Cloudflare tunnel configuration completed!" log "" log "Next steps:" log "1. Save all tunnel tokens securely" log "2. Use tokens when running cloudflared on respective nodes" log "3. Verify DNS records are created correctly" log "4. Test tunnel connectivity" } main "$@"