Update cf-ddns.sh

Added function to register CNAME to short_host()
This commit is contained in:
saifuddin 2025-10-09 07:28:43 +00:00
parent f7e0e44008
commit c8ee1d6cb2

View File

@ -16,7 +16,7 @@ source "$ENV_FILE"
: "${CF_PROXIED:=false}" : "${CF_PROXIED:=false}"
: "${CF_TTL:=120}" : "${CF_TTL:=120}"
# --- Derive zone/record from system hostname --- # --- Names from system ---
CF_RECORD_NAME="$(hostname -f 2>/dev/null || true)" CF_RECORD_NAME="$(hostname -f 2>/dev/null || true)"
CF_SHORT_NAME="$(hostname -s 2>/dev/null || true)" CF_SHORT_NAME="$(hostname -s 2>/dev/null || true)"
CF_ZONE_NAME="$(hostname -d 2>/dev/null || true)" CF_ZONE_NAME="$(hostname -d 2>/dev/null || true)"
@ -24,26 +24,39 @@ CF_ZONE_NAME="$(hostname -d 2>/dev/null || true)"
[[ -n "$CF_RECORD_NAME" ]] || fail "hostname -s returned empty" [[ -n "$CF_RECORD_NAME" ]] || fail "hostname -s returned empty"
[[ -n "$CF_ZONE_NAME" ]] || fail "hostname -d returned empty (set a DNS/search domain)" [[ -n "$CF_ZONE_NAME" ]] || fail "hostname -d returned empty (set a DNS/search domain)"
# --- short_host(): derive short alias used for the CNAME ---
short_host() {
local short_hostname part1 part2 part3 part4 num_parts second_initial transformed_hostname
short_hostname="$(hostname -s)"
IFS="-" read -r part1 part2 part3 part4 <<< "$short_hostname"
num_parts=$(awk -F'-' '{print NF}' <<< "$short_hostname")
if [ "$num_parts" -eq 4 ]; then
second_initial=${part2:0:1} # kept in case you want it later
transformed_hostname="${part2}-${part4}"
else
transformed_hostname="$short_hostname"
fi
echo "$transformed_hostname"
}
SHORT_ALIAS="$(short_host)"
SHORT_ALIAS_FQDN="${SHORT_ALIAS}.${CF_ZONE_NAME}"
# Safe filename for state # Safe filename for state
safe_name="$(echo "$CF_RECORD_NAME" | tr '/:' '__')" safe_name="$(echo "$CF_RECORD_NAME" | tr '/:' '__')"
LAST_IP_FILE="${STATE_DIR}/last_ipv4_${safe_name}" LAST_IP_FILE="${STATE_DIR}/last_ipv4_${safe_name}"
mkdir -p "$STATE_DIR" mkdir -p "$STATE_DIR"
# --- Detect local IPv4 on default route interface --- # --- Detect local IPv4 on default route interface ---
detect_ip() { detect_ip() {
local iface ip local iface ip
# Prefer ip-route default; fallback to ip route get
iface="$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}')" iface="$(ip route show default 2>/dev/null | awk '/default/ {print $5; exit}')"
if [[ -z "$iface" ]]; then if [[ -z "${iface}" ]]; then
iface="$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for (i=1;i<=NF;i++) if ($i=="dev") {print $(i+1); exit}}')" iface="$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for (i=1;i<=NF;i++) if ($i=="dev") {print $(i+1); exit}}')"
fi fi
[[ -n "$iface" ]] || fail "Could not detect default route interface" [[ -n "$iface" ]] || fail "Could not detect default route interface"
ip="$(ip -4 addr show dev "$iface" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)" ip="$(ip -4 addr show dev "$iface" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)"
[[ -n "$ip" ]] || fail "No IPv4 found on default interface '$iface'" [[ -n "$ip" ]] || fail "No IPv4 found on default interface '$iface'"
echo "$ip" echo "$ip"
} }
@ -65,13 +78,13 @@ zone_id="$(curl -fsS "${hdr[@]}" "${API}/zones?${zone_q}" \
| sed -n 's/.*"id":"\([^"]*\)".*"name":"'"$CF_ZONE_NAME"'".*/\1/p' | head -n1)" | sed -n 's/.*"id":"\([^"]*\)".*"name":"'"$CF_ZONE_NAME"'".*/\1/p' | head -n1)"
[[ -n "$zone_id" ]] || fail "Could not find Zone ID for ${CF_ZONE_NAME}" [[ -n "$zone_id" ]] || fail "Could not find Zone ID for ${CF_ZONE_NAME}"
# 2) Lookup existing A record by name # 2) Lookup existing A record by FQDN
rec_q="type=A&name=$(urlenc "$CF_RECORD_NAME")" rec_q="type=A&name=$(urlenc "$CF_RECORD_NAME")"
record_json="$(curl -fsS "${hdr[@]}" "${API}/zones/${zone_id}/dns_records?${rec_q}")" record_json="$(curl -fsS "${hdr[@]}" "${API}/zones/${zone_id}/dns_records?${rec_q}")"
record_id="$(echo "$record_json" | sed -n 's/.*"id":"\([^"]*\)".*"name":"'"$CF_RECORD_NAME"'".*"type":"A".*/\1/p' | head -n1)" record_id="$(echo "$record_json" | sed -n 's/.*"id":"\([^"]*\)".*"name":"'"$CF_RECORD_NAME"'".*"type":"A".*/\1/p' | head -n1)"
# 3) Create payload + create/update # 3) A record payload + create/update
json_payload() { json_payload_a() {
cat <<JSON cat <<JSON
{"type":"A","name":"${CF_SHORT_NAME}","content":"${current_ip}","ttl":${CF_TTL},"proxied":${CF_PROXIED}} {"type":"A","name":"${CF_SHORT_NAME}","content":"${current_ip}","ttl":${CF_TTL},"proxied":${CF_PROXIED}}
JSON JSON
@ -80,15 +93,42 @@ JSON
if [[ -z "$record_id" ]]; then if [[ -z "$record_id" ]]; then
log "Creating A ${CF_RECORD_NAME} -> ${current_ip}" log "Creating A ${CF_RECORD_NAME} -> ${current_ip}"
curl -fsS -X POST "${hdr[@]}" \ curl -fsS -X POST "${hdr[@]}" \
--data "$(json_payload)" \ --data "$(json_payload_a)" \
"${API}/zones/${zone_id}/dns_records" >/dev/null "${API}/zones/${zone_id}/dns_records" >/dev/null
log "Created." log "A record created."
else else
log "Updating A ${CF_RECORD_NAME} -> ${current_ip}" log "Updating A ${CF_RECORD_NAME} -> ${current_ip}"
curl -fsS -X PUT "${hdr[@]}" \ curl -fsS -X PUT "${hdr[@]}" \
--data "$(json_payload)" \ --data "$(json_payload_a)" \
"${API}/zones/${zone_id}/dns_records/${record_id}" >/dev/null "${API}/zones/${zone_id}/dns_records/${record_id}" >/dev/null
log "Updated." log "A record updated."
fi fi
echo "$current_ip" > "$LAST_IP_FILE" # 4) Create/Update CNAME: SHORT_ALIAS -> CF_RECORD_NAME
if [[ "$SHORT_ALIAS_FQDN" == "$CF_RECORD_NAME" ]]; then
log "SHORT_ALIAS equals CF_RECORD_NAME; skipping CNAME to avoid name conflict."
else
cname_q="type=CNAME&name=$(urlenc "$SHORT_ALIAS_FQDN")"
cname_json="$(curl -fsS "${hdr[@]}" "${API}/zones/${zone_id}/dns_records?${cname_q}")"
cname_id="$(echo "$cname_json" | sed -n 's/.*"id":"\([^"]*\)".*"name":"'"$SHORT_ALIAS_FQDN"'".*"type":"CNAME".*/\1/p' | head -n1)"
json_payload_cname() {
cat <<JSON
{"type":"CNAME","name":"${SHORT_ALIAS}","content":"${CF_RECORD_NAME}","ttl":${CF_TTL},"proxied":${CF_PROXIED}}
JSON
}
if [[ -z "$cname_id" ]]; then
log "Creating CNAME ${SHORT_ALIAS_FQDN} -> ${CF_RECORD_NAME}"
curl -fsS -X POST "${hdr[@]}" \
--data "$(json_payload_cname)" \
"${API}/zones/${zone_id}/dns_records" >/dev/null
log "CNAME created."
else
log "Updating CNAME ${SHORT_ALIAS_FQDN} -> ${CF_RECORD_NAME}"
curl -fsS -X PUT "${hdr[@]}" \
--data "$(json_payload_cname)" \
"${API}/zones/${zone_id}/dns_records/${cname_id}" >/dev/null
log "CNAME updated."
fi
fi
echo "$current_ip" > "$LAST_IP_FILE"