Commit 8f5f4c13c74e
Changed files (1)
tools
tools/update-gandi-dns.sh
@@ -24,6 +24,14 @@ DOMAIN_ZONE_FILES["demeester.fr"]="./systems/common/services/dns/demeester.fr.ni
ALL_DOMAINS=("sbr.pm" "demeester.fr")
SELECTED_DOMAINS=()
+# HTTPS DNS records (RFC 9460) per domain
+# These can't be expressed in nix-community/dns.nix yet, so we manage them here.
+# Format: "name:priority target params" (name is @ for apex)
+# See: https://docs.gandi.net/en/domain_names/faq/record_types/https_record.html
+declare -A DOMAIN_HTTPS_RECORDS
+# Note: Gandi requires an explicit FQDN target (not ".") for HTTPS records.
+DOMAIN_HTTPS_RECORDS["demeester.fr"]='@:1 demeester.fr. alpn="h3,h2"|vincent:1 vincent.demeester.fr. alpn="h3,h2"|www:1 www.demeester.fr. alpn="h3,h2"|*:1 demeester.fr. alpn="h3,h2"'
+
# Parse arguments
for arg in "$@"; do
case $arg in
@@ -106,6 +114,7 @@ update_domain() {
grep -v "^;" || true)
# Extract MX records
+ # shellcheck disable=SC2034
MX_RECORDS=$(grep -E "^\S+\s+(([0-9]+\s+)?IN\s+)?MX\s+" "$TEMP_ZONE" | \
grep -v "^;" || true)
@@ -151,7 +160,7 @@ update_domain() {
if [[ "$FULL_NAME" == "$DOMAIN." ]]; then
NAME="@"
else
- NAME="${FULL_NAME%.$DOMAIN.}"
+ NAME="${FULL_NAME%."$DOMAIN".}"
fi
DESIRED_NAMES["$NAME"]=1
@@ -217,7 +226,7 @@ update_domain() {
VALUE=$(echo "$line" | awk '{print $4}')
fi
- NAME="${FULL_NAME%.$DOMAIN.}"
+ NAME="${FULL_NAME%."$DOMAIN".}"
echo -e "${BLUE}Processing: ${RESET}$NAME.$DOMAIN CNAME $VALUE (TTL: $TTL)"
@@ -276,7 +285,7 @@ update_domain() {
if [[ "$FULL_NAME" == "$DOMAIN." ]]; then
NAME="@"
else
- NAME="${FULL_NAME%.$DOMAIN.}"
+ NAME="${FULL_NAME%."$DOMAIN".}"
fi
# Extract TXT value (everything after TXT, keeping quotes)
@@ -353,6 +362,64 @@ update_domain() {
unset TXT_BY_NAME
fi
+ # Process HTTPS records (RFC 9460 / TYPE65)
+ if [[ -n "${DOMAIN_HTTPS_RECORDS[$DOMAIN]+_}" ]]; then
+ echo -e "${BOLD}${BLUE}Processing HTTPS (TYPE65) records...${RESET}"
+ echo
+
+ IFS='|' read -ra HTTPS_ENTRIES <<< "${DOMAIN_HTTPS_RECORDS[$DOMAIN]}"
+ for entry in "${HTTPS_ENTRIES[@]}"; do
+ NAME="${entry%%:*}"
+ VALUE="${entry#*:}"
+
+ echo -e "${BLUE}Processing: ${RESET}$NAME.$DOMAIN HTTPS $VALUE"
+
+ if [[ "$DRY_RUN" == "true" ]]; then
+ echo -e " ${CYAN}[DRY RUN] Would update/create HTTPS record${RESET}"
+ UPDATED=$((UPDATED + 1))
+ else
+ CURRENT_VALUE=$(echo "$CURRENT_RECORDS" | jq -r \
+ --arg name "$NAME" \
+ --arg type "HTTPS" \
+ '.[] | select(.rrset_name == $name and .rrset_type == $type) | .rrset_values[0]' \
+ 2>/dev/null || echo "")
+
+ if [[ "$CURRENT_VALUE" == "$VALUE" ]]; then
+ echo -e " ${GREEN}โ Record unchanged, skipping${RESET}"
+ SKIPPED=$((SKIPPED + 1))
+ else
+ if [[ -z "$CURRENT_VALUE" ]]; then
+ echo -e " ${YELLOW}Creating new HTTPS record...${RESET}"
+ else
+ echo -e " ${YELLOW}Updating HTTPS record (was: $CURRENT_VALUE)...${RESET}"
+ fi
+
+ PAYLOAD=$(jq -n --arg v "$VALUE" '{rrset_values: [$v], rrset_ttl: 10800}')
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
+ -X PUT \
+ -H "Authorization: Bearer $GANDIV5_PERSONAL_TOKEN" \
+ -H "Content-Type: application/json" \
+ -d "$PAYLOAD" \
+ "$API_URL/$NAME/HTTPS")
+
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
+ BODY=$(echo "$RESPONSE" | sed '$d')
+
+ if [[ "$HTTP_CODE" == "201" ]] || [[ "$HTTP_CODE" == "200" ]]; then
+ echo -e " ${GREEN}โ HTTPS record updated successfully${RESET}"
+ UPDATED=$((UPDATED + 1))
+ else
+ echo -e " ${RED}โ Failed to update HTTPS record (HTTP $HTTP_CODE)${RESET}"
+ echo -e " ${RED}Response: $BODY${RESET}"
+ FAILED=$((FAILED + 1))
+ fi
+ fi
+ fi
+
+ echo
+ done
+ fi
+
# Remove stale A records from Gandi that are no longer in Nix config
echo -e "${BOLD}${BLUE}Checking for stale A records to remove...${RESET}"
echo