File: //bigscoots/wpo/cloudflare/cfent_init.sh
#!/bin/bash
source /bigscoots/includes/common.sh
source /root/.bigscoots/.cf
ENTZONE=c2d79b78db1f915729e6a48f8bd6b0c3
CFAPIURL=https://api.cloudflare.com/client/v4
# Usage information
usage() {
echo "Usage: $0 --domain DOMAIN --ip IP [--email EMAIL] [--apikey APIKEY] [--zoneid ZONEID] [--run]"
echo "Mandatory options:"
echo " --domain DOMAIN Domain name to update DNS records for"
echo " --ip IP IP address to set for the DNS records"
echo "Optional options:"
echo " --email EMAIL Cloudflare email address"
echo " --apikey APIKEY Cloudflare API key"
echo " --zoneid ZONEID Cloudflare zone ID"
echo "Flags:"
echo " --run Run the script in the current session (used internally)"
exit 0
}
function status_check () {
# Initialize JSON response
init_json_response
# Get the Cloudflare custom hostname ID
CFAPICHNAMEID=$(cat "/root/cfplugin/${DOMAIN}.step2.api" | jq -r '.result.id')
# Fetch the custom hostname details
RESPONSE=$(curl -s -X GET \
--url "${CFAPIURL}/zones/${ENTZONE}/custom_hostnames/${CFAPICHNAMEID}" \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${CFAPITOKEN}")
# Extract required fields
SSL_STATUS=$(echo "$RESPONSE" | jq -r '.result.ssl.status // "unknown"')
HOSTNAME_STATUS=$(echo "$RESPONSE" | jq -r '.result.status // "unknown"')
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
# Build the result JSON
RESULT_JSON=$(jq -n \
--arg bs_site_id "$BS_SITE_ID" \
--arg domain "$DOMAIN" \
--arg ssl_status "$SSL_STATUS" \
--arg hostname_status "$HOSTNAME_STATUS" \
'{
bs_site_id: $bs_site_id,
domain: $domain,
ssl_status: $ssl_status,
hostname_status: $hostname_status
}')
# Set the JSON response
set_json_result "$RESULT_JSON"
set_json_success
# Print the JSON response
print_json_response
}
# Parse command line arguments
RUN=0
ZONEID_ARG=""
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--domain)
DOMAIN="$2"
shift
shift
;;
--ip)
IP="$2"
shift
shift
;;
--email)
DOMAIN_CF_EMAIL="$2"
shift
shift
;;
--apikey)
DOMAIN_CF_APIKEY="$2"
shift
shift
;;
--zoneid)
DOMAIN_CF_ZONEID="$2"
ZONEID_ARG="--zoneid \"$DOMAIN_CF_ZONEID\""
shift
shift
;;
--run)
RUN=1
shift
;;
--status)
status_check
exit 0
;;
*)
usage
;;
esac
done
# Check that mandatory options are present
if [ -z "$DOMAIN" ] || [ -z "$IP" ]; then
usage
fi
function GEN_PKEY () {
# Generate the .info file with data from the master server
if [ ! -f /root/cfplugin/"${DOMAIN}".info ]; then
ssh "${SSH_OPTIONS[@]}" -p 2222 [email protected] "bash /var/www/main.bigscoots.com/create_master.sh ${DOMAIN} ${ENTZONE} ${IP}" >> /root/cfplugin/"${DOMAIN}".info
fi
# Read the JSON data from the .info file
JSON_PAYLOAD=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq --arg hash "$HASH" '
. | to_entries |
map(if .key == "bs_site_id" then . , {"key": "hash", "value": $hash} else . end) |
from_entries
')
# Check all keys for non-empty, non-null, and non-"null" values
IS_SUCCESS=$(echo "$JSON_PAYLOAD" | jq '
. as $object |
reduce keys[] as $key (true; . and ($object[$key] != null and $object[$key] != "" and $object[$key] != "null"))
')
# Append the success status to the JSON
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq --argjson success "$IS_SUCCESS" '. + {success: $success}')
# Send the JSON data to the API endpoint
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "${JSON_PAYLOAD}")
# Output the JSON payload and API response (optional, for debugging)
echo "$JSON_PAYLOAD"
echo "API Response: ${RESPONSE}"
}
function DEPLOY_PKEY () {
# Extract the bs_site_id from the .info file
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
if [ -n "$BS_SITE_ID" ] && [ "$BS_SITE_ID" != "null" ]; then
STATUS=true
else
STATUS=false
fi
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "deploy pkey" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg status "$STATUS" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"success": $status
}')
echo "$JSON_PAYLOAD"
# Send the JSON payload to the API endpoint
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
# Output the API response (optional, for debugging)
echo "API Response: ${RESPONSE}"
}
function FINALSTEPS () {
BS_MASTER_KEY=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_master_key')
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
# Execute the remote SSH command
WPO_SSL_STATUS=$(ssh "${SSH_OPTIONS[@]}" -p 2222 "${IP}" "bash /bigscoots/wpo/cloudflare/fujames.sh ${DOMAIN} ${BS_MASTER_KEY} ${BS_SITE_ID}")
SSH_EXIT_CODE=$?
export WPO_SSL_STATUS
# Determine success status based on the SSH exit code
if [[ $SSH_EXIT_CODE -eq 0 ]]; then
STATUS="true"
else
STATUS="false"
fi
# Extract bs_site_id from the .info file
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "wpo deployment and ssl" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg domain "$DOMAIN" \
--arg ip "$IP" \
--arg success "$STATUS" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"domain": $domain,
"ip": $ip,
"success": ($success | test("true"))
}')
# Send JSON payload to the API
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
echo "$JSON_PAYLOAD"
# Output API response (optional, for debugging)
echo "API Response: ${RESPONSE}"
}
function GATHERCFAPI () {
# Check if CFAPI already exists
if grep -q CFAPI /root/cfplugin/"${DOMAIN}".info; then
send_slack_alert "#cloudflare" ":warning:" "Function: \`GATHERCFAPI\`" "$hostname" "CFAPI already exists in /root/cfplugin/${DOMAIN}.info\nIf this info is incorrect or incomplete then remove CFAPI lines and rerun this command."
else
# Generate CFAPI info and append it to the .info file
ssh "${SSH_OPTIONS[@]}" -p 2222 "${IP}" "bash /bigscoots/wpo/cloudflare/fujames.sh ${DOMAIN} CFAPI" >> /root/cfplugin/"${DOMAIN}".info
fi
# Extract bs_site_id from the JSON block
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
# Extract CFAPI values from the text outside of the JSON
CFAPI_DOMAIN=$(grep 'CFAPI Domain' /root/cfplugin/"${DOMAIN}".info | awk '{print $3}')
CFAPI_SERVERIP=$(grep 'CFAPI Server IP' /root/cfplugin/"${DOMAIN}".info | awk '{print $4}')
CFAPI_CANONICALDOMAIN=$(grep 'CFAPI Canonical Domain' /root/cfplugin/"${DOMAIN}".info | awk '{print $4}')
CFAPI_CUSTOMHOSTNAME=$(grep 'CFAPI Custom Hostname' /root/cfplugin/"${DOMAIN}".info | awk '{print $4}')
# Determine the status based on whether all CFAPI variables were set
if [[ -n "$CFAPI_DOMAIN" && -n "$CFAPI_SERVERIP" && -n "$CFAPI_CANONICALDOMAIN" && -n "$CFAPI_CUSTOMHOSTNAME" ]]; then
STATUS="true"
else
STATUS="false"
fi
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "gather cfapi" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg cfapi_domain "$CFAPI_DOMAIN" \
--arg cfapi_serverip "$CFAPI_SERVERIP" \
--arg cfapi_canonicaldomain "$CFAPI_CANONICALDOMAIN" \
--arg cfapi_customhostname "$CFAPI_CUSTOMHOSTNAME" \
--arg success "$STATUS" \
'{
step: $step,
bs_site_id: $bs_site_id,
hash: $hash,
cfapi: {
domain: $cfapi_domain,
server_ip: $cfapi_serverip,
canonical_domain: $cfapi_canonicaldomain,
custom_hostname: $cfapi_customhostname
},
success: ($success | test("true"))
}')
echo "$JSON_PAYLOAD"
# Send JSON payload to the API
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
# Output the API response (optional, for debugging)
echo "API Response: ${RESPONSE}"
}
function ADDDNSCFAPI () {
if [[ -f "/root/cfplugin/${DOMAIN}.step1.api" ]]; then
# File exists, check the .success field
SUCCESS=$(jq -r '.success' < "/root/cfplugin/${DOMAIN}.step1.api")
else
# File does not exist, set SUCCESS to "false" to trigger curl
SUCCESS="false"
fi
# Run curl request if success is false
if [[ "$SUCCESS" != "true" ]]; then
curl -s -X POST "${CFAPIURL}/zones/${ENTZONE}/dns_records" \
-H "Authorization: Bearer ${CFAPITOKEN}" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"'"$CFAPI_DOMAIN"'","content":"'"$CFAPI_SERVERIP"'","ttl":120,"priority":10,"proxied":true}' \
-o "/root/cfplugin/${DOMAIN}.step1.api"
fi
# Extract response data
API_RESPONSE=$(cat /root/cfplugin/${DOMAIN}.step1.api)
SUCCESS=$(echo "$API_RESPONSE" | jq -r '.success')
ID=$(echo "$API_RESPONSE" | jq -r '.result.id')
CONTENT=$(echo "$API_RESPONSE" | jq -r '.result.content')
# Convert Cloudflare success to JSON success: true/false
if [[ "$SUCCESS" == "true" ]]; then
STATUS="true"
else
STATUS="false"
fi
# Extract bs_site_id from the .info file
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "add custom hostname dns record" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg success "$STATUS" \
--arg id "$ID" \
--arg content "$CONTENT" \
'{
step: $step,
bs_site_id: $bs_site_id,
hash: $hash,
success: ($success | test("true")),
record: {
id: $id,
content: $content
}
}')
echo "$JSON_PAYLOAD"
# Send JSON payload to the API
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
# Output API response (optional, for debugging)
echo "API Response: ${RESPONSE}"
}
function ADDCHNAMECFAPI () {
if [[ -f "/root/cfplugin/${DOMAIN}.step2.api" ]]; then
SUCCESS=$(jq -r '.success' < "/root/cfplugin/${DOMAIN}.step2.api")
else
SUCCESS="false"
fi
if [[ "$SUCCESS" != "true" ]]; then
curl -s -X POST "${CFAPIURL}/zones/${ENTZONE}/custom_hostnames" \
-H "Authorization: Bearer ${CFAPITOKEN}" \
-H "Content-Type: application/json" \
--data '{
"hostname": "'"$CFAPI_CANONICALDOMAIN"'",
"ssl": {
"bundle_method": "ubiquitous",
"certificate_authority": "lets_encrypt",
"method": "http",
"settings": {
"early_hints": "on",
"http2": "on",
"http3": "on",
"min_tls_version": "1.2",
"tls_1_3": "on"
},
"type": "dv",
"wildcard": false
}
}' \
-o "/root/cfplugin/${DOMAIN}.step2.api"
fi
# Extract API response
API_RESPONSE=$(cat /root/cfplugin/${DOMAIN}.step2.api)
SUCCESS=$(echo "$API_RESPONSE" | jq -r '.success')
ID=$(echo "$API_RESPONSE" | jq -r '.result.id')
OWNERSHIP_HTTP_URL=$(echo "$API_RESPONSE" | jq -r '.result.ownership_verification_http.http_url')
OWNERSHIP_HTTP_BODY=$(echo "$API_RESPONSE" | jq -r '.result.ownership_verification_http.http_body')
if [[ "$SUCCESS" == "true" ]]; then
STATUS="true"
else
STATUS="false"
fi
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
JSON_PAYLOAD=$(jq -n \
--arg step "add custom hostname" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg success "$STATUS" \
--arg id "$ID" \
--arg ownership_http_url "$OWNERSHIP_HTTP_URL" \
--arg ownership_http_body "$OWNERSHIP_HTTP_BODY" \
'{
step: $step,
bs_site_id: $bs_site_id,
hash: $hash,
success: ($success | test("true")),
result: {
id: $id,
ownership_verification_http: {
http_url: $ownership_http_url,
http_body: $ownership_http_body
}
}
}')
echo "$JSON_PAYLOAD"
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
echo "API Response: ${RESPONSE}"
}
function MDFYCHNAMECFAPI () {
CFAPICHNAMEID=$(cat /root/cfplugin/${DOMAIN}.step2.api | jq -r '.result.id')
curl -s -X PATCH "${CFAPIURL}/zones/${ENTZONE}/custom_hostnames/${CFAPICHNAMEID}" \
-H "Authorization: Bearer ${CFAPITOKEN}" \
-H "Content-Type: application/json" \
--data '{"custom_origin_server":"'"$CFAPI_CUSTOMHOSTNAME"'"}' \
-o /root/cfplugin/${DOMAIN}.step3.api
}
function GETCHNAMEINFO () {
CFAPICHNAMEID=$(cat /root/cfplugin/${DOMAIN}.step2.api | jq -r '.result.id')
curl -s -X PATCH "${CFAPIURL}/zones/${ENTZONE}/custom_hostnames/${CFAPICHNAMEID}" \
-H "Authorization: Bearer ${CFAPITOKEN}" \
-H "Content-Type: application/json" \
--data '{"ssl":{"method":"http","type":"dv","settings":{"min_tls_version":"1.2"}}}' \
-o /root/cfplugin/${DOMAIN}.step3.api
}
function VRFYCFAPI () {
MAX_RETRIES=100
RETRY_COUNT=0
SUCCESS="false"
while true; do
GETCHNAMEINFO
SSL_STATUS=$(jq -r '.result.ssl.status' < /root/cfplugin/"${DOMAIN}".step3.api)
SSL_HTTP_URL=$(jq -r '.result.ssl.validation_records[0].http_url // empty' < /root/cfplugin/"${DOMAIN}".step3.api)
SSL_HTTP_BODY=$(jq -r '.result.ssl.validation_records[0].http_body // empty' < /root/cfplugin/"${DOMAIN}".step3.api)
if [[ "$SSL_STATUS" == "active" || ( -n "$SSL_HTTP_URL" && -n "$SSL_HTTP_BODY" ) ]]; then
SUCCESS="true"
break
fi
((RETRY_COUNT++))
if [[ $RETRY_COUNT -ge $MAX_RETRIES ]]; then
echo "Maximum retries reached. Continuing script without valid SSL verification."
break
fi
sleep 5
done
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
if [[ ${CFAPI_CANONICALDOMAIN} = www* ]]; then
CANONICAL=www
else
CANONICAL=nonwww
fi
JSON_PAYLOAD=$(jq -n \
--arg step "obtain SSL verification records" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg domain "$DOMAIN" \
--arg ssl_http_url "$SSL_HTTP_URL" \
--arg ssl_http_body "$SSL_HTTP_BODY" \
--arg ssl_status "$SSL_STATUS" \
--arg success "$SUCCESS" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"domain": $domain,
"ssl_verification": {
"http_url": $ssl_http_url,
"http_body": $ssl_http_body,
"status": $ssl_status
},
"success": ($success | test("true"))
}')
echo "$JSON_PAYLOAD"
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
echo "API Response: ${RESPONSE}"
# Updated Slack message - no TXT records needed, HTTP challenge is automatic
bash /bigscoots/general/slack.sh "#cloudflare" "\n \n \n \
:zap:*Cloudflare Enterprise Setup*:zap: \
\n \
Domain: \`${DOMAIN}\` on server IP: \`${IP}\` \n \
\n \
In WPO Admin, set Cloudflare Plan to purchased *Tier 1,2,3*.\n \
\n \
Remove the ORANGE CLOUD from record: \`${CFAPI_CANONICALDOMAIN}\` \n \
Ensure the NON Canonical Domain is pointed with an A Record, Orange Cloud. Sometimes its a CNAME which will cause it to fail. \n \
\n \
SSL verification is via *HTTP challenge* (no DNS records needed). \n \
HTTP URL: \`${SSL_HTTP_URL}\` \n \
SSL Status: \`${SSL_STATUS}\` \n \
SSH into \`${IP}\` and force non Canonical Domain to \`${CFAPI_CANONICALDOMAIN}\` \n \
\`\`\`bash /bigscoots/wpo/manage/set.sh canonical ${DOMAIN} ${CANONICAL}\`\`\`
Wait 15 minutes then you can change the \`${CFAPI_CANONICALDOMAIN}\` record to a CNAME and point to \`enterprise.tier1.bigscoots.com.\` with a GREY cloud."
}
function HANDLE_TXT_RECORD () {
local STEP=$1
local TXT_NAME=$2
local TXT_VALUE=$3
# Add TXT record and capture response
ADD_TXT_RESPONSE=$(ADD_TXT_RECORD "$TXT_NAME" "$TXT_VALUE")
ADD_TXT_SUCCESS=$(echo "$ADD_TXT_RESPONSE" | jq -r '.success')
ADD_TXT_ERRORS=$(echo "$ADD_TXT_RESPONSE" | jq -c '.errors')
ADD_TXT_MESSAGES=$(echo "$ADD_TXT_RESPONSE" | jq -c '.messages')
# Determine success status
if [[ "$ADD_TXT_SUCCESS" == "true" ]]; then
STATUS="true"
else
STATUS="false"
fi
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "$STEP" \
--arg domain "$DOMAIN" \
--arg txt_name "$TXT_NAME" \
--arg txt_value "$TXT_VALUE" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg success "$STATUS" \
--arg errors "$ADD_TXT_ERRORS" \
--arg messages "$ADD_TXT_MESSAGES" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"domain": $domain,
"txt_record": {
"name": $txt_name,
"value": $txt_value
},
"success": ($success | test("true")),
"errors": ($errors | fromjson),
"messages": ($messages | fromjson)
}')
echo "$JSON_PAYLOAD"
# Send JSON payload to the API
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
# Output API response (optional, for debugging)
echo "API Response: ${RESPONSE}"
}
# Function to add TXT record
ADD_TXT_RECORD() {
local NAME=$1
local CONTENT=$2
local RECORD_TYPE=TXT
# echo "Adding TXT record with value: $NAME $CONTENT"
curl -s -X POST "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records" \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--data "{\"type\":\"$RECORD_TYPE\",\"name\":\"$NAME\",\"content\":\"$CONTENT\",\"ttl\":1,\"proxied\":false}" \
| jq '{success: .success, errors: .errors, messages: .messages}'
}
function UPDATE_DNS_CFENT_CNAME () {
# echo "🔄 Updating Cloudflare Canonical DNS Record for $CFAPI_CANONICALDOMAIN..."
# Update the DNS record to set it as a CNAME
CF_UPDATE_RESPONSE=$(curl --silent --location --request PUT "https://api.cloudflare.com/client/v4/zones/$DOMAIN_CF_ZONEID/dns_records/$DNS_RECORD_ID" \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--data "{\"type\":\"CNAME\",\"name\":\"$CFAPI_CANONICALDOMAIN\",\"content\":\"enterprise.tier1.bigscoots.com\",\"proxied\":false}")
# Extract relevant fields from the response
CF_UPDATE_SUCCESS=$(echo "$CF_UPDATE_RESPONSE" | jq -r '.success')
CF_UPDATE_ERRORS=$(echo "$CF_UPDATE_RESPONSE" | jq -c '.errors')
CF_UPDATE_MESSAGES=$(echo "$CF_UPDATE_RESPONSE" | jq -c '.messages')
# Determine status
if [[ "$CF_UPDATE_SUCCESS" == "true" ]]; then
STATUS="true"
# echo "✅ Cloudflare DNS record successfully updated to CNAME."
else
STATUS="false"
# echo "❌ Cloudflare DNS update failed."
fi
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "change cname on canonical dns" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg canonical_domain "$CFAPI_CANONICALDOMAIN" \
--arg success "$STATUS" \
--arg errors "$CF_UPDATE_ERRORS" \
--arg messages "$CF_UPDATE_MESSAGES" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"canonical_domain": $canonical_domain,
"success": ($success | test("true")),
"errors": $errors,
"messages": ($messages | fromjson)
}')
echo "$JSON_PAYLOAD"
# Send JSON payload to the API
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
# Output API response (optional, for debugging)
echo "🚀 API Response: ${RESPONSE}"
}
function GRAY_CLOUD_DOMAIN () {
# Extract bs_site_id from the .info file
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
# Check if SSL_STATUS is success
if [[ "$WPO_SSL_STATUS" != success ]]; then
# SSL is not successfully set; skip and set error messages
GRAY_CLOUD_SUCCESS="false"
GRAY_CLOUD_ERRORS="$DOMAIN does not have a signed SSL on the server unable to gray-cloud"
GRAY_CLOUD_MESSAGES="[]"
else
# SSL is successfully set; proceed with gray-clouding
# Get the DNS record ID for the canonical domain
DNS_RECORD_ID=$(GET_DNS_RECORD_ID)
# Update the DNS record to gray-cloud it
GRAY_CLOUD_RESPONSE=$(curl --silent --location --request PUT "https://api.cloudflare.com/client/v4/zones/$DOMAIN_CF_ZONEID/dns_records/$DNS_RECORD_ID" \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--data "{\"content\":\"$IP\",\"name\":\"$CFAPI_CANONICALDOMAIN\",\"proxied\":false,\"type\":\"A\"}")
# Extract relevant fields from the response
GRAY_CLOUD_SUCCESS=$(echo "$GRAY_CLOUD_RESPONSE" | jq -r '.success')
GRAY_CLOUD_ERRORS=$(echo "$GRAY_CLOUD_RESPONSE" | jq -c '.errors')
GRAY_CLOUD_MESSAGES=$(echo "$GRAY_CLOUD_RESPONSE" | jq -c '.messages')
fi
# Determine status
if [[ "$GRAY_CLOUD_SUCCESS" == "true" ]]; then
STATUS="true"
else
STATUS="false"
fi
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "gray cloud domain" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg domain "$DOMAIN" \
--arg ip "$IP" \
--arg success "$STATUS" \
--arg errors "$GRAY_CLOUD_ERRORS" \
--arg messages "$GRAY_CLOUD_MESSAGES" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"domain": $domain,
"ip": $ip,
"success": ($success | test("true")),
"errors": $errors,
"messages": ($messages | fromjson)
}')
echo "$JSON_PAYLOAD"
# Send JSON payload to the API
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
# Output API response (optional, for debugging)
echo "API Response: ${RESPONSE}"
}
GET_ZONE_ID () {
curl -s -X GET "${CFAPIURL}/zones?name=$DOMAIN" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "Content-Type: application/json" | jq -r '.result[0].id'
}
function CHK_CF_CUSTOM_HOSTNAME_STATUS () {
MAX_RETRIES=100 # Maximum retries (100 attempts)
RETRY_COUNT=0
SUCCESS="false" # Default to false
while true; do
# Fetch the latest custom hostname info
GETCHNAMEINFO
# Extract SSL status and result status
SSL_STATUS=$(jq -r '.result.ssl.status' < /root/cfplugin/"${DOMAIN}".step3.api)
RESULT_STATUS=$(jq -r '.result.status' < /root/cfplugin/"${DOMAIN}".step3.api)
# Debugging output (optional, remove if not needed)
echo "Attempt: $((RETRY_COUNT + 1)) | SSL Status: $SSL_STATUS | Result Status: $RESULT_STATUS"
# Check if both statuses are "active"
if [[ "$SSL_STATUS" == "active" && "$RESULT_STATUS" == "active" ]]; then
SUCCESS="true"
echo "✅ Custom hostname SSL and result status are active!"
break # Exit the loop when both conditions are met
fi
# Increment retry count and check the limit
((RETRY_COUNT++))
if [[ $RETRY_COUNT -ge $MAX_RETRIES ]]; then
echo "❌ Maximum retries reached. SSL or result status not active. Continuing script."
break
fi
# Wait 10 seconds before the next check
sleep 10
done
}
function UPDATE_DNS_RECORD () {
# Fetch the DNS record details for the canonical domain
response=$(curl --silent --location "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records?name=$CFAPI_CANONICALDOMAIN" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json')
# Extract record ID and type
record_id=$(echo "$response" | jq -r '.result[0].id')
record_type=$(echo "$response" | jq -r '.result[0].type')
# Extract bs_site_id from the .info file
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
# If the record is a CNAME, change it to an A record
if [ "$record_type" == "CNAME" ]; then
# Delete the existing CNAME record
delete_response=$(curl --silent --location --request DELETE "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records/$record_id" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json')
delete_success=$(echo "$delete_response" | jq -r '.success')
delete_errors=$(echo "$delete_response" | jq -c '.errors')
# If deletion was successful, create a new A record
if [[ "$delete_success" == "true" ]]; then
create_response=$(curl --silent --location --request POST "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json' \
--data '{
"type": "A",
"name": "'"$CFAPI_CANONICALDOMAIN"'",
"content": "'"$IP"'",
"ttl": 120,
"proxied": false
}')
create_success=$(echo "$create_response" | jq -r '.success')
create_errors=$(echo "$create_response" | jq -c '.errors')
# Determine overall success status
if [[ "$create_success" == "true" ]]; then
STATUS="true"
else
STATUS="false"
fi
else
# Failed to delete the CNAME record
STATUS="false"
create_errors="[]"
fi
else
# Record is not a CNAME, no action needed
STATUS="true"
delete_errors="[]"
create_errors="[]"
fi
# Create JSON payload
JSON_PAYLOAD=$(jq -n \
--arg step "update dns record" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg domain "$DOMAIN" \
--arg canonical_domain "$CFAPI_CANONICALDOMAIN" \
--arg ip "$IP" \
--arg status "$STATUS" \
--arg delete_errors "$delete_errors" \
--arg create_errors "$create_errors" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"domain": $domain,
"canonical_domain": $canonical_domain,
"ip": $ip,
"success": ($status | test("true")),
"delete_errors": ($delete_errors | fromjson),
"create_errors": ($create_errors | fromjson)
}')
# Send JSON payload to the API
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
echo "$JSON_PAYLOAD"
# Output API response (optional, for debugging)
echo "API Response: ${RESPONSE}"
}
function FIX_NONCANONICAL_DNS () {
if [[ "$CFAPI_CANONICALDOMAIN" == www.* ]]; then
NONCANONICALDOMAIN="${CFAPI_CANONICALDOMAIN#www.}"
else
NONCANONICALDOMAIN="www.${CFAPI_CANONICALDOMAIN}"
fi
NC_RESPONSE=$(curl --silent --location \
"${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records?name=$NONCANONICALDOMAIN" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json')
NC_RECORD_ID=$(echo "$NC_RESPONSE" | jq -r '.result[0].id')
NC_RECORD_TYPE=$(echo "$NC_RESPONSE" | jq -r '.result[0].type')
BS_SITE_ID=$(sed '/^{/,/^}/!d' /root/cfplugin/"${DOMAIN}".info | jq -r '.bs_site_id')
if [[ "$NC_RECORD_TYPE" == "CNAME" ]]; then
DELETE_RESPONSE=$(curl --silent --location --request DELETE \
"${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records/$NC_RECORD_ID" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json')
DELETE_SUCCESS=$(echo "$DELETE_RESPONSE" | jq -r '.success')
if [[ "$DELETE_SUCCESS" == "true" ]]; then
CREATE_RESPONSE=$(curl --silent --location --request POST \
"${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records" \
--header "X-Auth-Email: $DOMAIN_CF_EMAIL" \
--header "X-Auth-Key: $DOMAIN_CF_APIKEY" \
--header 'Content-Type: application/json' \
--data '{
"type": "A",
"name": "'"$NONCANONICALDOMAIN"'",
"content": "'"$IP"'",
"ttl": 120,
"proxied": true
}')
CREATE_SUCCESS=$(echo "$CREATE_RESPONSE" | jq -r '.success')
CREATE_ERRORS=$(echo "$CREATE_RESPONSE" | jq -c '.errors')
if [[ "$CREATE_SUCCESS" == "true" ]]; then
STATUS="true"
else
STATUS="false"
fi
else
STATUS="false"
CREATE_ERRORS="[]"
fi
else
STATUS="true"
CREATE_ERRORS="[]"
fi
JSON_PAYLOAD=$(jq -n \
--arg step "fix non-canonical dns record" \
--arg bs_site_id "$BS_SITE_ID" \
--arg hash "$HASH" \
--arg domain "$DOMAIN" \
--arg noncanonicaldomain "$NONCANONICALDOMAIN" \
--arg record_type "$NC_RECORD_TYPE" \
--arg ip "$IP" \
--arg success "$STATUS" \
--arg create_errors "$CREATE_ERRORS" \
'{
"step": $step,
"bs_site_id": $bs_site_id,
"hash": $hash,
"domain": $domain,
"noncanonical_domain": $noncanonicaldomain,
"original_record_type": $record_type,
"ip": $ip,
"success": ($success | test("true")),
"create_errors": ($create_errors | fromjson)
}')
echo "$JSON_PAYLOAD"
RESPONSE=$(curl -s -X POST https://n8n.bigscoots.dev/webhook/wpo/cf-ent-setup \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
echo "API Response: ${RESPONSE}"
}
function GET_DNS_RECORD_ID() {
curl --silent --location "${CFAPIURL}/zones/$DOMAIN_CF_ZONEID/dns_records?name=$CFAPI_CANONICALDOMAIN" \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $DOMAIN_CF_APIKEY" \
-H "X-Auth-Email: $DOMAIN_CF_EMAIL" | jq -r '.result[0].id'
}
enable_performance_plan() {
local api_url="https://main.bigscoots.com/bscache-usage-log/api/"
local content_type="Content-Type: application/json"
local security_header="x-bigscoots-user: webmaster"
local server_ip="$serverip"
local hostname="$CFAPI_CANONICALDOMAIN"
local server_hostname="$(hostname)"
local data='{
"action": "enable_plan",
"hostname": "'"$hostname"'",
"server_ip": "'"$server_ip"'",
"server_hostname": "'"$server_hostname"'",
"plan": "performance+"
}'
local response=$(curl -s --header "$content_type" --header "$security_header" --data "$data" "$api_url")
if [[ $response == *"\"success\": false"* ]]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`enable_standard_plan\`" "$hostname" "$response"
fi
}
update_master_db() {
local api_url="https://main.bigscoots.com/cf-custom-hostnames/"
local content_type="Content-Type: application/json"
local security_header="x-bigscoots-user: webmaster"
local hostname="$CFAPI_CANONICALDOMAIN"
local step3_file_path="/root/cfplugin/${DOMAIN}.step3.api"
local custom_host_name_id
if [ ! -f "$step3_file_path" ]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`update_master_db\`" "$hostname" "File does not exist. \`\`\`file: $step3_file_path\`\`\`"
return 1
fi
custom_host_name_id=$(cat "$step3_file_path" | jq -r ".result.id")
if [ -z "$custom_host_name_id" ] || [ "$custom_host_name_id" == "null" ]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`update_master_db\`" "$hostname" "Custom Hostname ID is empty. \`\`\`file: $step3_file_path\`\`\`"
return 1
fi
local data='{
"action": "add_record",
"hostname": "'"$hostname"'",
"hostname_id": "'"$custom_host_name_id"'"
}'
local response=$(curl -s --header "$content_type" --header "$security_header" -X POST --data "$data" "$api_url")
if [[ $response == *"\"success\": false"* ]]
then
send_slack_alert "#wpo-alerts" ":warning:" "Function: \`update_master_db\`" "$hostname" "$response"
fi
}
# If --run is provided, execute the main process
if [[ $RUN -eq 1 ]]; then
main_process() {
if [[ -z "$DOMAIN_CF_ZONEID" && -n "$DOMAIN_CF_EMAIL" && -n "$DOMAIN_CF_APIKEY" ]]
then
DOMAIN_CF_ZONEID=$(GET_ZONE_ID)
fi
HASH=$(get_wpo_api_hash)
GEN_PKEY
DEPLOY_PKEY
FINALSTEPS
GATHERCFAPI
FIX_NONCANONICAL_DNS
ADDDNSCFAPI
ADDCHNAMECFAPI
MDFYCHNAMECFAPI
GETCHNAMEINFO
VRFYCFAPI
# Now changes to the free Cloudflare account
UPDATE_DNS_RECORD
GRAY_CLOUD_DOMAIN
enable_performance_plan
update_master_db
CHK_CF_CUSTOM_HOSTNAME_STATUS
UPDATE_DNS_CFENT_CNAME
}
# Run the main process directly
main_process
exit 0
fi
# If --run is not provided, start the process in a screen session
SCREEN_NAME="cf_deploy_${DOMAIN}"
echo '{"errors": [], "messages": ["Process started successfully"], "success": true, "result": {}}'
screen -dmS "$SCREEN_NAME" bash -c "$0 --domain \"$DOMAIN\" --ip \"$IP\" --email \"$DOMAIN_CF_EMAIL\" --apikey \"$DOMAIN_CF_APIKEY\" $ZONEID_ARG --run"