Setting up Unbound from scratch

tested on ubuntu/xenial/artful and slackware14.2


Build the latest version. Libevent useful for 1000+ outgoing ports.

sha1sum unbound-$ver.tar.gz
#9932931d495248b4e45d278b4679efae29238772  unbound-1.10.1.tar.gz
tar xzf unbound-$ver.tar.gz
cd unbound-$ver/
./configure --help|less
./configure --with-libevent --disable-systemd
make clean
make -j4 > ../unbound.log && echo BUILT
make install

Create a system user for Unbound to drop its priviledges,

useradd --system -d /usr/local/etc/unbound -s /sbin/nologin unbound
grep unbound /etc/passwd
grep unbound /etc/group

(using named pipe instead) – Generate some key pairs for unbound-control to work

#ls -lF /usr/local/etc/unbound/unbound*.{key,pem}

ls -lF /var/unbound.control.pipe
mkfifo /var/unbound.control.pipe

you will notice the perms are updated by the daemon as such

srw-rw---- 1 unbound unbound 0 Oct  2 12:53 /var/unbound.control.pipe=


Check how many cores you have got,

grep ^processor /proc/cpuinfo

Setup the caching name server,

ln -s /usr/local/etc/unbound/unbound.conf
cd /usr/local/etc/unbound/

Get the valid root hints


Get also the root anchors

mkdir /var/unbound/
unbound-anchor -a /var/unbound/root.key
chown -R unbound:unbound /var/unbound/

Then proceed with the setup (remove the authoritative zone part if you do not need it)

mv -i unbound.conf unbound.conf.dist
grep -Ev '^[[:space:]]*(#|$)' unbound.conf.dist > unbound.conf
vi unbound.conf

        verbosity: 1
        #verbosity: 3
        num-threads: HOW_MANY_CORES
        #interface: ::0
        access-control: allow
        #access-control: ::/0 allow
        pidfile: "/var/run/"
        root-hints: "/usr/local/etc/unbound/named.cache"
        hide-identity: yes
        hide-version: yes
        #rrset-roundrobin: yes
        qname-minimisation: yes
        #chroot path
        auto-trust-anchor-file: "/var/root.key"
        do-not-query-localhost: no

        domain-insecure: "example.local"
        domain-insecure: ""
        #local-zone: "example.local" transparent
        #local-zone: "" transparent

#        control-enable: no

        control-enable: yes
        control-interface: /var/unbound.control.pipe

        name: "example.local"
        stub-addr: ::1@5353

        name: ""
        stub-addr: ::1@5353

Ready to go

read the logs

tail -n0 -F /var/log/*

check the configuration

unbound-checkconf /usr/local/etc/unbound/unbound.conf

start and enable at boot time (remote control)

vi /etc/rc.local

echo -n creating unbound-control pipe...
rm -f /var/unbound.control.pipe
/usr/bin/mkfifo /var/unbound.control.pipe && echo done

echo -n starting unbound...
/usr/local/sbin/unbound-control start && echo done

or if you don’t need remote control, simply

echo -n starting unbound...
/usr/local/sbin/unbound -c /usr/local/etc/unbound/unbound.conf && echo done || echo FAILED

status (remote control)

unbound-control status
unbound-control stats_noreset

status (manually)

pgrep -a unbound
ps auxfww | grep unbound | grep -v grep #main process runs as unbound user
netstat -lntup --inet --inet6 | grep unbound


unbound-control reload

Advanced operations

Flush the cache against a specific zone

unbound-control flush_zone example.local

Flush the overall cache,

unbound-control reload

Acceptance testing


Testing local-zone,

host localhost localhost
host localhost

Testing cached public zone,

host localhost
host localhost

Testing cashed stub-zone,

host example.local localhost
host pxe.example.local localhost
host INTERNAL_IP localhost

Analyze the cache

unbound-control dump_cache > cache.dump
less cache.dump


nmap -sU -p 53 DNS-SERVER
nmap -p 53 DNS-SERVER

and re-iterate a few of the tests from above


Ubuntu – make sure you do NOT have those installed: dnsmasq, resolvconf nor systemd-resolved unit, NetworkManager. If so, disable or remove them.

apt install libevent-dev libexpat1-dev

ls -lF /var/lib/unbound/root.key #does not exist yet

mkdir trash/
mv unbound.conf unbound.conf.d/ trash/

#systemctl restart unbound


cat /var/log/packages/libevent*


If Unbound service is listening but refusing to answer queries, fix access-control: as shown in the example above.

With verbosity 3, if you get,

configured stub servers failed -- returning SERVFAIL

==> check do-not-query-localhost

Against a stub zone too, if you get,

info: query response was nodata ANSWER

==> if it is not signed, domain-insecure helps.


unbound.conf - Unbound configuration file.

unbound-anchor - Unbound anchor utility.

Howto enable DNSSEC


unbound/doc/ old

[Unbound-users] reverse lookup stub zone

Unbound DNS Server Cache Control


Root Files

Unbound DNS Server Cache Control