Building project

Installing from packages

The resolver is packaged for Debian, Fedora+EPEL, Ubuntu, Docker, NixOS/NixPkgs, FreeBSD, HomeBrew, and Turris Omnia. Some of these are maintained directly by the knot-resolver team.

Refer to project page for information about installing from packages. If packages are not available for your OS, see following sections to see how you can build it from sources (or package it), or use official Docker images.

Platform considerations

Project Platforms Compatibility notes
daemon UNIX-like [1] C99, libuv provides portable I/O
library UNIX-like MSVC not supported, needs MinGW
modules varies  
tests/unit equivalent to library  
tests/integration UNIX-like Depends on library injection (see [2])
[1]Known to be running (not exclusively) on FreeBSD, Linux and OS X.

Requirements

The following is a list of software required to build Knot DNS Resolver from sources.

Requirement Required by Notes
GNU Make 3.80+ all (build only)
C compiler all (build only) [2]
pkg-config all (build only) [3]
hexdump or xxd daemon (build only)
libknot 2.4.0+ all Knot DNS library (requires autotools, GnuTLS and Jansson).
LuaJIT 2.0+ daemon Embedded scripting language.
libuv 1.7+ daemon Multiplatform I/O and services (libuv 1.0 with limitations [4]).

There are also optional packages that enable specific functionality in Knot DNS Resolver, they are useful mainly for developers to build documentation and tests.

Optional Needed for Notes
lua-http modules/http HTTP/2 client/server for Lua.
luasocket trust anchors, modules/stats Sockets for Lua.
luasec trust anchors TLS for Lua.
libmemcached modules/memcached To build memcached backend module.
hiredis modules/redis To build redis backend module.
Go 1.5+ modules Build modules written in Go.
cmocka unit tests Unit testing framework.
Doxygen documentation Generating API documentation.
Sphinx and sphinx_rtd_theme documentation Building this HTML/PDF documentation.
breathe documentation Exposing Doxygen API doc to Sphinx.
libsystemd daemon Systemd socket activation support.
libprotobuf 3.0+ modules/dnstap Protocol Buffers support for dnstap.
libprotobuf-c 1.0+ modules/dnstap C bindings for Protobuf.
libfstrm 0.2+ modules/dnstap Frame Streams data transport protocol.
luacheck lint Syntax and static analysis checker for Lua.
luacov check-config Code coverage analysis for Lua modules.
[2]Requires C99, __attribute__((cleanup)) and -MMD -MP for dependency file generation. GCC, Clang and ICC are supported.
[3]You can use variables <dependency>_CFLAGS and <dependency>_LIBS to configure dependencies manually (i.e. libknot_CFLAGS and libknot_LIBS).
[4]libuv 1.7 brings SO_REUSEPORT support that is needed for multiple forks. libuv < 1.7 can be still used, but only in single-process mode. Use different method for load balancing.

Packaged dependencies

Most of the dependencies can be resolved from packages, here’s an overview for several platforms.

  • Debian (since sid) - current stable doesn’t have libknot and libuv, which must be installed from sources.
sudo apt-get install pkg-config libknot-dev libuv1-dev libcmocka-dev libluajit-5.1-dev
  • Ubuntu - unknown.
  • Fedora
# minimal build
sudo dnf install @buildsys-build knot-devel libuv-devel luajit-devel
# unit tests
sudo dnf install libcmocka-devel
# integration tests
sudo dnf install cmake git python-dns python-jinja2
# optional features
sudo dnf install golang hiredis-devel libmemcached-devel lua-sec-compat lua-socket-compat systemd-devel
# docs
sudo dnf install doxygen python-breathe python-sphinx
  • RHEL/CentOS - unknown.
  • openSUSE - there is an experimental package.
  • FreeBSD - when installing from ports, all dependencies will install automatically, corresponding to the selected options.
  • NetBSD - unknown.
  • OpenBSD - unknown.
  • Mac OS X - the dependencies can be found through Homebrew.
brew install pkg-config libuv luajit cmocka

Building from sources

Initialize git submodules first.

$ git submodule update --init --recursive

The Knot DNS Resolver depends on the the Knot DNS library, recent version of libuv, and LuaJIT.

$ make info # See what's missing

When you have all the dependencies ready, you can build and install.

$ make PREFIX="/usr/local"
$ make install PREFIX="/usr/local"

Note

Always build with PREFIX if you want to install, as it is hardcoded in the executable for module search path. Production code should be compiled with -DNDEBUG. If you build the binary with -DNOVERBOSELOG, it won’t be possible to turn on verbose logging; we advise packagers against using that flag.

