Add the following to this file:
#!/bin/bash
# acme.sh DNS API hook for BIND9
BIND_UPDATE_SCRIPT="/usr/local/bin/update_bind9_txt.sh"
dns_bind9_add() {
fulldomain="$1"
txtvalue="$2"
_debug "dns_bind9_add: $fulldomain = $txtvalue"
"$BIND_UPDATE_SCRIPT" "ADD" "$fulldomain" "$txtvalue" || return 1
return 0
}
dns_bind9_rm() {
fulldomain="$1"
txtvalue="$2"
_debug "dns_bind9_rm: $fulldomain (value $txtvalue)"
"$BIND_UPDATE_SCRIPT" "DEL" "$fulldomain" "$txtvalue" || return 0
return 0
}
chmod +x ~/.acme.sh/dns_bind9.sh
Add the following to this file:
#!/bin/bash
# Must be run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root."
exit 1
fi
ACTION="$1" # ADD or DEL
RECORD="$2" # Full domain (_acme-challenge.sub.example.com)
TXT_VALUE="$3"
ZONE_DIR="/etc/bind/zones"
if [[ -z "$ACTION" || -z "$RECORD" || ( "$ACTION" == "ADD" && -z "$TXT_VALUE" ) ]]; then
echo "Usage: $0 ADD|DEL full.domain.name txt-value"
exit 1
fi
# Function to extract zone name from domain
find_zone_name() {
domain="$1"
while [[ "$domain" == *.* ]]; do
zone_candidate="$domain"
zone_file="$ZONE_DIR/$zone_candidate.zone"
if [[ -f "$zone_file" ]]; then
echo "$zone_candidate"
return
fi
domain="${domain#*.}"
done
echo ""
}
ZONE_NAME="$(find_zone_name "$RECORD")"
if [[ -z "$ZONE_NAME" ]]; then
echo "Zone file for $RECORD not found in $ZONE_DIR"
exit 1
fi
ZONE_FILE="$ZONE_DIR/$ZONE_NAME.zone"
# Backup
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
cp "$ZONE_FILE" "$ZONE_FILE.bak_$TIMESTAMP" || exit 1
# Function to increment SOA serial
increment_serial() {
sed -i -E "/; serial/ {
s/([0-9]{10})/\1 + 1/e
}" "$ZONE_FILE"
}
# Build relative name for zone file (strip zone from record)
REL_NAME="${RECORD%.$ZONE_NAME}"
REL_NAME="${REL_NAME%.}" # remove trailing dot if present
if [[ -z "$REL_NAME" || "$REL_NAME" == "$RECORD" ]]; then
REL_NAME="@"
fi
case "$ACTION" in
ADD)
echo "$REL_NAME. 300 IN TXT \"$TXT_VALUE\"" >> "$ZONE_FILE"
;;
DEL)
sed -i "\|^$REL_NAME[[:space:]].*IN[[:space:]]TXT[[:space:]]\"$TXT_VALUE\"|d" "$ZONE_FILE"
;;
*)
echo "Unknown action: $ACTION"
exit 1
;;
esac
increment_serial
# Reload the zone
rndc reload "$ZONE_NAME" || {
echo "Failed to reload zone $ZONE_NAME"
exit 1
}
echo "Successfully updated $ZONE_NAME for record $REL_NAME"
chmod +x /usr/local/bin/update_bind9_txt.sh
[…] Example for Bind9 on Debian 12 […]