Based on Debian 10 "Buster" environment.

DNS

There are some choices for DNS servers. BIND is one of the most popular with the full of functionalities, which is too much for me.
NSD and Knot DNS are simple, lightweight, and reliable alternatives for BIND. Since Knot DNS can automatically take care of DNSSEC keys and signings, I choose Knot DNS this time.

  • I used NSD for several years without any problem.
  • My domain registrar doesn't provide the service for DNSSEC. I choose Knot DNS for the time they open the service.

Install

Here I used the official Debian package, version 2.7.6. The documents for this version is still available here.

# apt install knot
# ufw allow 'knot'

Knot latest packages for Debian are available at the Knot official page.

Configuration

knot.conf

The Debian package version has slightly different default configuration than the official document.

/etc/knot/knot.conf

server:
    rundir: "/run/knot"
    user: knot:knot
    listen: [ 0.0.0.0@53, ::@53 ]  # Change IP address to accept the query from any

* snip *

template:
  - id: default
    storage: "/var/lib/knot"
    semantic-checks: on       # Add this line for extra checks
    file: "%s.zone"

As described here, the configuration for each domain should be stored in /var/lib/knot with the name "example.jp.zone".
The line "semantic-checks: on" is added to enable the extra checks for zone files.

For "zone" section, just adding the domain means "use default".

zone:
  - domain: example.jp

Zone file

The example of a zone file is on the Knot website. It looks just like standard zone files.

$ORIGIN example.jp.
$TTL 86400

@       SOA     ns01    info.example.jp. (
                2020010101      ; serial
                1d              ; refresh
                1h              ; retry
                1w              ; expire
                1h              ; negative cache TTL
                )

        NS      ns01
        NS      ns02
        MX      10 ns01
        TXT     "v=spf1 mx ~all"
        A       192.0.2.3
        AAAA    2001:DB8::3

After knot.conf and zone files are ready, restart Knot.

# systemctl restart knot

When the bind-address is changed, the whole knot has to be restarted.
In other cases, knotc command will take care.

For the configuration (knot.conf) and zone files reload,

# knotc reload

For the zone files reload,

# knotc zone-reload

Please refer the knotc command help for more info.

Check

Check if Knot will answer the query as expected.

$ dig example.jp @localhost

; <<>> DiG 9.11.5-P4-5.1-Debian <<>> example.jp @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27190
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.jp.                    IN      A

;; ANSWER SECTION:
example.jp.             86400   IN      A       192.0.2.3

;; Query time: 0 msec
;; SERVER: ::1#53(::1)
;; WHEN: Mon Jan 13 15:21:05 JST 2020
;; MSG SIZE  rcvd: 58

Master and Slave servers

For the redundancy, at least 2 DNS servers should be active.
One will be the master with zone files, and the second will be the slave as a mirror backup.

TSIG key

TSIG key can be generated by the keymgr command.

# keymgr -t key01

Then you will get the generated key and configuration.

# hmac-sha256:key01:799BI/gZTo1wvoX1D8PRGcKbfQ22N4HvQeq5rpmmZV8=
key:
  - id: key01
    algorithm: hmac-sha256
    secret: 799BI/gZTo1wvoX1D8PRGcKbfQ22N4HvQeq5rpmmZV8=

Copy the configuration displayed and paste it to the knot.conf.
Note: Never use the secret displayed here. Please generate your own key.

Master configuration

Knot will run as a master server if not specified to be the slave. Add remote (slave) server address, key, acl section and modify template section to use them.

/etc/knot/knot.conf

key:
  - id: key01
    algorithm: hmac-sha256
    secret: 799BI/gZTo1wvoX1D8PRGcKbfQ22N4HvQeq5rpmmZV8=

remote:
  - id: slave
    address: [ 2001:db8::1, 192.168.2.0 ]
    key: key01

acl:
  - id: allow_transfer
    address: [ 2001:db8::1, 192.168.2.0 ]
    key: key01
    action: transfer

template:
  - id: default
    storage: "/var/lib/knot"
    semantic-checks: on
    file: "%s.zone"
    notify: slave            # Specify the server to send out notifications
    acl: allow_transfer      # Apply ACL

Reload knot to apply the new configuration.

# knotc reload

Slave configuration

After installation, zone files are not required for the slave servers since all the information should come from the master server.
The TSIG key secret must be exactly the same as the master.

key:
  - id: key01
    algorithm: hmac-sha256
    secret: 799BI/gZTo1wvoX1D8PRGcKbfQ22N4HvQeq5rpmmZV8=

remote:
  - id: master
    address: [ 2001:db8::1, 192.168.2.0 ]
    key: key01

acl:
  - id: allow_notify
    address: [ 2001:db8::1, 192.168.2.0 ]
    key: key01
    action: notify

template:
  - id: default
    storage: "/var/lib/knot"
    file: "%s.zone"
    master: master           # Specify the master server
    acl: allow_notify        # Apply ACL

In case if slave server doesn't get the latest information, force retransfer at the slave server.

# knotc zone-retransfer