doran/scripts/hetzner/configure-cloudflare-dns.sh
2026-03-29 10:28:09 +02:00

87 lines
2.5 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
: "${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}"
: "${CLOUDFLARE_ZONE_ID:?set CLOUDFLARE_ZONE_ID}"
: "${BASE_DOMAIN:?set BASE_DOMAIN}"
: "${PUBLIC_DOMAIN:=$BASE_DOMAIN}"
: "${DNS_MODE:=upsert}"
api() {
curl -fsS -X "$1" "https://api.cloudflare.com/client/v4$2" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H 'Content-Type: application/json' \
${3:+--data "$3"}
}
lookup_record_id() {
local type="$1"
local name="$2"
curl -fsS "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/dns_records?type=$type&name=$name" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H 'Content-Type: application/json' | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d["result"][0]["id"] if d.get("result") else "")'
}
upsert_record() {
local type="$1"
local name="$2"
local content="$3"
local proxied="${4:-false}"
local existing_id
existing_id=$(lookup_record_id "$type" "$name")
local payload
payload=$(printf '{"type":"%s","name":"%s","content":"%s","ttl":120,"proxied":%s}' "$type" "$name" "$content" "$proxied")
if [[ -n "$existing_id" ]]; then
api PUT "/zones/$CLOUDFLARE_ZONE_ID/dns_records/$existing_id" "$payload" >/dev/null
else
api POST "/zones/$CLOUDFLARE_ZONE_ID/dns_records" "$payload" >/dev/null
fi
}
delete_record() {
local type="$1"
local name="$2"
local existing_id
existing_id=$(lookup_record_id "$type" "$name")
if [[ -n "$existing_id" ]]; then
api DELETE "/zones/$CLOUDFLARE_ZONE_ID/dns_records/$existing_id" >/dev/null
echo "deleted $type $name"
else
echo "skipped missing $type $name"
fi
}
records=(
"$PUBLIC_DOMAIN"
"git.$PUBLIC_DOMAIN"
"registry.$PUBLIC_DOMAIN"
"grafana.$PUBLIC_DOMAIN"
"headlamp.$PUBLIC_DOMAIN"
)
case "$DNS_MODE" in
upsert)
: "${SERVER_IP:?set SERVER_IP}"
upsert_record A "${records[0]}" "$SERVER_IP" false
upsert_record A "${records[1]}" "$SERVER_IP" false
upsert_record A "${records[2]}" "$SERVER_IP" false
upsert_record A "${records[3]}" "$SERVER_IP" false
upsert_record A "${records[4]}" "$SERVER_IP" false
echo "cloudflare dns updated for ${records[*]}"
;;
delete)
delete_record A "${records[0]}"
delete_record A "${records[1]}"
delete_record A "${records[2]}"
delete_record A "${records[3]}"
delete_record A "${records[4]}"
echo "cloudflare dns cleanup finished for ${records[*]}"
;;
*)
echo "unsupported DNS_MODE: $DNS_MODE" >&2
exit 1
;;
esac