2026年6月11日
2026年6月11日
NSD で複数ゾーンを管理する設定|ゾーン一覧から設定を生成し、一括検証とシリアル確認を自動化する
NSD で数十〜数百のゾーンを扱うなら、ゾーンの一覧を1つのテキストファイルで管理し、そこから nsd.conf に読み込ませるゾーン設定を自動生成して、全ゾーンの文法チェック、反映、全サーバーでのシリアルの一致確認までをスクリプトで流す運用にすると、手作業の漏れを減らせます。この記事では、ファイルの構成、include による設定の分割、生成と反映のスクリプト、シリアルの確認、ゾーンの追加と削除の順番、Git での管理までを説明します。
共通の設定を pattern にまとめる基本はこの記事でも使いますが、ここでの主題は「ゾーンが増えても同じ手順で漏れなく回せる仕組み」です。内容は NSD 4.x 系を前提にしています(2026年10月現在)。設定項目やコマンドは版によって追加・変更されることがあるため、nsd -v で手元の版を確かめ、同梱のマニュアル(nsd.conf(5)、nsd-control(8))と照らし合わせてください。スクリプトは例なので、検証環境で動きを確かめてから本番に入れます。
ファイルの構成を決める
手で書く設定と、機械で作る設定を分けておくのが要点です。
/etc/nsd/
├── nsd.conf # server・remote-control・key・pattern(手で書く)
├── zones.list # 「ゾーン名 pattern名」の一覧(手で書く)
├── zones.conf # zones.list から生成するゾーン設定(手で編集しない)
└── zones/ # ゾーンファイル(Git で管理)
├── example.com.zone
└── example.net.zone
zones.conf を手で直すと、次に生成したときに上書きされて変更が消えます。ファイルの先頭に「生成物なので編集しない」と書き出しておくと、ほかの担当者が触る事故を防げます。
nsd.conf:共通部分と include
# /etc/nsd/nsd.conf
server:
ip-address: 192.0.2.1
zonesdir: "/etc/nsd/zones"
remote-control:
control-enable: yes
control-interface: 127.0.0.1
key:
name: "xfr-key"
algorithm: hmac-sha256
secret: "your-base64-secret"
key:
name: "ext-key"
algorithm: hmac-sha256
secret: "your-other-base64-secret"
# 自社のセカンダリへ配るゾーン
pattern:
name: "primary"
zonefile: "%s.zone"
notify: 198.51.100.2 xfr-key
provide-xfr: 198.51.100.2 xfr-key
# 外部のセカンダリサービスにも配るゾーン
pattern:
name: "primary-ext"
include-pattern: "primary"
notify: 203.0.113.53 ext-key
provide-xfr: 203.0.113.53 ext-key
include: "/etc/nsd/zones.conf"
secret はダミーです。実際の値は openssl rand -base64 32 などで作り、nsd.conf の読み取り権限を nsd と管理者だけに絞ります。
pattern は「ゾーンの扱いの種類」ごとに作ります。上の例では、自社のセカンダリだけに配るゾーンと、外部のセカンダリサービスにも配るゾーンを分け、後者は前者を include-pattern で取り込んでいます。DNSSEC で署名したゾーンを配る場合は、zonefile: "%s.zone.signed" のように署名済みのファイルを読む pattern を別に作ると、署名前のファイルを誤って配る事故を防げます。NSD 自身は署名を行わないため、署名は外部のツールで行い、NSD は署名済みのゾーンを配る役に徹します。
zones.list と生成スクリプト
# /etc/nsd/zones.list
# ゾーン名 pattern名
example.com primary
example.net primary
shop.example.org primary-ext
この一覧から zones.conf を作り、検証に通ったときだけ差し替えて反映するスクリプトの例です。
#!/bin/bash
# /usr/local/sbin/nsd-deploy.sh
set -euo pipefail
cd /etc/nsd
# 1. zones.list から新しい zones.conf を作る
{
echo "# zones.list から自動生成。手で編集しないこと"
while read -r zone pattern; do
case "$zone" in ''|'#'*) continue ;; esac
printf 'zone:\n name: "%s"\n include-pattern: "%s"\n\n' "$zone" "$pattern"
done < zones.list
} > zones.conf.new
# 2. 全ゾーンのゾーンファイルを検査する
fail=0
while read -r zone pattern; do
case "$zone" in ''|'#'*) continue ;; esac
nsd-checkzone "$zone" "zones/$zone.zone" > /dev/null || { echo "NG: $zone"; fail=1; }
done < zones.list
[ "$fail" -eq 0 ] || { echo "ゾーンファイルに誤りがあるため中止"; exit 1; }
# 3. 差し替えて設定全体を検査し、だめなら元に戻す
cp -p zones.conf zones.conf.bak
mv zones.conf.new zones.conf
if ! nsd-checkconf nsd.conf; then
mv zones.conf.bak zones.conf
echo "nsd.conf の検査に失敗したため元に戻した"
exit 1
fi
# 4. ゾーンの増減を反映し、変更のあったゾーンを読み直す
nsd-control reconfig
nsd-control reload
流れのポイントは次のとおりです。
- 検査してから差し替える:ゾーンファイルの誤りを先に見つけ、設定ファイルは差し替えたうえで
nsd-checkconfに通し、失敗したら元に戻します。初回はzones.confが無いので、空のファイルを作ってから実行します。 - **
reconfigとreloadの役割の違い**:nsd-control reconfigは nsd.conf を読み直し、pattern や鍵の変更と、設定に書かれたゾーンの追加・削除を反映します。待ち受けアドレスの変更など、再起動しないと反映されない項目もあります。nsd-control reloadは、変更のあったゾーンファイルを読み直します。 - 途中で止める:
set -eと明示的なexit 1で、どこかで失敗したら先へ進まないようにしています。1つのゾーンの誤りで全体の反映を止める考え方です。誤りのあるゾーンだけ外して残りを反映したい場合もありますが、そのゾーンが古い内容のまま残ることに気付きにくくなるため、まずは止める運用から始めるのが無難です。
シリアルを全サーバーで突き合わせる
ゾーンファイルを直したのに SOA のシリアルを上げ忘れると、プライマリの NSD は新しい内容で答えても、セカンダリは「更新なし」と判断して古い内容を配り続けます。ゾーンが多いほど見落としやすいため、反映後に全サーバーのシリアルを比べるスクリプトを用意します。
#!/bin/bash
# /usr/local/sbin/nsd-serial-check.sh
# 1列目のサーバー(プライマリ)とシリアルが違うものを表示する
servers="192.0.2.1 198.51.100.2 203.0.113.53"
while read -r zone pattern; do
case "$zone" in ''|'#'*) continue ;; esac
line="$zone"
for s in $servers; do
serial=$(dig @"$s" +short +norec +time=3 "$zone" SOA | awk '{print $3}')
line="$line ${serial:-NG}"
done
echo "$line"
done < /etc/nsd/zones.list | awk '{ for (i = 3; i <= NF; i++) if ($i != $2) { print "MISMATCH:", $0; next } }'
外部のセカンダリサービスにだけ配っていないゾーンもあるので、実際には pattern ごとに比べるサーバーを変えます。反映の直後はゾーン転送が終わっていないことがあるため、数分おいてから実行するか、定期実行で「同じゾーンが続けて不一致」のときだけ通知するようにします。NG は応答が無かったことを表し、そのサーバーがゾーンを持っていない(設定漏れ)か、到達できないかのどちらかです。
シリアルは 2026101801(年月日+2桁の連番)の形式が分かりやすく、1日に100回未満の更新なら番号が足りなくなりません。シリアルは大きい値へ進める前提の仕組みで、誤って大きな値にすると戻すのに手間がかかるため、手で書き換えるより、編集のたびにスクリプトで上げる運用が安全です。
セカンダリ側に NSD を使っている場合は、nsd-control zonestatus で各ゾーンの状態(正常か、更新を試みている途中か、期限切れか)も確認できます。
ゾーンの追加と削除の順番
追加するときは、NSD 側の準備を先に済ませます。
- ゾーンファイルを
zones/に置き、zones.listに1行足す - セカンダリ側にも同じゾーンを設定する
nsd-deploy.shを実行し、nsd-serial-check.shで全サーバーが同じシリアルを返すことを確認する- 最後に、ドメインの登録事業者でネームサーバーをこれらのサーバーに向ける
削除するときは逆の順番です。先に登録事業者側でネームサーバーを別のサーバーへ移し、NS レコードの TTL が切れるのを待ってから、NSD とセカンダリからゾーンを外します。先に NSD から消すと、委任だけが残った状態(レイムデリゲーション)になり、そのドメインの名前が引けなくなったり不安定になったりします。
Git で管理し、レビューを通す
zones.list と zones/ を Git のリポジトリにすると、誰がいつどのレコードを変えたかを追えるようになり、問題があったときに直前の状態へ戻すのも簡単です。
- 変更はブランチで行い、CI で変更されたゾーンに
nsd-checkzoneをかける - ゾーンファイルが変わっているのに SOA の行が変わっていない差分を、CI で警告する
- 本番への配布は、リポジトリの内容を rsync や構成管理ツールで
/etc/nsd/に置いてからnsd-deploy.shを実行する
TSIG の鍵(nsd.conf の secret)はリポジトリに入れず、サーバー上で別ファイルにして管理します。
なお、nsd-control addzone でゾーンを足す方法もありますが、その場合ゾーンの一覧は nsd.conf ではなく NSD が管理する一覧ファイル(zonelistfile)に記録されます。この記事の方式と混ぜると、同じゾーンがどちらで管理されているのか分からなくなるため、どちらか一方に統一します。
まとめ
- 手で書く nsd.conf・zones.list と、自動生成する zones.conf を分け、
includeで読み込みます。 - 生成スクリプトでは、全ゾーンの
nsd-checkzoneとnsd-checkconfに通ってから差し替え、nsd-control reconfigとreloadで反映します。 - 反映後は全サーバーの SOA シリアルを突き合わせ、シリアルの上げ忘れやセカンダリの設定漏れを見つけます。
- 追加は NSD 側を先に、削除は登録事業者側を先に行い、ゾーンの一覧とゾーンファイルは Git で管理します。