- Add nginx site template + sync-mev-control-gui-defi-oracle.sh - NPM fleet: mev.defi-oracle.io + www.mev; Cloudflare set-mev-defi-oracle-dns.sh - ip-addresses + .env.master.example: MEV_ADMIN_API_* and web root vars - Runbook MEV_CONTROL_DEFI_ORACLE_IO_DEPLOYMENT.md; AGENTS, MASTER_INDEX, ALL_VMIDS Made-with: Cursor
152 lines
5.0 KiB
Bash
Executable File
152 lines
5.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Publish mev.defi-oracle.io and www.mev.defi-oracle.io (same edge mode as info.defi-oracle.io).
|
|
# Requires CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO and Cloudflare credentials (see set-info-defi-oracle-dns-to-vmid2400-tunnel.sh).
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
cd "$PROJECT_ROOT"
|
|
|
|
source "$PROJECT_ROOT/config/ip-addresses.conf" 2>/dev/null || true
|
|
if [[ -f "$PROJECT_ROOT/.env" ]]; then
|
|
set +u
|
|
source "$PROJECT_ROOT/.env" 2>/dev/null || true
|
|
set -u
|
|
fi
|
|
|
|
TUNNEL_ID="${VMID2400_TUNNEL_ID:-${CLOUDFLARE_TUNNEL_ID_VMID2400:-26138c21-db00-4a02-95db-ec75c07bda5b}}"
|
|
ZONE_ID="${CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO:-}"
|
|
TUNNEL_TARGET="${TUNNEL_ID}.cfargotunnel.com"
|
|
EDGE_MODE="${MEV_DEFI_ORACLE_EDGE_MODE:-${INFO_DEFI_ORACLE_EDGE_MODE:-auto}}"
|
|
PUBLIC_EDGE_IP="${MEV_DEFI_ORACLE_PUBLIC_IP:-${INFO_DEFI_ORACLE_PUBLIC_IP:-${PUBLIC_IP:-}}}"
|
|
ACCOUNT_ID="${CLOUDFLARE_ACCOUNT_ID:-}"
|
|
HOSTS=( "mev.defi-oracle.io" "www.mev.defi-oracle.io" )
|
|
|
|
if [[ -z "$ZONE_ID" ]]; then
|
|
echo "CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO is required." >&2
|
|
exit 1
|
|
fi
|
|
|
|
cf_api() {
|
|
local method="$1"
|
|
local endpoint="$2"
|
|
local data="${3:-}"
|
|
local url="https://api.cloudflare.com/client/v4/zones/${ZONE_ID}${endpoint}"
|
|
|
|
if [[ -n "${CLOUDFLARE_API_TOKEN:-}" ]]; then
|
|
if [[ -n "$data" ]]; then
|
|
curl -s -X "$method" "$url" -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json" --data "$data"
|
|
else
|
|
curl -s -X "$method" "$url" -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json"
|
|
fi
|
|
elif [[ -n "${CLOUDFLARE_EMAIL:-}" && -n "${CLOUDFLARE_API_KEY:-}" ]]; then
|
|
if [[ -n "$data" ]]; then
|
|
curl -s -X "$method" "$url" -H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY" -H "Content-Type: application/json" --data "$data"
|
|
else
|
|
curl -s -X "$method" "$url" -H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY" -H "Content-Type: application/json"
|
|
fi
|
|
else
|
|
echo "Cloudflare credentials are required." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
cf_global_api() {
|
|
local method="$1"
|
|
local url="$2"
|
|
if [[ -n "${CLOUDFLARE_API_TOKEN:-}" ]]; then
|
|
curl -s -X "$method" "$url" -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json"
|
|
elif [[ -n "${CLOUDFLARE_EMAIL:-}" && -n "${CLOUDFLARE_API_KEY:-}" ]]; then
|
|
curl -s -X "$method" "$url" -H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY" -H "Content-Type: application/json"
|
|
else
|
|
echo "Cloudflare credentials are required." >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
resolve_account_id() {
|
|
if [[ -n "$ACCOUNT_ID" ]]; then
|
|
printf '%s\n' "$ACCOUNT_ID"
|
|
return 0
|
|
fi
|
|
local response
|
|
response="$(cf_global_api GET "https://api.cloudflare.com/client/v4/accounts")"
|
|
ACCOUNT_ID="$(printf '%s\n' "$response" | jq -r '.result[0].id // empty')"
|
|
printf '%s\n' "$ACCOUNT_ID"
|
|
}
|
|
|
|
tunnel_exists() {
|
|
local account_id
|
|
account_id="$(resolve_account_id)"
|
|
[[ -z "$account_id" ]] && return 1
|
|
local response
|
|
response="$(cf_global_api GET "https://api.cloudflare.com/client/v4/accounts/${account_id}/cfd_tunnel/${TUNNEL_ID}")"
|
|
printf '%s\n' "$response" | jq -e '.success == true' >/dev/null 2>&1
|
|
}
|
|
|
|
delete_conflicting_records() {
|
|
local name="$1"
|
|
local existing
|
|
existing="$(cf_api GET "/dns_records?name=${name}")"
|
|
printf '%s\n' "$existing" | jq -r '.result[]? | "\(.id) \(.type)"' | while read -r record_id record_type; do
|
|
[[ -z "$record_id" ]] && continue
|
|
if [[ "$record_type" == "A" || "$record_type" == "AAAA" || "$record_type" == "CNAME" ]]; then
|
|
cf_api DELETE "/dns_records/${record_id}" >/dev/null
|
|
fi
|
|
done
|
|
}
|
|
|
|
create_cname() {
|
|
local name="$1"
|
|
local payload
|
|
payload="$(jq -n --arg name "$name" --arg content "$TUNNEL_TARGET" '{type:"CNAME",name:$name,content:$content,proxied:true,ttl:1}')"
|
|
cf_api POST "/dns_records" "$payload" | jq -e '.success == true' >/dev/null
|
|
}
|
|
|
|
create_a_record() {
|
|
local name="$1"
|
|
local payload
|
|
payload="$(jq -n --arg name "$name" --arg content "$PUBLIC_EDGE_IP" '{type:"A",name:$name,content:$content,proxied:true,ttl:1}')"
|
|
cf_api POST "/dns_records" "$payload" | jq -e '.success == true' >/dev/null
|
|
}
|
|
|
|
TARGET_MODE="$EDGE_MODE"
|
|
if [[ "$TARGET_MODE" == "auto" ]]; then
|
|
if tunnel_exists; then
|
|
TARGET_MODE="tunnel"
|
|
else
|
|
TARGET_MODE="public_ip"
|
|
fi
|
|
fi
|
|
|
|
case "$TARGET_MODE" in
|
|
tunnel)
|
|
echo "Publishing mev.defi-oracle.io hostnames to tunnel ${TUNNEL_TARGET}"
|
|
;;
|
|
public_ip|npmplus)
|
|
echo "Publishing mev.defi-oracle.io hostnames to public edge ${PUBLIC_EDGE_IP}"
|
|
;;
|
|
*)
|
|
echo "Unsupported EDGE_MODE=${TARGET_MODE}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
if [[ "$TARGET_MODE" != "tunnel" ]] && [[ -z "$PUBLIC_EDGE_IP" ]]; then
|
|
echo "Set PUBLIC_IP (or MEV_DEFI_ORACLE_PUBLIC_IP / INFO_DEFI_ORACLE_PUBLIC_IP) for A-record mode." >&2
|
|
exit 1
|
|
fi
|
|
|
|
for host in "${HOSTS[@]}"; do
|
|
delete_conflicting_records "$host"
|
|
if [[ "$TARGET_MODE" == "tunnel" ]]; then
|
|
create_cname "$host"
|
|
else
|
|
create_a_record "$host"
|
|
fi
|
|
echo " - ${host}"
|
|
done
|
|
|
|
echo "Done."
|