Stuff.
  • Home
  • Categories
  • Tags
  • Archives

Incrementing DNS SOA serial

Many sysadmins edit zone files manually. Some script it. Both need a way to increment the SOA serial when a change is made. Here is a sh-compatible, fully POSIX, shellcheck-clean script to do that atomically. You should modify it to suit your own needs.

This example shows additionally how to incorporate it in a Let's Encrypt hook using NSD as your primary name server.

#!/bin/sh

# Increment standard SOA serial
# Also optionally add Let's Encrypt record as part of a hook.
# Note: the first 10-digit number in the zone will be overwritten (y3k protection :P)
# To guarantee safety, the SOA record must be the first record in the zone file.

set -e

zonefile=/etc/nsd/alxu.ca.zone

exec 9<"$zonefile"

flock -n 9

oldzone="$(cat <&9)"

#             Y    Y    Y    Y    M    M    D    D    N    N
serialglob="[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"

 preserial="${oldzone%%$serialglob*}"
postserial="${oldzone#*$serialglob}"

tmp="${oldzone#$preserial}"
serial="${tmp%$postserial}"
case "$serial" in
    $serialglob) ;;
    *) echo 'zone file not in correct format, aborting'; exit 1
esac
serd="${serial%[0-9][0-9]}"
sern="${serial#[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]}"

nowd="$(date +%Y%m%d)"
if [ "$serd" = "$nowd" ]; then
    if [ "$sern" = 99 ]; then
        echo 'serial number is already 99, cannot increment, aborting' >&2
        exit 1
    fi
    newser="$serd$(printf "%02d" $((sern+1)))"
else
    newser="${nowd}00"
fi

echo "Editing zone file" >&2

# Let's Encrypt
printf '%s\n_acme-challenge.%s. 60 IN TXT %s\n' "$preserial$newser$postserial" "$1" "$2" > "$zonefile.new"
mv "$zonefile.new" "$zonefile"

# just output the zone
#printf '%s\n' "$preserial$newser$postserial" > "$zonefile.new"
#mv "$zonefile.new" "$zonefile"

printf "Reloading nsd: " >&2

nsd-control reload

echo "Waiting for axfr" >&2

# wait for nsd axfr, journalctl is dumb
sh -s << 'EOF' || true
journalctl -f -u nsd -n 0 | grep --line-buffered 'axfr for' | while read -r _; do
kill $$
# hopefully journalctl doesn't stick around too long
exit
done
EOF

Published

Jul 13, 2017

Category

misc
  • Creative Commons Licence
    Released under a Creative Commons Attribution-ShareAlike 4.0 International License.
  • Powered by Pelican. Theme: Elegant by Talha Mansoor