DNS resolution is of paramount importance on a (mail, web) server. It can take a substancial amount of network traffic and it is subject to attacks like poisoning.

We use djbdnsdnscache program as local DNS resolver on each server and set it up as double cache cascade.



Service set up

The following are generic instructions for the basic service setup. You must substitute and with sensible values and configure the DNS cache correctly.

See double cache cascade for the default setup of the service.

sudo -i


# Set up
dnscache-conf Gdnscache Gdnslog /etc/$RESOLVER $IP || >&2
cd /etc/$RESOLVER || cat >&2
chgrp -R staff root
chmod -R g+w root
chmod g+sw root

# Supervise directories
install -d -m 2775 -o root -g staff /var/lib/supervise/$RESOLVER
ln -nfs /var/lib/supervise/$RESOLVER supervise
cd log || cat >&2
install -d -m 2775 -o root -g staff /var/lib/supervise/$RESOLVER.log
ln -nfs /var/lib/supervise/$RESOLVER.log supervise

echo as user set RESOLVER=$RESOLVER again


# Activate service
cd /etc/$RESOLVER || cat >&2
tail -F log/main/current&
ln -s `pwd` /service

# Operator access
sudo chmod g+rw {.,log}/supervise/{ok,control}

# Check
sv stat .

After verifying that the service started with a line like:

@400000005c2b7df728e15adc starting

the log viewer can be terminated.

Client set up

We require to run a DNS cache on (localhost) on our servers.

Removing the file /etc/resolv.conf should make the resolving libraries use this IP as default value.

We prefer creating the file for self-evidence:

sudo true

sudo sed w/etc/resolv.conf <<EOF
# $USER $(date -uIs)


On CX cloud servers previously:

  • Disable the cloud-init network configuration
  • Disable resolv.conf mangling Hetzner/CX/resolution
sudo true

cd /etc/network/interfaces.d || cat >/dev/null
sudo sed -i /dns-nameservers/d 50-hetzner-CX.cfg

Update dnsroots.global

Updating dnsroots.global is only relevant for the external resolver of the double cache cascade.

The first sudo ?shnippet creates a Makefile, which recreates /etc/dnsroots.global from DNS data as described in jdebp.

The Makefile requires all respective files/directories to be writable by group staff to be able to run it as administrator.

sudo chgrp staff /etc/dnsroots.global
sudo chmod g+w /etc/dnsroots.global

xargs -l -- echo -e > /etc/dnscachex/root/Makefile <<EOF
# leg20190111
servers/@: /etc/dnsroots.global
\\\\tcp \$^ \$@
\\\\tsv restart dnscachex
/etc/dnsroots.global: /tmp/dnsroots.global
\\\\tdiff -q \$@ \$^ || cat \$^ > \$@
\\\\tdnsip \`dnsqr ns . | awk \'/answer:/{ print \$\$5; }\' |sort\` > \$@
.PHONY: /tmp/dnsroots.global

The second sudo shnippet provides a daily cron job for checking and updating the root servers.

cat | sudo tee /etc/cron.daily/dnscachex <<EOF
cd /etc/dnscachex/root && make
sudo chmod +x /etc/cron.daily/dnscachex


  • We will simplify the Makefile so it generates servers/@ directly and remove /etc/dnsroots.globals in order to not to fool anybody.


  • Fix dnsroots.globals update: obligatory for all caches, redoo with RESOLVER variable and as real shnippet.
  • Cache size: https://cr.yp.to/djbdns/cachesize.html
  • Randomize seed: man dnscache-conf
  • Logging/Monitoring
  • Troubleshooting, djbdns tools. squish.dns.
  • CACHESIZE and DATALIMIT settings
  • This, and the double cache cascade are not ?setup guide compliant. They cannot be used via copy paste. No or placeholders should be used.