Note

If you build with PREFIX, you may need to also set the LDFLAGS for the libraries:

make LDFLAGS="-Wl,-rpath=/usr/local/lib" PREFIX="/usr/local"

Alternatively you can build only specific parts of the project, i.e. library.

$ make lib
$ make lib-install

Note

Documentation is not built by default, run make doc to build it.

Building with security compiler flags

Knot DNS Resolver enables certain security compile-time flags that do not affect performance. You can add more flags to the build by appending them to CFLAGS variable, e.g. make CFLAGS="-fstack-protector".

Method Status Notes
-fstack-protector disabled (must be specifically enabled in CFLAGS)
-D_FORTIFY_SOURCE=2 enabled  
-pie enabled enables ASLR for kresd (disable with make HARDENING=no)
RELRO enabled full [5]

You can also disable linker hardening when it’s unsupported with make HARDENING=no.

[5]See checksec.sh

Building for packages

The build system supports DESTDIR

$ make install DESTDIR=/tmp/stage

Tip

There is a template for service file and AppArmor profile to help you kickstart the package.

Default paths

The default installation follows FHS with several custom paths for configuration and modules. All paths are prefixed with PREFIX variable by default if not specified otherwise.

Component Variable Default Notes
library LIBDIR $(PREFIX)/lib pkg-config is auto-generated [6]
daemon SBINDIR $(PREFIX)/sbin  
configuration ETCDIR $(PREFIX)/etc/kresd Configuration file, templates.
modules MODULEDIR $(LIBDIR)/kdns_modules Runtime directory for loading dynamic modules [7].
work directory   the current directory Run directory for daemon. (Only relevant during run time, not e.g. during installation.)
[6]The libkres.pc is installed in $(LIBDIR)/pkgconfig.
[7]The default moduledir can be changed with -m option to kresd daemon or by calling moduledir() function from lua.

Note

Each module is self-contained and may install additional bundled files within $(MODULEDIR)/$(modulename). These files should be read-only, non-executable.

Static or dynamic?

By default the resolver library is built as a dynamic library with versioned ABI. You can revert to static build with BUILDMODE variable.

$ make BUILDMODE=dynamic # Default, create dynamic library
$ make BUILDMODE=static  # Create static library

When the library is linked statically, it usually produces a smaller binary. However linking it to various C modules might violate ODR and increase the size.

Resolving dependencies

The build system relies on pkg-config to find dependencies. You can override it to force custom versions of the software by environment variables.

$ make libknot_CFLAGS="-I/opt/include" libknot_LIBS="-L/opt/lib -lknot -ldnssec"

Optional dependencies may be disabled as well using HAS_x=yes|no variable.

$ make HAS_go=no HAS_cmocka=no

Warning

If the dependencies lie outside of library search path, you need to add them somehow. Try LD_LIBRARY_PATH on Linux/BSD, and DYLD_FALLBACK_LIBRARY_PATH on OS X. Otherwise you need to add the locations to linker search path.

Several dependencies may not be in the packages yet, the script pulls and installs all dependencies in a chroot. You can avoid rebuilding dependencies by specifying BUILD_IGNORE variable, see the Dockerfile for example. Usually you only really need to rebuild libknot.

$ export FAKEROOT="${HOME}/.local"
$ export PKG_CONFIG_PATH="${FAKEROOT}/lib/pkgconfig"
$ export BUILD_IGNORE="..." # Ignore installed dependencies
$ ./scripts/bootstrap-depends.sh ${FAKEROOT}

Building extras

The project can be built with code coverage tracking using the COVERAGE=1 variable.

The make coverage target gathers both gcov code coverage for C files, and luacov code coverage for Lua files and merges it for analysis. It requires lcov to be installed.

$ make coverage

Running unit and integration tests

The linter requires luacheck and is executed by make lint. The unit tests require cmocka and are executed by make check. Tests for the dnstap module need go and are executed by make ckeck-dnstap.

The integration tests use Deckard, the DNS test harness.

$  make check-integration

Note that the daemon and modules must be installed first before running integration tests, the reason is that the daemon is otherwise unable to find and load modules.

Read the documentation for more information about requirements, how to run it and extend it.

Getting Docker image

Docker images require only either Linux or a Linux VM (see boot2docker on OS X).

$ docker run cznic/knot-resolver

See the Docker images page for more information and options. You can hack on the container by changing the container entrypoint to shell like:

$ docker run -it --entrypoint=/bin/bash cznic/knot-resolver

Tip

You can build the Docker image yourself with docker build -t knot-resolver scripts.