summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/Makefile.am228
-rw-r--r--doc/Makefile.in919
-rw-r--r--doc/appendices.rst126
-rw-r--r--doc/conf.py274
-rw-r--r--doc/configuration.rst1204
-rw-r--r--doc/ext/ignore_panels.py18
-rw-r--r--doc/index.rst19
-rw-r--r--doc/installation.rst92
-rw-r--r--doc/introduction.rst87
-rw-r--r--doc/logo.pdfbin0 -> 3067 bytes
-rw-r--r--doc/logo.svg35
-rw-r--r--doc/man/kcatalogprint.8in80
-rw-r--r--doc/man/kdig.1in464
-rw-r--r--doc/man/keymgr.8in372
-rw-r--r--doc/man/khost.1in156
-rw-r--r--doc/man/kjournalprint.8in120
-rw-r--r--doc/man/knot.conf.5in2826
-rw-r--r--doc/man/knotc.8in438
-rw-r--r--doc/man/knotd.8in93
-rw-r--r--doc/man/knsec3hash.1in96
-rw-r--r--doc/man/knsupdate.1in218
-rw-r--r--doc/man/kxdpgun.8in278
-rw-r--r--doc/man/kzonecheck.1in91
-rw-r--r--doc/man/kzonesign.1in95
-rw-r--r--doc/man_kcatalogprint.rst54
-rw-r--r--doc/man_kdig.rst396
-rw-r--r--doc/man_keymgr.rst300
-rw-r--r--doc/man_khost.rst108
-rw-r--r--doc/man_kjournalprint.rst88
-rw-r--r--doc/man_knotc.rst390
-rw-r--r--doc/man_knotd.rst69
-rw-r--r--doc/man_knsec3hash.rst60
-rw-r--r--doc/man_knsupdate.rst188
-rw-r--r--doc/man_kxdpgun.rst218
-rw-r--r--doc/man_kzonecheck.rst65
-rw-r--r--doc/man_kzonesign.rst69
-rw-r--r--doc/migration.rst437
-rw-r--r--doc/modules.rst.in8
-rw-r--r--doc/operation.rst1387
-rw-r--r--doc/reference.rst3050
-rw-r--r--doc/requirements.rst115
-rw-r--r--doc/theme_html/static/admon_caution_48.pngbin0 -> 1553 bytes
-rw-r--r--doc/theme_html/static/admon_important_48.pngbin0 -> 1985 bytes
-rw-r--r--doc/theme_html/static/admon_note_48.pngbin0 -> 2404 bytes
-rw-r--r--doc/theme_html/static/admon_tip_48.pngbin0 -> 2176 bytes
-rw-r--r--doc/theme_html/static/admon_warning_48.pngbin0 -> 1096 bytes
-rw-r--r--doc/theme_html/static/admons.css69
-rw-r--r--doc/theme_html/static/main.css6
-rw-r--r--doc/theme_html/theme.conf4
-rw-r--r--doc/troubleshooting.rst110
-rw-r--r--doc/utilities.rst24
51 files changed, 15544 insertions, 0 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..b26e298
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,228 @@
+MANPAGES_IN = \
+ man/knot.conf.5in \
+ man/knotc.8in \
+ man/knotd.8in \
+ man/kcatalogprint.8in \
+ man/keymgr.8in \
+ man/kjournalprint.8in \
+ man/kdig.1in \
+ man/khost.1in \
+ man/knsupdate.1in \
+ man/knsec3hash.1in \
+ man/kzonecheck.1in \
+ man/kzonesign.1in \
+ man/kxdpgun.8in
+
+MANPAGES_RST = \
+ reference.rst \
+ man_knotc.rst \
+ man_knotd.rst \
+ man_kcatalogprint.rst \
+ man_keymgr.rst \
+ man_kjournalprint.rst \
+ man_kdig.rst \
+ man_khost.rst \
+ man_knsupdate.rst \
+ man_knsec3hash.rst \
+ man_kzonecheck.rst \
+ man_kzonesign.rst \
+ man_kxdpgun.rst
+
+EXTRA_DIST = \
+ conf.py \
+ \
+ appendices.rst \
+ configuration.rst \
+ index.rst \
+ installation.rst \
+ introduction.rst \
+ migration.rst \
+ modules.rst.in \
+ operation.rst \
+ reference.rst \
+ requirements.rst \
+ troubleshooting.rst \
+ utilities.rst \
+ \
+ $(MANPAGES_IN) \
+ $(MANPAGES_RST) \
+ \
+ logo.pdf \
+ logo.svg \
+ \
+ ext/ignore_panels.py \
+ theme_html
+
+SPHINX_V = $(SPHINX_V_@AM_V@)
+SPHINX_V_ = $(SPHINX_V_@AM_DEFAULT_V@)
+SPHINX_V_0 = -q
+SPHINX_V_1 = -n
+
+AM_V_SPHINX = $(AM_V_SPHINX_@AM_V@)
+AM_V_SPHINX_ = $(AM_V_SPHINX_@AM_DEFAULT_V@)
+AM_V_SPHINX_0 = @echo " SPHINX $@";
+
+SPHINXBUILDDIR = $(builddir)/_build
+
+_SPHINXOPTS = -c $(srcdir) \
+ -a \
+ $(SPHINX_V)
+
+ALLSPHINXOPTS = $(_SPHINXOPTS) \
+ -D version="$(VERSION)" \
+ -D today="$(RELEASE_DATE)" \
+ -D release="$(VERSION)" \
+ $(SPHINXOPTS) \
+ $(srcdir)
+
+man_SPHINXOPTS = $(_SPHINXOPTS) \
+ -D version="@""VERSION@" \
+ -D today="@""RELEASE_DATE@" \
+ -D release="@""VERSION@" \
+ -D extensions="ignore_panels" \
+ $(SPHINXOPTS) \
+ $(srcdir)
+
+.PHONY: html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub
+
+man_MANS =
+
+if HAVE_DAEMON
+man_MANS += \
+ man/knot.conf.5 \
+ man/knotc.8 \
+ man/knotd.8
+endif # HAVE_DAEMON
+
+if HAVE_UTILS
+if HAVE_DAEMON
+man_MANS += \
+ man/kcatalogprint.8 \
+ man/keymgr.8 \
+ man/kjournalprint.8 \
+ man/kzonecheck.1 \
+ man/kzonesign.1
+endif # HAVE_DAEMON
+
+man_MANS += \
+ man/kdig.1 \
+ man/khost.1 \
+ man/knsupdate.1 \
+ man/knsec3hash.1
+
+if ENABLE_XDP
+man_MANS += man/kxdpgun.8
+endif # ENABLE_XDP
+endif # HAVE_UTILS
+
+man/knot.conf.5: man/knot.conf.5in
+man/knotc.8: man/knotc.8in
+man/knotd.8: man/knotd.8in
+man/kcatalogprint.8: man/kcatalogprint.8in
+man/keymgr.8: man/keymgr.8in
+man/kjournalprint.8: man/kjournalprint.8in
+man/kdig.1: man/kdig.1in
+man/khost.1: man/khost.1in
+man/knsupdate.1: man/knsupdate.1in
+man/knsec3hash.1: man/knsec3hash.1in
+man/kzonecheck.1: man/kzonecheck.1in
+man/kzonesign.1: man/kzonesign.1in
+man/kxdpgun.8: man/kxdpgun.8in
+
+man_SUBST = $(AM_V_GEN)mkdir -p man; \
+ sed -e 's,[@]VERSION@,$(VERSION),' \
+ -e 's,[@]RELEASE_DATE@,$(RELEASE_DATE),' \
+ -e 's,[@]config_dir@,$(config_dir),' \
+ -e 's,[@]storage_dir@,$(storage_dir),' \
+ -e 's,[@]run_dir@,$(run_dir),' \
+ -e 's,[@]conf_mapsize@,$(conf_mapsize),' \
+ $< > $@
+
+.1in.1:
+ $(man_SUBST)
+
+.5in.5:
+ $(man_SUBST)
+
+.8in.8:
+ $(man_SUBST)
+
+if HAVE_DOCS
+
+if HAVE_SPHINXBUILD
+html-local:
+ $(AM_V_SPHINX)$(SPHINXBUILD) -b html -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html
+ @echo "The HTML documentation has been built in $(SPHINXBUILDDIR)/html/"
+
+install-html-local:
+ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static $(DESTDIR)/$(docdir)/_sources
+ $(INSTALL) -D $(SPHINXBUILDDIR)/html/*.html $(DESTDIR)/$(docdir)/
+ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_sources/* $(DESTDIR)/$(docdir)/_sources/
+ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_static/* $(DESTDIR)/$(docdir)/_static/
+
+singlehtml:
+ $(AM_V_SPHINX)$(SPHINXBUILD) -b singlehtml -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/singlehtml
+ @echo "The single HTML documentation has been built in $(SPHINXBUILDDIR)/singlehtml/"
+
+install-singlehtml: singlehtml
+ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static
+ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/*.html $(DESTDIR)/$(docdir)/
+ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/_static/* $(DESTDIR)/$(docdir)/_static/
+
+epub:
+ $(AM_V_SPHINX)$(SPHINXBUILD) -b epub -A today=$(RELEASE_DATE) -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/epub
+ @echo "The EPUB documentation has been built in $(SPHINXBUILDDIR)/epub/"
+
+install-epub:
+ $(INSTALL) -d $(DESTDIR)/$(docdir)
+ $(INSTALL_DATA) $(SPHINXBUILDDIR)/epub/KnotDNS.epub $(DESTDIR)/$(docdir)/
+
+if HAVE_PDFLATEX
+pdf-local:
+ $(AM_V_SPHINX)$(SPHINXBUILD) -b latex -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/latex
+ $(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf
+ @echo "The PDF documentation has been built in $(SPHINXBUILDDIR)/latex/"
+
+install-pdf-local:
+ $(INSTALL) -d $(DESTDIR)/$(docdir)
+ $(INSTALL_DATA) $(SPHINXBUILDDIR)/latex/KnotDNS.pdf $(DESTDIR)/$(docdir)/
+
+else
+pdf-local install-pdf-local:
+ @echo "Install 'pdflatex' and re-run configure to be able to generate PDF documentation!"
+endif # HAVE_PDFLATEX
+
+if HAVE_MAKEINFO
+info-local:
+ $(AM_V_SPHINX)$(SPHINXBUILD) -b texinfo -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/texinfo
+ $(MAKE) -C $(SPHINXBUILDDIR)/texinfo info
+ @echo "The Info pages have been built in $(SPHINXBUILDDIR)/texinfo/"
+
+install-info-local:
+ $(INSTALL) -d $(DESTDIR)/$(infodir)
+ $(INSTALL_DATA) $(SPHINXBUILDDIR)/texinfo/knot.info $(DESTDIR)/$(infodir)/
+
+else
+info-local install-info-local:
+ @echo "Install 'texinfo' and re-run configure to be able to generate Info pages!"
+endif # HAVE_MAKEINFO
+
+.NOTPARALLEL: man
+man: $(man_MANS)
+$(MANPAGES_IN): $(MANPAGES_RST)
+ $(AM_V_SPHINX)$(SPHINXBUILD) -b man -d $(SPHINXBUILDDIR)/doctrees $(man_SPHINXOPTS) $(SPHINXBUILDDIR)/man
+ @mkdir -p $(srcdir)/man
+ @for f in $(SPHINXBUILDDIR)/man/*; do \
+ sed -e '/^\.TP$$/ {' -e 'n' -e 's/^\.B //' -e '}' "$$f" > "$(srcdir)/man/$$(basename $$f)in"; \
+ done
+
+else
+html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub:
+ @echo "Install 'sphinx-build' and re-run configure to be able to generate documentation!"
+endif # HAVE_SPHINXBUILD
+
+endif # HAVE_DOCS
+
+clean-local:
+ -rm -rf $(SPHINXBUILDDIR)
+ -rm -f man/*.1 man/*.5 man/*.8
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..5642629
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,919 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_DAEMON_TRUE@am__append_1 = \
+@HAVE_DAEMON_TRUE@ man/knot.conf.5 \
+@HAVE_DAEMON_TRUE@ man/knotc.8 \
+@HAVE_DAEMON_TRUE@ man/knotd.8
+
+@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@am__append_2 = \
+@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kcatalogprint.8 \
+@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/keymgr.8 \
+@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kjournalprint.8 \
+@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kzonecheck.1 \
+@HAVE_DAEMON_TRUE@@HAVE_UTILS_TRUE@ man/kzonesign.1
+
+@HAVE_UTILS_TRUE@am__append_3 = \
+@HAVE_UTILS_TRUE@ man/kdig.1 \
+@HAVE_UTILS_TRUE@ man/khost.1 \
+@HAVE_UTILS_TRUE@ man/knsupdate.1 \
+@HAVE_UTILS_TRUE@ man/knsec3hash.1
+
+@ENABLE_XDP_TRUE@@HAVE_UTILS_TRUE@am__append_4 = man/kxdpgun.8
+subdir = doc
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/code-coverage.m4 \
+ $(top_srcdir)/m4/knot-lib-version.m4 \
+ $(top_srcdir)/m4/knot-module.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/sanitizer.m4 $(top_srcdir)/m4/visibility.m4 \
+ $(top_srcdir)/m4/knot-version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = modules.rst
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man1dir = $(mandir)/man1
+am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \
+ "$(DESTDIR)$(man8dir)"
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/modules.rst.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DNSTAP_CFLAGS = @DNSTAP_CFLAGS@
+DNSTAP_LIBS = @DNSTAP_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+GENHTML = @GENHTML@
+GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KNOT_VERSION_MAJOR = @KNOT_VERSION_MAJOR@
+KNOT_VERSION_MINOR = @KNOT_VERSION_MINOR@
+KNOT_VERSION_PATCH = @KNOT_VERSION_PATCH@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAG_EXCLUDE_LIBS = @LDFLAG_EXCLUDE_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_NO_UNDEFINED = @LT_NO_UNDEFINED@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROTOC_C = @PROTOC_C@
+RANLIB = @RANLIB@
+RELEASE_DATE = @RELEASE_DATE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINXBUILD = @SPHINXBUILD@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+cap_ng_CFLAGS = @cap_ng_CFLAGS@
+cap_ng_LIBS = @cap_ng_LIBS@
+conf_mapsize = @conf_mapsize@
+config_dir = @config_dir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dlopen_LIBS = @dlopen_LIBS@
+docdir = @docdir@
+dvidir = @dvidir@
+embedded_libngtcp2_CFLAGS = @embedded_libngtcp2_CFLAGS@
+embedded_libngtcp2_LIBS = @embedded_libngtcp2_LIBS@
+exec_prefix = @exec_prefix@
+fuzzer_CFLAGS = @fuzzer_CFLAGS@
+fuzzer_LDFLAGS = @fuzzer_LDFLAGS@
+gnutls_CFLAGS = @gnutls_CFLAGS@
+gnutls_LIBS = @gnutls_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libbpf_CFLAGS = @libbpf_CFLAGS@
+libbpf_LIBS = @libbpf_LIBS@
+libdir = @libdir@
+libdnssec_SONAME = @libdnssec_SONAME@
+libdnssec_SOVERSION = @libdnssec_SOVERSION@
+libdnssec_VERSION_INFO = @libdnssec_VERSION_INFO@
+libedit_CFLAGS = @libedit_CFLAGS@
+libedit_LIBS = @libedit_LIBS@
+libexecdir = @libexecdir@
+libfstrm_CFLAGS = @libfstrm_CFLAGS@
+libfstrm_LIBS = @libfstrm_LIBS@
+libidn2_CFLAGS = @libidn2_CFLAGS@
+libidn2_LIBS = @libidn2_LIBS@
+libidn_CFLAGS = @libidn_CFLAGS@
+libidn_LIBS = @libidn_LIBS@
+libknot_SONAME = @libknot_SONAME@
+libknot_SOVERSION = @libknot_SOVERSION@
+libknot_VERSION_INFO = @libknot_VERSION_INFO@
+libkqueue_CFLAGS = @libkqueue_CFLAGS@
+libkqueue_LIBS = @libkqueue_LIBS@
+libmaxminddb_CFLAGS = @libmaxminddb_CFLAGS@
+libmaxminddb_LIBS = @libmaxminddb_LIBS@
+libmnl_CFLAGS = @libmnl_CFLAGS@
+libmnl_LIBS = @libmnl_LIBS@
+libnghttp2_CFLAGS = @libnghttp2_CFLAGS@
+libnghttp2_LIBS = @libnghttp2_LIBS@
+libngtcp2_CFLAGS = @libngtcp2_CFLAGS@
+libngtcp2_LIBS = @libngtcp2_LIBS@
+libprotobuf_c_CFLAGS = @libprotobuf_c_CFLAGS@
+libprotobuf_c_LIBS = @libprotobuf_c_LIBS@
+liburcu_CFLAGS = @liburcu_CFLAGS@
+liburcu_LIBS = @liburcu_LIBS@
+liburcu_PKGCONFIG = @liburcu_PKGCONFIG@
+libxdp_CFLAGS = @libxdp_CFLAGS@
+libxdp_LIBS = @libxdp_LIBS@
+libzscanner_SONAME = @libzscanner_SONAME@
+libzscanner_SOVERSION = @libzscanner_SOVERSION@
+libzscanner_VERSION_INFO = @libzscanner_VERSION_INFO@
+lmdb_CFLAGS = @lmdb_CFLAGS@
+lmdb_LIBS = @lmdb_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+malloc_LIBS = @malloc_LIBS@
+mandir = @mandir@
+math_LIBS = @math_LIBS@
+mkdir_p = @mkdir_p@
+module_dir = @module_dir@
+module_instdir = @module_instdir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pthread_LIBS = @pthread_LIBS@
+run_dir = @run_dir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+storage_dir = @storage_dir@
+sysconfdir = @sysconfdir@
+systemd_CFLAGS = @systemd_CFLAGS@
+systemd_LIBS = @systemd_LIBS@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+MANPAGES_IN = \
+ man/knot.conf.5in \
+ man/knotc.8in \
+ man/knotd.8in \
+ man/kcatalogprint.8in \
+ man/keymgr.8in \
+ man/kjournalprint.8in \
+ man/kdig.1in \
+ man/khost.1in \
+ man/knsupdate.1in \
+ man/knsec3hash.1in \
+ man/kzonecheck.1in \
+ man/kzonesign.1in \
+ man/kxdpgun.8in
+
+MANPAGES_RST = \
+ reference.rst \
+ man_knotc.rst \
+ man_knotd.rst \
+ man_kcatalogprint.rst \
+ man_keymgr.rst \
+ man_kjournalprint.rst \
+ man_kdig.rst \
+ man_khost.rst \
+ man_knsupdate.rst \
+ man_knsec3hash.rst \
+ man_kzonecheck.rst \
+ man_kzonesign.rst \
+ man_kxdpgun.rst
+
+EXTRA_DIST = \
+ conf.py \
+ \
+ appendices.rst \
+ configuration.rst \
+ index.rst \
+ installation.rst \
+ introduction.rst \
+ migration.rst \
+ modules.rst.in \
+ operation.rst \
+ reference.rst \
+ requirements.rst \
+ troubleshooting.rst \
+ utilities.rst \
+ \
+ $(MANPAGES_IN) \
+ $(MANPAGES_RST) \
+ \
+ logo.pdf \
+ logo.svg \
+ \
+ ext/ignore_panels.py \
+ theme_html
+
+SPHINX_V = $(SPHINX_V_@AM_V@)
+SPHINX_V_ = $(SPHINX_V_@AM_DEFAULT_V@)
+SPHINX_V_0 = -q
+SPHINX_V_1 = -n
+AM_V_SPHINX = $(AM_V_SPHINX_@AM_V@)
+AM_V_SPHINX_ = $(AM_V_SPHINX_@AM_DEFAULT_V@)
+AM_V_SPHINX_0 = @echo " SPHINX $@";
+SPHINXBUILDDIR = $(builddir)/_build
+_SPHINXOPTS = -c $(srcdir) \
+ -a \
+ $(SPHINX_V)
+
+ALLSPHINXOPTS = $(_SPHINXOPTS) \
+ -D version="$(VERSION)" \
+ -D today="$(RELEASE_DATE)" \
+ -D release="$(VERSION)" \
+ $(SPHINXOPTS) \
+ $(srcdir)
+
+man_SPHINXOPTS = $(_SPHINXOPTS) \
+ -D version="@""VERSION@" \
+ -D today="@""RELEASE_DATE@" \
+ -D release="@""VERSION@" \
+ -D extensions="ignore_panels" \
+ $(SPHINXOPTS) \
+ $(srcdir)
+
+man_MANS = $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4)
+man_SUBST = $(AM_V_GEN)mkdir -p man; \
+ sed -e 's,[@]VERSION@,$(VERSION),' \
+ -e 's,[@]RELEASE_DATE@,$(RELEASE_DATE),' \
+ -e 's,[@]config_dir@,$(config_dir),' \
+ -e 's,[@]storage_dir@,$(storage_dir),' \
+ -e 's,[@]run_dir@,$(run_dir),' \
+ -e 's,[@]conf_mapsize@,$(conf_mapsize),' \
+ $< > $@
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .1 .1in .5 .5in .8 .8in
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign doc/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+modules.rst: $(top_builddir)/config.status $(srcdir)/modules.rst.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man1: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man1dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.1[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+install-man5: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man5dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.5[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man5:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man5dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.5[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
+install-man8: $(man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.8[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+@HAVE_DOCS_FALSE@html-local:
+@HAVE_SPHINXBUILD_FALSE@html-local:
+@HAVE_DOCS_FALSE@info-local:
+@HAVE_MAKEINFO_FALSE@info-local:
+@HAVE_SPHINXBUILD_FALSE@info-local:
+@HAVE_DOCS_FALSE@install-html-local:
+@HAVE_SPHINXBUILD_FALSE@install-html-local:
+@HAVE_DOCS_FALSE@install-info-local:
+@HAVE_MAKEINFO_FALSE@install-info-local:
+@HAVE_SPHINXBUILD_FALSE@install-info-local:
+@HAVE_DOCS_FALSE@install-pdf-local:
+@HAVE_PDFLATEX_FALSE@install-pdf-local:
+@HAVE_SPHINXBUILD_FALSE@install-pdf-local:
+@HAVE_DOCS_FALSE@pdf-local:
+@HAVE_PDFLATEX_FALSE@pdf-local:
+@HAVE_SPHINXBUILD_FALSE@pdf-local:
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am: html-local
+
+info: info-am
+
+info-am: info-local
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am: install-html-local
+
+install-info: install-info-am
+
+install-info-am: install-info-local
+
+install-man: install-man1 install-man5 install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am: install-pdf-local
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am: pdf-local
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man
+
+uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ clean-local cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am html-local \
+ info info-am info-local install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-html-local install-info install-info-am \
+ install-info-local install-man install-man1 install-man5 \
+ install-man8 install-pdf install-pdf-am install-pdf-local \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am pdf-local ps ps-am tags-am \
+ uninstall uninstall-am uninstall-man uninstall-man1 \
+ uninstall-man5 uninstall-man8
+
+.PRECIOUS: Makefile
+
+
+.PHONY: html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub
+
+man/knot.conf.5: man/knot.conf.5in
+man/knotc.8: man/knotc.8in
+man/knotd.8: man/knotd.8in
+man/kcatalogprint.8: man/kcatalogprint.8in
+man/keymgr.8: man/keymgr.8in
+man/kjournalprint.8: man/kjournalprint.8in
+man/kdig.1: man/kdig.1in
+man/khost.1: man/khost.1in
+man/knsupdate.1: man/knsupdate.1in
+man/knsec3hash.1: man/knsec3hash.1in
+man/kzonecheck.1: man/kzonecheck.1in
+man/kzonesign.1: man/kzonesign.1in
+man/kxdpgun.8: man/kxdpgun.8in
+
+.1in.1:
+ $(man_SUBST)
+
+.5in.5:
+ $(man_SUBST)
+
+.8in.8:
+ $(man_SUBST)
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@html-local:
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b html -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The HTML documentation has been built in $(SPHINXBUILDDIR)/html/"
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@install-html-local:
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static $(DESTDIR)/$(docdir)/_sources
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -D $(SPHINXBUILDDIR)/html/*.html $(DESTDIR)/$(docdir)/
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_sources/* $(DESTDIR)/$(docdir)/_sources/
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/html/_static/* $(DESTDIR)/$(docdir)/_static/
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@singlehtml:
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b singlehtml -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/singlehtml
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The single HTML documentation has been built in $(SPHINXBUILDDIR)/singlehtml/"
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@install-singlehtml: singlehtml
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir) $(DESTDIR)/$(docdir)/_static
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/*.html $(DESTDIR)/$(docdir)/
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/singlehtml/_static/* $(DESTDIR)/$(docdir)/_static/
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@epub:
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b epub -A today=$(RELEASE_DATE) -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/epub
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The EPUB documentation has been built in $(SPHINXBUILDDIR)/epub/"
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@install-epub:
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir)
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/epub/KnotDNS.epub $(DESTDIR)/$(docdir)/
+
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@pdf-local:
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b latex -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/latex
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(MAKE) -C $(SPHINXBUILDDIR)/latex all-pdf
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The PDF documentation has been built in $(SPHINXBUILDDIR)/latex/"
+
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@install-pdf-local:
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(docdir)
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/latex/KnotDNS.pdf $(DESTDIR)/$(docdir)/
+
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_FALSE@@HAVE_SPHINXBUILD_TRUE@pdf-local install-pdf-local:
+@HAVE_DOCS_TRUE@@HAVE_PDFLATEX_FALSE@@HAVE_SPHINXBUILD_TRUE@ @echo "Install 'pdflatex' and re-run configure to be able to generate PDF documentation!"
+
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@info-local:
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b texinfo -d $(SPHINXBUILDDIR)/doctrees $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/texinfo
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(MAKE) -C $(SPHINXBUILDDIR)/texinfo info
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ @echo "The Info pages have been built in $(SPHINXBUILDDIR)/texinfo/"
+
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@install-info-local:
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL) -d $(DESTDIR)/$(infodir)
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(INSTALL_DATA) $(SPHINXBUILDDIR)/texinfo/knot.info $(DESTDIR)/$(infodir)/
+
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_FALSE@@HAVE_SPHINXBUILD_TRUE@info-local install-info-local:
+@HAVE_DOCS_TRUE@@HAVE_MAKEINFO_FALSE@@HAVE_SPHINXBUILD_TRUE@ @echo "Install 'texinfo' and re-run configure to be able to generate Info pages!"
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@.NOTPARALLEL: man
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@man: $(man_MANS)
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@$(MANPAGES_IN): $(MANPAGES_RST)
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ $(AM_V_SPHINX)$(SPHINXBUILD) -b man -d $(SPHINXBUILDDIR)/doctrees $(man_SPHINXOPTS) $(SPHINXBUILDDIR)/man
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @mkdir -p $(srcdir)/man
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ @for f in $(SPHINXBUILDDIR)/man/*; do \
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ sed -e '/^\.TP$$/ {' -e 'n' -e 's/^\.B //' -e '}' "$$f" > "$(srcdir)/man/$$(basename $$f)in"; \
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_TRUE@ done
+
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_FALSE@html-local singlehtml pdf-local info-local epub man install-html-local install-singlehtml install-pdf-local install-info-local install-epub:
+@HAVE_DOCS_TRUE@@HAVE_SPHINXBUILD_FALSE@ @echo "Install 'sphinx-build' and re-run configure to be able to generate documentation!"
+
+clean-local:
+ -rm -rf $(SPHINXBUILDDIR)
+ -rm -f man/*.1 man/*.5 man/*.8
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/appendices.rst b/doc/appendices.rst
new file mode 100644
index 0000000..309bb20
--- /dev/null
+++ b/doc/appendices.rst
@@ -0,0 +1,126 @@
+.. highlight:: none
+.. _Appendices:
+
+**********
+Appendices
+**********
+
+.. _compatible_pkcs11_devices:
+
+Compatible PKCS #11 Devices
+===========================
+
+This section has informative character. Knot DNS has been tested with several
+devices which claim to support PKCS #11 interface. The following table
+indicates which algorithms and operations have been observed to work. Please
+notice minimal GnuTLS library version required for particular algorithm
+support.
+
+.. |yes| replace:: **yes**
+.. |no| replace:: no
+.. |unknown| replace:: ?
+
+.. list-table::
+ :header-rows: 1
+ :stub-columns: 1
+
+ * -
+ - Key generate
+ - Key import
+ - ED25519 256-bit
+ - ECDSA 256-bit
+ - ECDSA 384-bit
+ - RSA 1024-bit
+ - RSA 2048-bit
+ - RSA 4096-bit
+ * - `Feitian ePass 2003 <https://www.ftsafe.com/Products/PKI/Standard>`_
+ - |yes|
+ - |no|
+ - |no|
+ - |no|
+ - |no|
+ - |yes|
+ - |yes|
+ - |no|
+ * - `SafeNet Network HSM (Luna SA 4) <https://safenet.gemalto.com/data-encryption/hardware-security-modules-hsms/luna-hsms-key-management/luna-sa-network-hsm/>`_
+ - |yes|
+ - |no|
+ - |no|
+ - |no|
+ - |no|
+ - |yes|
+ - |yes|
+ - |yes|
+ * - `SoftHSM 2.0 <https://www.opendnssec.org/softhsm/>`_ [#fn-softhsm]_
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ * - `Trustway Proteccio NetHSM <https://atos.net/en/solutions/cyber-security/data-protection-and-governance/hardware-security-module-trustway-proteccio-nethsm>`_
+ - |yes|
+ - ECDSA only
+ - |no|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ * - `Ultra Electronics CIS Keyper Plus (Model 9860-2) <https://www.ultra.group/our-business-units/intelligence-communications/cyber/key-management/#acc-keyperplus>`_
+ - |yes|
+ - RSA only
+ - |no|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ * - `Utimaco SecurityServer (V4) <https://hsm.utimaco.com/products-hardware-security-modules/general-purpose-hsm/securityserver-cse/>`_ [#fn-utimaco]_
+ - |yes|
+ - |yes|
+ - |no|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+ - |yes|
+
+.. in progress: key ID checks have to be disabled in code
+ * - `Yubikey NEO <https://www.yubico.com/products/yubikey-hardware/yubikey-neo/>`_
+ - |no|
+ - |no|
+ - |no|
+ - |yes|
+ - |no|
+ - |yes|
+ - |yes|
+ - |no|
+
+.. [#fn-softhsm] Algorithms supported depend on support in OpenSSL on which SoftHSM relies.
+ A command similar to the following may be used to verify what algorithms are supported:
+ ``$ pkcs11-tool --modul /usr/lib64/pkcs11/libsofthsm2.so -M``.
+.. [#fn-utimaco] Requires setting the number of background workers to 1!
+
+The following table summarizes supported DNSSEC algorithm numbers and minimal
+GnuTLS library version required. Any algorithm may work with older library,
+however the supported operations may be limited (e.g. private key import).
+
+.. list-table::
+ :header-rows: 1
+ :stub-columns: 1
+
+ * -
+ - `Numbers <https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1>`_
+ - GnuTLS version
+ * - ED25519
+ - 15
+ - 3.6.0 or newer
+ * - ECDSA
+ - 13, 14
+ - 3.4.8 or newer
+ * - RSA
+ - 5, 7, 8, 10
+ - 3.4.6 or newer
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..ec821d6
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,274 @@
+# -*- coding: utf-8 -*-
+#
+# Knot DNS documentation build configuration file, created by
+# sphinx-quickstart on Tue Apr 15 13:48:28 2014.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os, time, logging
+
+sys.setrecursionlimit(1500)
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('ext'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+import importlib.util
+if importlib.util.find_spec("sphinx_panels"):
+ extensions = [ 'sphinx_panels' ]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'Knot DNS'
+copyright_year = 2024
+current_year = time.localtime().tm_year
+if current_year > copyright_year:
+ logging.warning('Copyright year is %d, but current year is %d.'%(copyright_year, current_year))
+ logging.warning('Maybe you should update copyright_year in doc/conf.py?')
+copyright = u'Copyright 2010–%d, CZ.NIC, z.s.p.o.' % copyright_year
+author = 'CZ.NIC Labs <https://www.knot-dns.cz>'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+#version = ''
+# The full version, including alpha/beta/rc tags.
+#release = ''
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = False
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build', 'modules']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'theme_html'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ['.']
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = 'logo.svg'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+#html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, smartquotes will be used to convert quotes and dashes to
+# typographically correct entities.
+smartquotes = False
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_domain_indices = False
+
+# If false, no index is generated.
+html_use_index = False
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'KnotDNSdoc'
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+'papersize': 'a4paper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+
+# No empty pages between chapters
+'classoptions': ',openany,oneside',
+
+# Language preferences
+'babel': '\\usepackage[english]{babel}',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'KnotDNS.tex', 'Knot DNS Documentation', copyright, 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+latex_logo = 'logo.pdf'
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+latex_domain_indices = False
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('reference', 'knot.conf', 'Knot DNS configuration file', author, 5),
+ ('man_knotc', 'knotc', 'Knot DNS control utility', author, 8),
+ ('man_knotd', 'knotd', 'Knot DNS server daemon', author, 8),
+ ('man_kcatalogprint', 'kcatalogprint', 'Knot DNS catalog print utility', author, 8),
+ ('man_keymgr', 'keymgr', 'Knot DNS key management utility', author, 8),
+ ('man_kjournalprint', 'kjournalprint', 'Knot DNS journal print utility', author, 8),
+ ('man_kdig', 'kdig', 'Advanced DNS lookup utility', author, 1),
+ ('man_khost', 'khost', 'Simple DNS lookup utility', author, 1),
+ ('man_knsec3hash', 'knsec3hash', 'Simple utility to compute NSEC3 hash', author, 1),
+ ('man_knsupdate', 'knsupdate', 'Dynamic DNS update utility', author, 1),
+ ('man_kzonecheck', 'kzonecheck', 'Knot DNS zone check tool', author, 1),
+ ('man_kzonesign', 'kzonesign', 'DNSSEC signing utility', author, 1),
+ ('man_kxdpgun', 'kxdpgun', 'XDP-powered DNS benchmarking tool', author, 8),
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'knot', 'Knot DNS Documentation', author,
+ 'KnotDNS', 'Knot Authoritative DNS Server', 'Miscellaneous')
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# -- Options for Epub output ----------------------------------------------
+
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+epub_theme = 'theme_epub'
+epub_cover = ('_static/logo.svg', 'epub-cover.html')
+epub_exclude_files = ['epub-cover.xhtml']
diff --git a/doc/configuration.rst b/doc/configuration.rst
new file mode 100644
index 0000000..193bd78
--- /dev/null
+++ b/doc/configuration.rst
@@ -0,0 +1,1204 @@
+.. highlight:: none
+.. _Configuration:
+
+*************
+Configuration
+*************
+
+Simple configuration
+====================
+
+The following example presents a simple configuration file
+which can be used as a base for your Knot DNS setup::
+
+ # Example of a very simple Knot DNS configuration.
+
+ server:
+ listen: 0.0.0.0@53
+ listen: ::@53
+
+ zone:
+ - domain: example.com
+ storage: /var/lib/knot/zones/
+ file: example.com.zone
+
+ log:
+ - target: syslog
+ any: info
+
+Now let's walk through this configuration step by step:
+
+- The :ref:`server_listen` statement in the :ref:`server section<Server section>`
+ defines where the server will listen for incoming connections.
+ We have defined the server to listen on all available IPv4 and IPv6 addresses,
+ all on port 53.
+- The :ref:`zone section` defines the zones that the server will
+ serve. In this case, we defined one zone named *example.com* which is stored
+ in the zone file :file:`/var/lib/knot/zones/example.com.zone`.
+- The :ref:`log section` defines the log facilities for
+ the server. In this example, we told Knot DNS to send its log messages with
+ the severity ``info`` or more serious to the syslog (or systemd journal).
+
+For detailed description of all configuration items see
+:ref:`Configuration Reference`.
+
+Zone templates
+==============
+
+A zone template allows a single zone configuration to be shared among several
+zones. There is no inheritance between templates; they are exclusive. The
+``default`` template identifier is reserved for the default template::
+
+ template:
+ - id: default
+ storage: /var/lib/knot/master
+ semantic-checks: on
+
+ - id: signed
+ storage: /var/lib/knot/signed
+ dnssec-signing: on
+ semantic-checks: on
+ master: [master1, master2]
+
+ - id: slave
+ storage: /var/lib/knot/slave
+
+ zone:
+ - domain: example1.com # Uses default template
+
+ - domain: example2.com # Uses default template
+ semantic-checks: off # Override default settings
+
+ - domain: example.cz
+ template: signed
+ master: master3 # Override masters to just master3
+
+ - domain: example1.eu
+ template: slave
+ master: master1
+
+ - domain: example2.eu
+ template: slave
+ master: master2
+
+.. NOTE::
+ Each template option can be explicitly overridden in zone-specific configuration.
+
+.. _ACL:
+
+Access control list (ACL)
+=========================
+
+Some types of incoming DNS requests must be authorized before they can be
+processed by the server. A zone can have configured :ref:`zone_acl` which is
+a sequence of :ref:`rules <ACL section>` describing what requests are authorized.
+By default if :ref:`automatic ACL <server_automatic-acl>` is not enabled, all requests,
+which require authorization, are denied.
+
+Every ACL rule can allow or deny one or more request types based on the
+source IP address, network subnet, or address range and/or if the request is
+secured by a given TSIG key. See :doc:`keymgr -t<man_keymgr>` on how
+to generate a TSIG key.
+
+If there are multiple ACL rules assigned to a zone, they are applied in the
+specified order of the :ref:`zone_acl` configuration. The first rule that matches
+the given request is applied and the remaining rules are ignored. Some examples::
+
+ acl:
+ - id: address_rule
+ address: [2001:db8::1, 192.168.2.0/24]
+ action: transfer
+
+ - id: deny_rule
+ address: 192.168.2.100
+ action: transfer
+ deny: on
+
+ zone:
+ - domain: acl1.example.com
+ acl: [deny_rule, address_rule] # Allow some addresses with an exception
+
+::
+
+ key:
+ - id: key1 # The real TSIG key name
+ algorithm: hmac-sha256
+ secret: 4Tc0K1QkcMCs7cOW2LuSWnxQY0qysdvsZlSb4yTN9pA=
+
+ acl:
+ - id: deny_all
+ address: 192.168.3.0/24
+ deny: on # No action specified and deny on implies denial of all actions
+
+ - id: key_rule
+ key: key1 # Access based just on TSIG key
+ action: [transfer, notify]
+
+ zone:
+ - domain: acl2.example.com
+ acl: [deny_all, key_rule] # Allow with the TSIG except for the subnet
+
+In the case of dynamic DNS updates, some additional conditions may be specified
+for more granular filtering. See more in the section :ref:`Restricting dynamic updates`.
+
+.. NOTE::
+ If more conditions (address ranges and/or a key)
+ are given in a single ACL rule, all of them have to be satisfied for the rule to match.
+
+.. TIP::
+ In order to restrict regular DNS queries, use module :ref:`queryacl<mod-queryacl>`.
+
+Secondary (slave) zone
+======================
+
+Knot DNS doesn't strictly differ between primary (formerly known as master)
+and secondary (formerly known as slave) zones. The only requirement for a secondary
+zone is to have a :ref:`zone_master` statement set. For effective zone synchronization,
+incoming zone change notifications (NOTIFY), which require authorization, can be
+enabled using :ref:`automatic ACL <server_automatic-acl>` or :ref:`explicit ACL <zone_acl>`
+configuration. Optional transaction authentication (TSIG) is supported for both
+zone transfers and zone notifications::
+
+ server:
+ automatic-acl: on # Enabled automatic ACL
+
+ key:
+ - id: xfr_notify_key # Common TSIG key for XFR an NOTIFY
+ algorithm: hmac-sha256
+ secret: VFRejzw8h4M7mb0xZKRFiZAfhhd1eDGybjqHr2FV3vc=
+
+ remote:
+ - id: primary
+ address: [2001:DB8:1::1, 192.168.1.1] # Primary server IP addresses
+ # via: [2001:DB8:2::1, 10.0.0.1] # Local source addresses (optional)
+ key: xfr_notify_key # TSIG key (optional)
+
+ zone:
+ - domain: example.com
+ master: primary # Primary remote(s)
+
+An example of explicit ACL with different TSIG keys for zone transfers
+and notifications::
+
+ key:
+ - id: notify_key # TSIG key for NOTIFY
+ algorithm: hmac-sha256
+ secret: uBbhV4aeSS4fPd+wF2ZIn5pxOMF35xEtdq2ibi2hHEQ=
+
+ - id: xfr_key # TSIG key for XFR
+ algorithm: hmac-sha256
+ secret: VFRejzw8h4M7mb0xZKRFiZAfhhd1eDGybjqHr2FV3vc=
+
+ remote:
+ - id: primary
+ address: [2001:DB8:1::1, 192.168.1.1] # Primary server IP addresses
+ # via: [2001:DB8:2::1, 10.0.0.1] # Local source addresses if needed
+ key: xfr_key # Optional TSIG key
+
+ acl:
+ - id: notify_from_primary # ACL rule for NOTIFY from primary
+ address: [2001:DB8:1::1, 192.168.1.1] # Primary addresses (optional)
+ key: notify_key # TSIG key (optional)
+ action: notify
+
+ zone:
+ - domain: example.com
+ master: primary # Primary remote(s)
+ acl: notify_from_primary # Explicit ACL(s)
+
+Note that the :ref:`zone_master` option accepts a list of remotes, which are
+queried for a zone refresh sequentially in the specified order. When the server
+receives a zone change notification from a listed remote, only that remote is
+used for a subsequent zone transfer.
+
+.. NOTE::
+ When transferring a lot of zones, the server may easily get into a state
+ where all available ports are in the TIME_WAIT state, thus transfers
+ cease until the operating system closes the ports for good. There are
+ several ways to work around this:
+
+ * Allow reusing of ports in TIME_WAIT (sysctl -w net.ipv4.tcp_tw_reuse=1)
+ * Shorten TIME_WAIT timeout (tcp_fin_timeout)
+ * Increase available local port count
+
+Primary (master) zone
+=====================
+
+A zone is considered primary if it doesn't have :ref:`zone_master` set. As
+outgoing zone transfers (XFR) require authorization, it must be enabled
+using :ref:`automatic ACL <server_automatic-acl>` or :ref:`explicit ACL <zone_acl>`
+configuration. Outgoing zone change notifications (NOTIFY) to remotes can be
+set by configuring :ref:`zone_notify`. Transaction authentication
+(TSIG) is supported for both zone transfers and zone notifications::
+
+ server:
+ automatic-acl: on # Enabled automatic ACL
+
+ key:
+ - id: xfr_notify_key # Common TSIG key for XFR an NOTIFY
+ algorithm: hmac-sha256
+ secret: VFRejzw8h4M7mb0xZKRFiZAfhhd1eDGybjqHr2FV3vc=
+
+ remote:
+ - id: secondary
+ address: [2001:DB8:1::1, 192.168.1.1] # Secondary server IP addresses
+ # via: [2001:DB8:2::1, 10.0.0.1] # Local source addresses (optional)
+ key: xfr_notify_key # TSIG key (optional)
+
+ acl:
+ - id: local_xfr # Allow XFR to localhost without TSIG
+ address: [::1, 127.0.0.1]
+ action: transfer
+
+ zone:
+ - domain: example.com
+ notify: secondary # Secondary remote(s)
+ acl: local_xfr # Explicit ACL for local XFR
+
+Note that the :ref:`zone_notify` option accepts a list of remotes, which are
+all notified sequentially in the specified order.
+
+A secondary zone may serve as a primary zone for a different set of remotes
+at the same time.
+
+.. _dynamic updates:
+
+Dynamic updates
+===============
+
+Dynamic updates for the zone are allowed via proper ACL rule with the
+``update`` action. If the zone is configured as a secondary and a DNS update
+message is accepted, the server forwards the message to its first primary
+:ref:`zone_master` or :ref:`zone_ddns-master` if configured.
+The primary master's response is then forwarded back to the originator.
+
+However, if the zone is configured as a primary, the update is accepted and
+processed::
+
+ acl:
+ - id: update_acl
+ address: 192.168.3.0/24
+ action: update
+
+ zone:
+ - domain: example.com.
+ acl: update_acl
+
+.. NOTE::
+ To forward DDNS requests signed with a locally unknown key, an ACL rule for
+ the action ``update`` without a key must be configured for the zone. E.g.::
+
+ acl:
+ - id: fwd_foreign_key
+ action: update
+ # possible non-key options
+
+ zone:
+ - domain: example.com.
+ acl: fwd_foreign_key
+
+.. _Restricting dynamic updates:
+
+Restricting dynamic updates
+---------------------------
+
+There are several additional ACL options for dynamic DNS updates which affect
+the request classification based on the update contents.
+
+Updates can be restricted to specific resource record types::
+
+ acl:
+ - id: type_rule
+ action: update
+ update-type: [A, AAAA, MX] # Updated records must match one of the specified types
+
+Another possibility is restriction on the owner name of updated records. The option
+:ref:`acl_update-owner` is used to select the source of domain
+names which are used for the comparison. And the option :ref:`acl_update-owner-match`
+specifies the required relation between the record owner and the reference domain
+names. Example::
+
+ acl:
+ - id: owner_rule1
+ action: update
+ update-owner: name # Updated record owners are restricted by the next conditions
+ update-owner-match: equal # The record owner must exactly match one name from the next list
+ update-owner-name: [foo, bar.] # Reference domain names
+
+.. NOTE::
+ If the specified owner name is non-FQDN (e.g. ``foo``), it's considered relatively
+ to the effective zone name. So it can apply to more zones
+ (e.g. ``foo.example.com.`` or ``foo.example.net.``). Alternatively, if the
+ name is FQDN (e.g. ``bar.``), the rule only applies to this name.
+
+If the reference domain name is the zone name, the following variant can be used::
+
+ acl:
+ - id: owner_rule2
+ action: update
+ update-owner: zone # The reference name is the zone name
+ update-owner-match: sub # Any record owner matches except for the zone name itself
+
+ template:
+ - id: default
+ acl: owner_rule2
+
+ zone:
+ - domain: example.com.
+ - domain: example.net.
+
+The last variant is for the cases where the reference domain name is a TSIG key name,
+which must be used for the transaction security::
+
+ key:
+ - id: example.com # Key names are always considered FQDN
+ ...
+ - id: steve.example.net
+ ...
+ - id: jane.example.net
+ ...
+
+ acl:
+ - id: owner_rule3_com
+ action: update
+ update-owner: key # The reference name is the TSIG key name
+ update-owner-match: sub # The record owner must be a subdomain of the key name
+ key: [example.com] # One common key for updating all non-apex records
+
+ - id: owner_rule3_net
+ action: update
+ update-owner: key # The reference name is the TSIG key name
+ update-owner-match: equal # The record owner must exactly match the used key name
+ key: [steve.example.net, jane.example.net] # Keys for updating specific zone nodes
+
+ zone:
+ - domain: example.com.
+ acl: owner_rule3_com
+ - domain: example.net.
+ acl: owner_rule3_net
+
+.. _dnssec:
+
+Automatic DNSSEC signing
+========================
+
+Knot DNS supports automatic DNSSEC signing of zones. The signing
+can operate in two modes:
+
+1. :ref:`Automatic key management <dnssec-automatic-zsk-management>`.
+ In this mode, the server maintains signing keys. New keys are generated
+ according to assigned policy and are rolled automatically in a safe manner.
+ No zone operator intervention is necessary.
+
+2. :ref:`Manual key management <dnssec-manual-key-management>`.
+ In this mode, the server maintains zone signatures only. The signatures
+ are kept up-to-date and signing keys are rolled according to timing
+ parameters assigned to the keys. The keys must be generated and timing
+ parameters must be assigned by the zone operator.
+
+The DNSSEC signing process maintains some metadata which is stored in the
+:abbr:`KASP (Key And Signature Policy)` database. This database is backed
+by LMDB.
+
+.. WARNING::
+ Make sure to set the KASP database permissions correctly. For manual key
+ management, the database must be *readable* by the server process. For
+ automatic key management, it must be *writeable*. If no HSM is used,
+ the database also contains private key material – don't set the permissions
+ too weak.
+
+.. _dnssec-automatic-zsk-management:
+
+Automatic ZSK management
+------------------------
+
+For automatic ZSK management a signing :ref:`policy<Policy section>` has to
+be configured and assigned to the zone. The policy specifies how the zone
+is signed (i.e. signing algorithm, key size, key lifetime, signature lifetime,
+etc.). If no policy is specified or the ``default`` one is assigned, the
+default signing parameters are used.
+
+A minimal zone configuration may look as follows::
+
+ zone:
+ - domain: myzone.test
+ dnssec-signing: on
+
+With a custom signing policy, the policy section will be added::
+
+ policy:
+ - id: custom_policy
+ signing-threads: 4
+ algorithm: ECDSAP256SHA256
+ zsk-lifetime: 60d
+
+ zone:
+ - domain: myzone.test
+ dnssec-signing: on
+ dnssec-policy: custom_policy
+
+After configuring the server, reload the changes:
+
+.. code-block:: console
+
+ $ knotc reload
+
+The server will generate initial signing keys and sign the zone properly. Check
+the server logs to see whether everything went well.
+
+.. _dnssec-automatic-ksk-management:
+
+Automatic KSK management
+------------------------
+
+For automatic KSK management, first configure ZSK management like above, and use
+additional options in :ref:`policy section <Policy section>`, mostly specifying
+desired (finite) lifetime for KSK: ::
+
+ remote:
+ - id: parent_zone_server
+ address: 192.168.12.1@53
+
+ submission:
+ - id: parent_zone_sbm
+ parent: [parent_zone_server]
+
+ policy:
+ - id: custom_policy
+ signing-threads: 4
+ algorithm: ECDSAP256SHA256
+ zsk-lifetime: 60d
+ ksk-lifetime: 365d
+ ksk-submission: parent_zone_sbm
+
+ zone:
+ - domain: myzone.test
+ dnssec-signing: on
+ dnssec-policy: custom_policy
+
+After the initially-generated KSK reaches its lifetime, new KSK is published and after
+convenience delay the submission is started. The server publishes CDS and CDNSKEY records
+and the user shall propagate them to the parent. The server periodically checks for
+DS at the parent zone and when positive, finishes the rollover.
+
+.. _dnssec-manual-key-management:
+
+Manual key management
+---------------------
+
+For automatic DNSSEC signing with manual key management, a signing policy
+with manual key management flag has to be set::
+
+ policy:
+ - id: manual
+ manual: on
+
+ zone:
+ - domain: myzone.test
+ dnssec-signing: on
+ dnssec-policy: manual
+
+To generate signing keys, use the :doc:`keymgr<man_keymgr>` utility.
+For example, we can use Single-Type Signing:
+
+.. code-block:: console
+
+ $ keymgr myzone.test. generate algorithm=ECDSAP256SHA256 ksk=yes zsk=yes
+
+And reload the server. The zone will be signed.
+
+To perform a manual rollover of a key, the timing parameters of the key need
+to be set. Let's roll the key. Generate a new key, but do not activate
+it yet:
+
+.. code-block:: console
+
+ $ keymgr myzone.test. generate algorithm=ECDSAP256SHA256 ksk=yes zsk=yes active=+1d
+
+Take the key ID (or key tag) of the old key and disable it the same time
+the new key gets activated:
+
+.. code-block:: console
+
+ $ keymgr myzone.test. set <old_key_id> retire=+2d remove=+3d
+
+Reload the server again. The new key will be published (i.e. the DNSKEY record
+will be added into the zone). Remember to update the DS record in the
+parent zone to include a reference to the new key. This must happen within one
+day (in this case) including a delay required to propagate the new DS to
+caches.
+
+.. WARNING::
+ If you ever decide to switch from manual key management to automatic key management,
+ note that the automatic key management uses
+ :ref:`policy_zsk-lifetime` and :ref:`policy_ksk-lifetime` policy configuration
+ options to schedule key rollovers and it internally uses timestamps of keys differently
+ than in the manual case. As a consequence it might break if the ``retire`` or ``remove`` timestamps
+ are set for the manually generated keys currently in use. Make sure to set these timestamps
+ to zero using :doc:`keymgr<man_keymgr>`:
+
+ .. code-block:: console
+
+ $ keymgr myzone.test. set <key_id> retire=0 remove=0
+
+ and configure your policy suitably according to :ref:`dnssec-automatic-zsk-management`
+ and :ref:`dnssec-automatic-ksk-management`.
+
+.. _dnssec-signing:
+
+Zone signing
+------------
+
+The signing process consists of the following steps:
+
+#. Processing KASP database events. (e.g. performing a step of a rollover).
+#. Updating the DNSKEY records. The whole DNSKEY set in zone apex is replaced
+ by the keys from the KASP database. Note that keys added into the zone file
+ manually will be removed. To add an extra DNSKEY record into the set, the
+ key must be imported into the KASP database (possibly deactivated).
+#. Fixing the NSEC or NSEC3 chain.
+#. Removing expired signatures, invalid signatures, signatures expiring
+ in a short time, and signatures issued by an unknown key.
+#. Creating missing signatures. Unless the Single-Type Signing Scheme
+ is used, DNSKEY records in a zone apex are signed by KSK keys and
+ all other records are signed by ZSK keys.
+#. Updating and re-signing SOA record.
+
+The signing is initiated on the following occasions:
+
+- Start of the server
+- Zone reload
+- Reaching the signature refresh period
+- Key set changed due to rollover event
+- Received DDNS update
+- Forced zone re-sign via server control interface
+
+On a forced zone re-sign, all signatures in the zone are dropped and recreated.
+
+The ``knotc zone-status`` command can be used to see when the next scheduled
+DNSSEC re-sign will happen.
+
+.. _dnssec-on-slave-signing:
+
+On-secondary (on-slave) signing
+-------------------------------
+
+It is possible to enable automatic DNSSEC zone signing even on a secondary
+server. If enabled, the zone is signed after every AXFR/IXFR transfer
+from primary, so that the secondary always serves a signed up-to-date version
+of the zone.
+
+It is strongly recommended to block any outside access to the primary
+server, so that only the secondary server's signed version of the zone is served.
+
+Enabled on-secondary signing introduces events when the secondary zone changes
+while the primary zone remains unchanged, such as a key rollover or
+refreshing of RRSIG records, which cause inequality of zone SOA serial
+between primary and secondary. The secondary server handles this by saving the
+primary's SOA serial in a special variable inside KASP DB and appropriately
+modifying AXFR/IXFR queries/answers to keep the communication with
+primary server consistent while applying the changes with a different serial.
+
+.. _catalog-zones:
+
+Catalog zones
+=============
+
+Catalog zones (:rfc:`9432`) are a concept whereby a list of zones to be configured is maintained
+as contents of a separate, special zone. This approach has the benefit of simple
+propagation of a zone list to secondary servers, especially when the list is
+frequently updated.
+
+Terminology first. *Catalog zone* is a meta-zone which shall not be a part
+of the DNS tree, but it contains information about the set of member zones and
+is transferable to secondary servers using common AXFR/IXFR techniques.
+A *catalog-member zone* (or just *member zone*) is a zone based on
+information from the catalog zone and not from configuration file/database.
+*Member properties* are some additional information related to each member zone,
+also distributed with the catalog zone.
+
+A catalog zone is handled almost in the same way as a regular zone:
+It can be configured using all the standard options (but for example
+DNSSEC signing is useless as the zone won't be queried by clients), including primary/secondary configuration
+and ACLs. A catalog zone is indicated by setting the option
+:ref:`zone_catalog-role`. Standard DNS queries to a catalog zone are answered
+with REFUSED as though the zone doesn't exist unless there is a matching ACL
+rule for action transfer configured.
+The name of the catalog zone is arbitrary. It's possible to configure
+multiple catalog zones.
+
+.. WARNING::
+ Don't choose a name for a catalog zone below a name of any other
+ existing zones configured on the server as it would effectively "shadow"
+ part of your DNS subtree.
+
+Upon catalog zone (re)load or change, all the PTR records in the format
+``unique-id.zones.catalog. 0 IN PTR member.com.`` (but not ``too.deep.zones.catalog.``!)
+are processed and member zones created, with zone names taken from the
+PTR records' RData, and zone settings taken from the configuration
+templates specified by :ref:`zone_catalog-template`.
+
+The owner names of the PTR records shall follow this scheme:
+
+.. code-block:: console
+
+ <unique-id>.zones.<catalog-zone>.
+
+where the mentioned labels shall match:
+
+- *<unique-id>* — Single label that is recommended to be unique among member zones.
+- ``zones`` — Required label.
+- *<catalog-zone>* — Name of the catalog zone.
+
+Additionally, records in the format
+``group.unique-id.zones.catalog. 0 IN TXT "conf-template"``
+are processed as a definition of the member's *group* property. The
+``unique-id`` must match the one of the PTR record defining the member.
+It's required that at most one group is defined for each member. If multiple
+groups are defined, one group is picked at random.
+
+All other records and other member properties are ignored. They remain in the catalog
+zone, however, and might be for example transferred to a secondary server,
+which may interpret catalog zones differently. SOA still needs to be present in
+the catalog zone and its serial handled appropriately. An apex NS record must be
+present as for any other zone. The version record ``version 0 IN TXT "2"``
+is required at the catalog zone apex.
+
+A catalog zone may be modified using any standard means (e.g. AXFR/IXFR, DDNS,
+zone file reload). In the case of incremental change, only affected
+member zones are reloaded.
+
+The catalog zone must have at least one :ref:`zone_catalog-template`
+configured. The configuration for any defined member zone is taken from its
+*group* property value, which should match some catalog-template name.
+If the *group* property is not defined for a member, is empty, or doesn't match
+any of defined catalog-template names, the first catalog-template
+(in the order from configuration) is used. Nesting of catalog zones isn't
+supported.
+
+Any de-cataloged member zone is purged immediately, including its
+zone file, journal, timers, and DNSSEC keys. The zone file is not
+deleted if :ref:`zone_zonefile-sync` is set to *-1* for member zones.
+Any member zone, whose PTR record's owner has been changed, is purged
+immediately if and only if the *<unique-id>* has been changed.
+
+When setting up catalog zones, it might be useful to set
+:ref:`database_catalog-db` and :ref:`database_catalog-db-max-size`
+to non-default values.
+
+.. NOTE::
+
+ Whenever a catalog zone is updated, the server reloads itself with
+ all configured zones, including possibly existing other catalog zones.
+ It's similar to calling `knotc zone-reload` (for all zones).
+ The consequence is that new zone files might be discovered and reloaded,
+ even for zones that do not relate to updated catalog zone.
+
+ Catalog zones never expire automatically, regardless of what is declared
+ in the catalog zone SOA. However, a catalog zone can be expired manually
+ at any time using `knotc -f zone-purge +expire`.
+
+ Currently, expiration of a catalog zone doesn't have any effect on its
+ member zones.
+
+.. WARNING::
+
+ The server does not work well if one member zone appears in two catalog zones
+ concurrently. The user is encouraged to avoid this situation whatsoever.
+ Thus, there is no way a member zone can be migrated from one catalog
+ to another while preserving its metadata. Following steps may be used
+ as a workaround:
+
+ * :ref:`Back up<Data and metadata backup>` the member zone's metadata
+ (on each server separately).
+ * Remove the member zone from the catalog it's a member of.
+ * Wait for the catalog zone to be propagated to all servers.
+ * Add the member zone to the other catalog.
+ * Restore the backed up metadata (on each server separately).
+
+Catalog zones configuration examples
+------------------------------------
+
+Below are configuration snippets (e.g. `server` and `log` sections missing)
+of very simple catalog zone setups, in order to illustrate the relations
+between catalog-related configuration options.
+
+First setup represents a very simple scenario where the primary is
+the catalog zone generator and the secondary is the catalog zone consumer.
+
+Primary configuration::
+
+ acl:
+ - id: slave_xfr
+ address: ...
+ action: transfer
+
+ template:
+ - id: mmemb
+ catalog-role: member
+ catalog-zone: catz.
+ acl: slave_xfr
+
+ zone:
+ - domain: catz.
+ catalog-role: generate
+ acl: slave_xfr
+
+ - domain: foo.com.
+ template: mmemb
+
+ - domain: bar.com.
+ template: mmemb
+
+Secondary configuration::
+
+ acl:
+ - id: master_notify
+ address: ...
+ action: notify
+
+ template:
+ - id: smemb
+ master: master
+ acl: master_notify
+
+ zone:
+ - domain: catz.
+ master: master
+ acl: master_notify
+ catalog-role: interpret
+ catalog-template: smemb
+
+When new zones are added (or removed) to the primary configuration with assigned
+`mmemb` template, they will automatically propagate to the secondary
+and have the `smemb` template assigned there.
+
+Second example is with a hand-written (or script-generated) catalog zone,
+while employing configuration groups::
+
+ catz. 0 SOA invalid. invalid. 1625079950 3600 600 2147483646 0
+ catz. 0 NS invalid.
+ version.catz. 0 TXT "2"
+ nj2xg5bnmz2w4ltd.zones.catz. 0 PTR just-fun.com.
+ group.nj2xg5bnmz2w4ltd.zones.catz. 0 TXT unsigned
+ nvxxezjnmz2w4ltd.zones.catz. 0 PTR more-fun.com.
+ group.nvxxezjnmz2w4ltd.zones.catz. 0 TXT unsigned
+ nfwxa33sorqw45bo.zones.catz. 0 PTR important.com.
+ group.nfwxa33sorqw45bo.zones.catz. 0 TXT signed
+ mjqw42zomnxw2lq0.zones.catz. 0 PTR bank.com.
+ group.mjqw42zomnxw2lq0.zones.catz. 0 TXT signed
+
+And the server in this case is configured to distinguish the groups by applying
+different templates::
+
+ template:
+ - id: unsigned
+ ...
+
+ - id: signed
+ dnssec-signing: on
+ dnssec-policy: ...
+ ...
+
+ zone:
+ - domain: catz.
+ file: ...
+ catalog-role: interpret
+ catalog-template: [ unsigned, signed ]
+
+.. _DNS_over_QUIC:
+
+DNS over QUIC
+=============
+
+QUIC is a low-latency, encrypted, internet transport protocol.
+Knot DNS supports DNS over QUIC (DoQ) (:rfc:`9250`), including zone transfers (XoQ).
+By default, the UDP port `853` is used for DNS over QUIC.
+
+To use QUIC, a server :ref:`private key<server_key-file>` and a :ref:`certificate<server_cert-file>`
+must be available. If no key is configured, the server automatically generates one
+with a self-signed temporary certificate. The key is stored in the KASP database
+directory for persistence across restarts.
+
+In order to listen for incoming requests over QUIC, at least one :ref:`interface<server_listen-quic>`
+or :ref:`XDP interface<xdp_quic>` must be configured.
+
+An example of configuration of listening for DNS over QUIC on the loopback interface:
+
+.. code-block:: console
+
+ server:
+ listen-quic: ::1
+
+When the server is started, it logs some interface details and public key pin
+of the used certificate:
+
+.. code-block:: console
+
+ ... info: binding to QUIC interface ::1@853
+ ... info: QUIC, certificate public key 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw=
+
+.. TIP::
+
+ The public key pin, which isn't secret, can also be displayed via:
+
+ .. code-block:: console
+
+ $ knotc status cert-key
+ 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw=
+
+ Or from the keyfile via:
+
+ .. code-block:: console
+
+ $ certtool --infile=quic_key.pem -k | grep pin-sha256
+ pin-sha256:0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw=
+
+Using :doc:`kdig<man_kdig>` we can verify that the server responds over QUIC:
+
+.. code-block:: console
+
+ $ kdig @::1 ch txt version.server +quic
+ ;; QUIC session (QUICv1)-(TLS1.3)-(ECDHE-X25519)-(EdDSA-Ed25519)-(AES-256-GCM)
+ ;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 0
+ ;; Flags: qr rd; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 1
+
+ ;; EDNS PSEUDOSECTION:
+ ;; Version: 0; flags: ; UDP size: 1232 B; ext-rcode: NOERROR
+ ;; PADDING: 370 B
+
+ ;; QUESTION SECTION:
+ ;; version.server. CH TXT
+
+ ;; ANSWER SECTION:
+ version.server. 0 CH TXT "Knot DNS 3.3.0"
+
+ ;; Received 468 B
+ ;; Time 2023-08-15 15:04:36 CEST
+ ;; From ::1@853(QUIC) in 1.1 ms
+
+In this case, :rfc:`opportunistic authentication<9103#section-9.3.1>` was
+used, which doesn't guarantee that the client communicates with the genuine server
+and vice versa. For :rfc:`strict authentication<9103#section-9.3.2>`
+of the server, we can enforce certificate key pin check by specifying it
+(enabled debug mode for details):
+
+.. code-block:: console
+
+ $ kdig @::1 ch txt version.server +tls-pin=0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw= +quic -d
+ ;; DEBUG: Querying for owner(version.server.), class(3), type(16), server(::1), port(853), protocol(UDP)
+ ;; DEBUG: TLS, received certificate hierarchy:
+ ;; DEBUG: #1, CN=tester
+ ;; DEBUG: SHA-256 PIN: 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw=, MATCH
+ ;; DEBUG: TLS, skipping certificate verification
+ ;; QUIC session (QUICv1)-(TLS1.3)-(ECDHE-X25519)-(EdDSA-Ed25519)-(AES-256-GCM)
+ ...
+
+We see that a server certificate key matches the specified pin. Another possibility
+is to use certificate chain validation if a suitable certificate is configured
+on the server.
+
+Zone transfers
+--------------
+
+For outgoing requests (e.g. NOTIFY and refresh), Knot DNS utilizes
+:rfc:`session resumption<9250#section-5.5.3>`, which speeds up QUIC connection
+establishment.
+
+Here are a few examples of zone transfer configurations using various
+:rfc:`authentication mechanisms<9103#section-9>`:
+
+Opportunistic authentication:
+.............................
+
+Primary and secondary can authenticate using TSIG. Fallback to clear-text DNS
+isn't supported.
+
+.. panels::
+
+ Primary:
+
+ .. code-block:: console
+
+ server:
+ listen-quic: ::1
+ automatic-acl: on
+
+ key:
+ - id: xfr_key
+ algorithm: hmac-sha256
+ secret: S059OFJv1SCDdR2P6JKENgWaM409iq2X44igcJdERhc=
+
+ remote:
+ - id: secondary
+ address: ::2
+ key: xfr_key # TSIG for secondary authentication
+ quic: on
+
+ zone:
+ - domain: example.com
+ notify: secondary
+
+ ---
+
+ Secondary:
+
+ .. code-block:: console
+
+ server:
+ listen-quic: ::2
+ automatic-acl: on
+
+ key:
+ - id: xfr_key
+ algorithm: hmac-sha256
+ secret: S059OFJv1SCDdR2P6JKENgWaM409iq2X44igcJdERhc=
+
+ remote:
+ - id: primary
+ address: ::1
+ key: xfr_key # TSIG for primary authentication
+ quic: on
+
+ zone:
+ - domain: example.com
+ master: primary
+
+Strict authentication:
+......................
+
+Note that the automatic ACL doesn't work in this case due to asymmetrical
+configuration. The secondary can authenticate using TSIG.
+
+.. panels::
+
+ Primary:
+
+ .. code-block:: console
+
+ server:
+ listen-quic: ::1
+
+ key:
+ - id: secondary_key
+ algorithm: hmac-sha256
+ secret: S059OFJv1SCDdR2P6JKENgWaM409iq2X44igcJdERhc=
+
+ remote:
+ - id: secondary
+ address: ::2
+ quic: on
+
+ acl:
+ - id: secondary_xfr
+ address: ::2
+ key: secondary_key # TSIG for secondary authentication
+ action: transfer
+
+ zone:
+ - domain: example.com
+ notify: secondary
+ acl: secondary_xfr
+
+ ---
+
+ Secondary:
+
+ .. code-block:: console
+
+ server:
+ listen-quic: ::2
+
+ key:
+ - id: secondary_key
+ algorithm: hmac-sha256
+ secret: S059OFJv1SCDdR2P6JKENgWaM409iq2X44igcJdERhc=
+
+ remote:
+ - id: primary
+ address: ::1
+ key: secondary_key # TSIG for secondary authentication
+ quic: on
+
+ acl:
+ - id: primary_notify
+ address: ::1
+ cert-key: 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw=
+ action: notify
+
+ zone:
+ - domain: example.com
+ master: primary
+ acl: primary_notify
+
+Mutual authentication:
+......................
+
+The :rfc:`mutual authentication<9103#section-9.3.3>` guarantees authentication
+for both the primary and the secondary. In this case, TSIG would be redundant.
+This mode is recommended if possible.
+
+.. panels::
+
+ Primary:
+
+ .. code-block:: console
+
+ server:
+ listen-quic: ::1
+ automatic-acl: on
+
+ remote:
+ - id: secondary
+ address: ::2
+ quic: on
+ cert-key: PXqv7/lXn6N7scg/KJWvfU/TEPe5BoIUHQGRLMPr6YQ=
+
+ zone:
+ - domain: example.com
+ notify: secondary
+
+ ---
+
+ Secondary:
+
+ .. code-block:: console
+
+ server:
+ listen-quic: ::2
+ automatic-acl: on
+
+ remote:
+ - id: primary
+ address: ::1
+ quic: on
+ cert-key: 0xtdayWpnJh4Py8goi8cei/gXGD4kJQ+HEqcxS++DBw=
+
+ zone:
+ - domain: example.com
+ master: primary
+
+.. NOTE::
+
+ Instead of certificate verification with specified authentication domain name,
+ Knot DNS uses certificate public key pinning. This approach has much lower
+ overhead and in most cases simplifies configuration and certificate management.
+
+.. _query-modules:
+
+Query modules
+=============
+
+Knot DNS supports configurable query modules that can alter the way
+queries are processed. Each query requires a finite number of steps to
+be resolved. We call this set of steps a *query plan*, an abstraction
+that groups these steps into several stages.
+
+* Before-query processing
+* Answer, Authority, Additional records packet sections processing
+* After-query processing
+
+For example, processing an Internet-class query needs to find an
+answer. Then based on the previous state, it may also append an
+authority SOA or provide additional records. Each of these actions
+represents a 'processing step'. Now, if a query module is loaded for a
+zone, it is provided with an implicit query plan which can be extended
+by the module or even changed altogether.
+
+A module is active if its name, which includes the ``mod-`` prefix, is assigned
+to the zone/template :ref:`zone_module` option or to the ``default`` template
+:ref:`template_global-module` option if activating for all queries.
+If the module is configurable, a corresponding module section with
+an identifier must be created and then referenced in the form of
+``module_name/module_id``. See :ref:`Modules` for the list of available modules.
+
+The same module can be specified multiple times, such as a global module and
+a per-zone module, or with different configurations. However, not all modules
+are intended for this, for example, mod-cookies! Global modules are executed
+before per-zone modules.
+
+.. NOTE::
+ Query modules are processed in the order they are specified in the
+ zone/template configuration. In most cases, the recommended order is::
+
+ mod-synthrecord, mod-onlinesign, mod-cookies, mod-rrl, mod-dnstap, mod-stats
+
+Performance Tuning
+==================
+
+Numbers of Workers
+------------------
+
+There are three types of workers ready for parallel execution of performance-oriented tasks:
+UDP workers, TCP workers, and Background workers. The first two types handle all network requests
+via the UDP and TCP protocol (respectively) and do the response jobs for common
+queries. Background workers process changes to the zone.
+
+By default, Knot determines a well-fitting number of workers based on the number of CPU cores.
+The user can specify the number of workers for each type with configuration/server section:
+:ref:`server_udp-workers`, :ref:`server_tcp-workers`, :ref:`server_background-workers`.
+
+An indication of when to increase the number of workers is when the server is lagging behind
+expected performance, while CPU usage remains low. This is usually due to waiting for network
+or I/O response during the operation. It may be caused by Knot design not fitting the use-case well.
+The user should try increasing the number of workers (of the related type) slightly above 100 and if
+the performance improves, decide a further, exact setting.
+
+Number of available file descriptors
+------------------------------------
+
+A name server configured for a large number of zones (hundreds or more) needs enough file descriptors
+available for zone transfers and zone file updates, which default OS settings often don't provide.
+It's necessary to check with the OS configuration and documentation and ensure the number of file
+descriptors (sometimes called a number of concurrently open files) effective for the knotd process
+is set suitably high. The number of concurrently open incoming TCP connections must be taken into
+account too. In other words, the required setting is affected by the :ref:`server_tcp-max-clients`
+setting.
+
+Sysctl and NIC optimizations
+----------------------------
+
+There are several recommendations based on Knot developers' experience with their specific HW and SW
+(mainstream Intel-based servers, Debian-based GNU/Linux distribution). They may improve or impact
+performance in common use cases.
+
+If your NIC driver allows it (see /proc/interrupts for hint), set CPU affinity (/proc/irq/$IRQ/smp_affinity)
+manually so that each NIC channel is served by unique CPU core(s). You must turn off irqbalance service
+in advance to avoid configuration override.
+
+Configure sysctl as follows: ::
+
+ socket_bufsize=1048576
+ busy_latency=0
+ backlog=40000
+ optmem_max=20480
+
+ net.core.wmem_max = $socket_bufsize
+ net.core.wmem_default = $socket_bufsize
+ net.core.rmem_max = $socket_bufsize
+ net.core.rmem_default = $socket_bufsize
+ net.core.busy_read = $busy_latency
+ net.core.busy_poll = $busy_latency
+ net.core.netdev_max_backlog = $backlog
+ net.core.optmem_max = $optmem_max
+
+Disable huge pages.
+
+Configure your CPU to "performance" mode. This can be achieved depending on architecture, e.g. in BIOS,
+or e.g. configuring /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor to "performance".
+
+Tune your NIC device with ethtool: ::
+
+ ethtool -A $dev autoneg off rx off tx off
+ ethtool -K $dev tso off gro off ufo off
+ ethtool -G $dev rx 4096 tx 4096
+ ethtool -C $dev rx-usecs 75
+ ethtool -C $dev tx-usecs 75
+ ethtool -N $dev rx-flow-hash udp4 sdfn
+ ethtool -N $dev rx-flow-hash udp6 sdfn
+
+On FreeBSD you can just: ::
+
+ ifconfig ${dev} -rxcsum -txcsum -lro -tso
+
+Knot developers are open to hear about users' further suggestions about network devices tuning/optimization.
diff --git a/doc/ext/ignore_panels.py b/doc/ext/ignore_panels.py
new file mode 100644
index 0000000..ce59513
--- /dev/null
+++ b/doc/ext/ignore_panels.py
@@ -0,0 +1,18 @@
+from docutils.parsers.rst import Directive
+
+class IgnorePanels(Directive):
+
+ has_content = True
+
+ def run(self):
+ return list()
+
+def setup(app):
+
+ app.add_directive("panels", IgnorePanels)
+
+ return {
+ 'version': '0.1',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
diff --git a/doc/index.rst b/doc/index.rst
new file mode 100644
index 0000000..c2bd3dd
--- /dev/null
+++ b/doc/index.rst
@@ -0,0 +1,19 @@
+.. highlight:: none
+
+Welcome to Knot DNS's documentation!
+====================================
+
+.. toctree::
+ :maxdepth: 2
+
+ introduction
+ requirements
+ installation
+ configuration
+ operation
+ troubleshooting
+ reference
+ modules
+ utilities
+ migration
+ appendices
diff --git a/doc/installation.rst b/doc/installation.rst
new file mode 100644
index 0000000..f89f439
--- /dev/null
+++ b/doc/installation.rst
@@ -0,0 +1,92 @@
+.. highlight:: none
+.. _Installation:
+
+************
+Installation
+************
+
+.. _Installation from a package_:
+
+Installation from a package
+===========================
+
+Knot DNS may already be included in your operating system distribution and
+therefore can be installed from packages (Linux), ports (BSD), or via
+Homebrew (macOS). This is always preferred unless you want to test the latest
+features, contribute to Knot development, or you know what you are doing.
+
+See the project `download <https://www.knot-dns.cz/download>`_ page for
+the latest information.
+
+.. _Installation from source code:
+
+Installation from source code
+=============================
+
+Required build environment
+--------------------------
+
+The build process relies on these standard tools:
+
+* make
+* libtool
+* pkg-config
+* autoconf >= 2.65
+* python-sphinx (optional, for documentation building)
+
+GCC >= 4.1 is mandatory for atomic built-ins, but the latest
+available version is recommended. Another requirement is ``_GNU_SOURCE``
+and C99 support, otherwise it adapts to the available compiler features.
+LLVM clang compiler since version 2.9 can be used as well.
+
+Getting the source code
+-----------------------
+
+You can find the source code for the latest release on `www.knot-dns.cz <https://www.knot-dns.cz>`_.
+Alternatively, you can fetch the whole project from the git repository
+`https://gitlab.nic.cz/knot/knot-dns.git <https://gitlab.nic.cz/knot/knot-dns>`_.
+
+After obtaining the source code, compilation and installation is quite a
+straightforward process using autotools.
+
+.. _Configuring and generating Makefiles:
+
+Configuring and generating Makefiles
+------------------------------------
+
+If compiling from git source, you need to bootstrap the ``./configure`` file first::
+
+ $ autoreconf -i -f
+
+In most cases, you can just run configure without any options::
+
+ $ ./configure
+
+For all available configure options run::
+
+ $ ./configure --help
+
+Compilation
+-----------
+
+After running ``./configure`` you can compile Knot DNS by running
+``make`` command, which will produce binaries and other related
+files::
+
+ $ make
+
+.. NOTE::
+ The compilation with enabled optimizations may take a long time. In such
+ a case the ``--disable-fastparser`` configure option can help.
+
+Installation
+------------
+
+When you have finished building Knot DNS, it's time to install the
+binaries and configuration files into the operation system hierarchy.
+You can do so by executing::
+
+ $ make install
+
+When installing as a non-root user, you might have to gain elevated privileges by
+switching to root user, e.g. ``sudo make install`` or ``su -c 'make install'``.
diff --git a/doc/introduction.rst b/doc/introduction.rst
new file mode 100644
index 0000000..0174f05
--- /dev/null
+++ b/doc/introduction.rst
@@ -0,0 +1,87 @@
+.. highlight:: none
+.. _Introduction:
+
+************
+Introduction
+************
+
+What is Knot DNS
+================
+
+Knot DNS is a high-performance open-source DNS server. It
+implements only the authoritative domain name service. Knot DNS
+can reliably serve TLD domains as well as any other zones.
+
+Knot DNS benefits from its multi-threaded and mostly lock-free
+implementation which allows it to scale well on SMP systems and
+operate non-stop even when adding or removing zones.
+
+The server itself is accompanied by several utilities for general DNS
+operations or for maintaining the server.
+
+For more info and downloads see `www.knot-dns.cz <https://www.knot-dns.cz>`_.
+
+Knot DNS features
+=================
+
+DNS features:
+
+* Primary and secondary server operation
+* Internet (IN) and Chaos (CH) classes
+* DNS extension (EDNS0, EDE, EXPIRE)
+* UDP, TCP, and QUIC protocols
+* Zone catalog generation and interpretation
+* Minimal responses
+* Dynamic zone updates
+* DNSSEC with NSEC and NSEC3
+* ZONEMD generation and validation
+* Transaction signature using TSIG
+* Full and incremental zone transfers (AXFR, IXFR)
+* Name server identification using NSID or Chaos TXT records
+* Resource record types A, NS, CNAME, SOA, PTR, HINFO, MINFO, MX,
+ TXT, RP, AFSDB, RT, KEY, AAAA, LOC, SRV, NAPTR, KX, CERT, DNAME, APL, DS,
+ SSHFP, IPSECKEY, RRSIG, NSEC, DNSKEY, DHCID, NSEC3, NSEC3PARAM, TLSA, SMIMEA,
+ CDS, CDNSKEY, OPENPGPKEY, CSYNC, ZONEMD, SVCB, HTTPS, SPF, NID, L32, L64, LP,
+ EUI48, EUI64, URI, CAA, and Unknown
+
+Server features:
+
+* IPv4 and IPv6 support
+* Semantic zone checks
+* Server control interface
+* Zone journal storage
+* Persistent zone event timers
+* YAML-based or database-based configuration
+* Query processing modules with dynamic loading
+* On-the-fly zone management and server reconfiguration
+* Multithreaded DNSSEC zone signing and zone validation
+* Automatic DNSSEC key management
+* Zone data backup and restore
+* Offline KSK operation
+* PKCS #11 interface
+
+Remarkable module extensions:
+
+* Response rate limiting
+* Forward and reverse records synthesis
+* DNS request traffic statistics
+* Efficient DNS traffic logging interface
+* Dnstap traffic logging
+* Online DNSSEC signing
+* GeoIP response tailoring supporting ECS and DNSSEC
+
+Remarkable supported networking features:
+
+* TCP Fast Open (client and server)
+* Opportunistic, strict, and mutual authentication profiles over QUIC
+* High-performance UDP, TCP, and QUIC through AF_XDP processing (on Linux 4.18+)
+* SO_REUSEPORT (on Linux) or SO_REUSEPORT_LB (on FreeBSD 12.0+) on UDP and by choice on TCP
+* Binding to non-local addresses (IP_FREEBIND on Linux, IP_BINDANY/IPV6_BINDANY on FreeBSD)
+* Ignoring PMTU information for IPv4/UDP via IP_PMTUDISC_OMIT
+
+License
+=======
+
+Knot DNS is licensed under the `GNU General Public License <https://www.gnu.org/copyleft/gpl.html>`_
+version 3 or (at your option) any later version. The full text of the license
+is available in the ``COPYING`` file distributed with source code.
diff --git a/doc/logo.pdf b/doc/logo.pdf
new file mode 100644
index 0000000..113566b
--- /dev/null
+++ b/doc/logo.pdf
Binary files differ
diff --git a/doc/logo.svg b/doc/logo.svg
new file mode 100644
index 0000000..e0085ca
--- /dev/null
+++ b/doc/logo.svg
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Vrstva_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 600 225" style="enable-background:new 0 0 600 225;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#003893;}
+</style>
+<path class="st0" d="M319.2,106.8l-30.5-37.9h-0.2v37.9h-19.5V24.6h19.5V58h0.4l29.4-33.4H343l-35.4,37.9l37.5,44.4H319.2
+ M407.2,106.8L374.1,53h-0.3l0.5,53.8h-19.3V24.6h22.6l33,53.6h0.4l-0.5-53.6h19.3v82.2H407.2z M486.1,109
+ c-25.7,0-44.7-17.7-44.7-43.7c0-26.4,19-43,44.7-43c25.8,0,44.8,16.6,44.8,43C530.9,91.3,511.9,109,486.1,109z M486.1,40.3
+ c-13.9,0-23.5,10.7-23.5,25.1c0,14.9,9.6,25.5,23.5,25.5c13.8,0,23.6-10.7,23.6-25.5C509.7,50.9,500,40.3,486.1,40.3z M576.8,41.5
+ v65.3h-19.9V41.5h-23.2v-17H600v17H576.8z M299.6,200.2h-30.7V118h29.7c23.3,0,47,9.8,47,40.9C345.7,187.8,322.2,200.2,299.6,200.2z
+ M298.2,134.9h-9.9V183h9.4c14.2,0,27.3-5.8,27.3-24.2C325,140.4,311.9,134.9,298.2,134.9z M407.2,200.2l-33.1-53.8h-0.3l0.5,53.8
+ h-19.3V118h22.6l33,53.6h0.4l-0.5-53.6h19.3v82.2H407.2z M488.6,139.3c-3.4-4.3-9.5-7.1-14.6-7.1c-5.1,0-11.5,1.7-11.5,8.2
+ c0,5.5,4.9,7.2,12.7,9.6c11.1,3.6,25.5,8.4,25.5,24.7c0,18.9-15.2,27.4-31.5,27.4c-11.7,0-23.6-4.3-30.8-11.8l13-13.2
+ c3.9,5,11.3,8.7,17.8,8.7c6,0,11.4-2.3,11.4-8.9c0-6.3-6.3-8.2-17.1-11.7c-10.5-3.4-21-8.7-21-23.6c0-18.2,16.5-25.8,31.8-25.8
+ c9.3,0,19.7,3.5,26.9,10.1L488.6,139.3z M184.9,27.1c1.3,6.9,2.1,14,2.1,21.3c0,22.2-6.6,43-17.9,60.4c-0.4,0.6-0.8,1.2-1.2,1.8
+ c-0.4,0.6-0.8,1.2-1.2,1.7c-4.3,6.2-9.3,11.9-14.8,17.1c-0.5,0.5-1,0.9-1.5,1.4c-0.5,0.5-1,0.9-1.5,1.4c-10.9,9.6-23.6,17-37.6,21.8
+ c-3.5-6.3-6.2-13.1-8.1-20.3c12-3.9,23-10.3,32.2-18.6c0.5-0.4,1-0.9,1.4-1.3c0.5-0.4,1-0.9,1.4-1.4c5.2-5.1,9.8-10.9,13.6-17.1
+ c0.4-0.6,0.7-1.2,1-1.7c0.4-0.6,0.7-1.2,1-1.8c7.1-12.9,11.2-27.6,11.2-43.3c0-6.4-0.7-12.6-2-18.6c-0.1-0.7-0.3-1.3-0.4-1.9
+ c-0.2-0.6-0.3-1.3-0.5-1.9c-0.6,0.2-1.3,0.3-1.9,0.5c-0.6,0.2-1.3,0.4-1.9,0.6c-20.6,6.7-37.9,20.7-49,38.9
+ c-7.2-2.2-14.7-3.8-22.4-4.6c13.2-25.5,35.8-45.3,63.3-54.6c0,0,0,0,0,0c-12.1-4.5-25.3-6.9-38.9-6.9C55.7-0.1,9.4,40.5,0.6,93.8
+ c0.5-0.4,1-0.9,1.5-1.3c19.6-17.2,45.3-27.7,73.4-27.7c1.9,0,3.7,0,5.5,0.1c0.7,0,1.4,0.1,2.1,0.1c0.7,0.1,1.4,0.1,2.1,0.2
+ c7.7,0.7,15.1,2.1,22.2,4.3c0.6,0.2,1.3,0.4,1.9,0.6c0.6,0.2,1.3,0.4,1.9,0.6c14,4.8,26.7,12.2,37.6,21.8c-3.8,6.3-8.3,12-13.5,17.1
+ c-9.2-8.3-20.1-14.7-32.1-18.6c-0.6-0.2-1.2-0.4-1.9-0.6c-0.6-0.2-1.3-0.4-1.9-0.6c-6.9-1.9-14.2-3-21.6-3.2c-0.7,0-1.4,0-2.1,0
+ h-0.3c-0.6,0-1.2,0-1.8,0c-22.3,0.4-42.7,9-58.1,23c-0.5,0.4-1,0.9-1.4,1.3c-0.5,0.4-1,0.9-1.4,1.4c0.4,0.4,0.9,0.9,1.4,1.4
+ c0.5,0.5,1,0.9,1.5,1.3c15.5,13.9,35.8,22.5,58.1,23c1.7,7.5,4.2,14.8,7.3,21.7c-1.8,0.1-3.7,0.1-5.5,0.1
+ c-28.1,0-53.8-10.5-73.4-27.7c-0.5-0.4-1-0.9-1.5-1.3c8.8,53.3,55.1,94,110.9,94c13.7,0,26.8-2.4,38.9-6.9
+ c-27.5-9.4-50.1-29.2-63.3-54.7c-0.3-0.6-0.6-1.3-0.9-1.9c-0.3-0.6-0.6-1.3-0.9-1.9c-3.2-6.8-5.7-13.9-7.5-21.4
+ c-0.2-0.6-0.3-1.3-0.4-2c-0.2-0.6-0.3-1.3-0.4-2c-1.4-7-2.1-14.3-2.1-21.7c0-7.4,0.7-14.7,2.1-21.7c7.5,0.1,14.7,1.2,21.6,3.1
+ c-1.3,6-1.9,12.2-1.9,18.6s0.7,12.6,1.9,18.6c0.1,0.6,0.3,1.3,0.4,1.9c0.2,0.6,0.3,1.3,0.5,1.9c1.9,7.2,4.6,14,8,20.4
+ c0.3,0.6,0.6,1.2,1,1.8c0.3,0.6,0.7,1.2,1,1.8c11.1,18.2,28.4,32.2,49,38.9c0.6,0.2,1.3,0.4,1.9,0.6c0.6,0.2,1.3,0.4,1.9,0.5
+ c0.2-0.6,0.3-1.3,0.5-1.9c0.2-0.6,0.3-1.3,0.4-2c1.3-6,2-12.2,2-18.6c0-15.7-4.1-30.5-11.2-43.3c5.6-5.2,10.7-10.9,15.1-17.1
+ c11.3,17.4,17.9,38.2,17.9,60.5c0,7.3-0.7,14.4-2.1,21.2c23.9-20.6,39-51.1,39-85.2C223.9,78.3,208.8,47.8,184.9,27.1z"/>
+</svg>
diff --git a/doc/man/kcatalogprint.8in b/doc/man/kcatalogprint.8in
new file mode 100644
index 0000000..da964d8
--- /dev/null
+++ b/doc/man/kcatalogprint.8in
@@ -0,0 +1,80 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KCATALOGPRINT" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+kcatalogprint \- Knot DNS catalog print utility
+.SH SYNOPSIS
+.sp
+\fBkcatalogprint\fP [\fIconfig_option\fP] [\fIoptions\fP]
+.SH DESCRIPTION
+.sp
+The program prints zone catalog stored in a catalog database.
+.SS Config options
+.INDENT 0.0
+.TP
+\fB\-c\fP, \fB\-\-config\fP \fIfile\fP
+Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP).
+.TP
+\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP
+Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP).
+The default configuration database, if exists, has a preference to the default
+configuration file.
+.TP
+\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP
+Use specified catalog database path and default configuration.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-a\fP, \fB\-\-catalog\fP
+Filter the output by catalog zone name.
+.TP
+\fB\-m\fP, \fB\-\-member\fP
+Filter the output by member zone name.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH SEE ALSO
+.sp
+\fBknotd(8)\fP, \fBknot.conf(5)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/kdig.1in b/doc/man/kdig.1in
new file mode 100644
index 0000000..99745c9
--- /dev/null
+++ b/doc/man/kdig.1in
@@ -0,0 +1,464 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KDIG" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+kdig \- Advanced DNS lookup utility
+.SH SYNOPSIS
+.sp
+\fBkdig\fP [\fIcommon\-settings\fP] [\fIquery\fP [\fIsettings\fP]]...
+.sp
+\fBkdig\fP \fB\-h\fP
+.SH DESCRIPTION
+.sp
+This utility sends one or more DNS queries to a nameserver. Each query can have
+individual \fIsettings\fP, or it can be specified globally via \fIcommon\-settings\fP,
+which must precede \fIquery\fP specification.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIquery\fP
+\fIname\fP | \fB\-q\fP \fIname\fP | \fB\-x\fP \fIaddress\fP | \fB\-G\fP \fItapfile\fP
+.TP
+\fIcommon\-settings\fP, \fIsettings\fP
+[\fIquery_class\fP] [\fIquery_type\fP] [\fB@\fP\fIserver\fP]... [\fIoptions\fP]
+.TP
+\fIname\fP
+Is a domain name that is to be looked up.
+.TP
+\fIserver\fP
+Is a domain name or an IPv4 or IPv6 address of the nameserver to send a query
+to. An additional port can be specified using address:port ([address]:port
+for IPv6 address), address@port, or address#port notation. A value which begins
+with \(aq/\(aq character is considered an absolute UNIX socket path. If no server is
+specified, the servers from \fB/etc/resolv.conf\fP are used.
+.UNINDENT
+.sp
+If no arguments are provided, \fBkdig\fP sends NS query for the root
+zone.
+.SS Query classes
+.sp
+A \fIquery_class\fP can be either a DNS class name (IN, CH) or generic class
+specification \fBCLASS\fP\fIXXXXX\fP where \fIXXXXX\fP is a corresponding decimal
+class number. The default query class is IN.
+.SS Query types
+.sp
+A \fIquery_type\fP can be either a DNS resource record type
+(A, AAAA, NS, SOA, DNSKEY, ANY, etc.) or one of the following:
+.INDENT 0.0
+.TP
+\fBTYPE\fP\fIXXXXX\fP
+Generic query type specification where \fIXXXXX\fP is a corresponding decimal
+type number.
+.TP
+\fBAXFR\fP
+Full zone transfer request.
+.TP
+\fBIXFR=\fP\fIserial\fP
+Incremental zone transfer request for specified SOA serial number
+(i.e. all zone updates since the specified zone version are to be returned).
+.TP
+\fBNOTIFY=\fP\fIserial\fP
+Notify message with a SOA serial hint specified.
+.TP
+\fBNOTIFY\fP
+Notify message with a SOA serial hint unspecified.
+.UNINDENT
+.sp
+The default query type is A.
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-4\fP
+Use the IPv4 protocol only.
+.TP
+\fB\-6\fP
+Use the IPv6 protocol only.
+.TP
+\fB\-b\fP \fIaddress\fP
+Set the source IP address of the query to \fIaddress\fP\&. The address must be a
+valid address for local interface or :: or 0.0.0.0. An optional port
+can be specified in the same format as the \fIserver\fP value.
+.TP
+\fB\-c\fP \fIclass\fP
+An explicit \fIquery_class\fP specification. See possible values above.
+.TP
+\fB\-d\fP
+Enable debug messages.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-k\fP \fIkeyfile\fP
+Use the TSIG key stored in a file \fIkeyfile\fP to authenticate the request. The
+file must contain the key in the same format as accepted by the
+\fB\-y\fP option.
+.TP
+\fB\-p\fP \fIport\fP
+Set the nameserver port number or service name to send a query to. The default
+port is 53.
+.TP
+\fB\-q\fP \fIname\fP
+Set the query name. An explicit variant of \fIname\fP specification. If no \fIname\fP
+is provided, empty question section is set.
+.TP
+\fB\-t\fP \fItype\fP
+An explicit \fIquery_type\fP specification. See possible values above.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.TP
+\fB\-x\fP \fIaddress\fP
+Send a reverse (PTR) query for IPv4 or IPv6 \fIaddress\fP\&. The correct name, class
+and type is set automatically.
+.TP
+\fB\-y\fP [\fIalg\fP:]\fIname\fP:\fIkey\fP
+Use the TSIG key named \fIname\fP to authenticate the request. The \fIalg\fP
+part specifies the algorithm (the default is hmac\-sha256) and \fIkey\fP specifies
+the shared secret encoded in Base64.
+.TP
+\fB\-E\fP \fItapfile\fP
+Export a dnstap trace of the query and response messages received to the
+file \fItapfile\fP\&.
+.TP
+\fB\-G\fP \fItapfile\fP
+Generate message output from a previously saved dnstap file \fItapfile\fP\&.
+.TP
+\fB+\fP[\fBno\fP]\fBmultiline\fP
+Wrap long records to more lines and improve human readability.
+.TP
+\fB+\fP[\fBno\fP]\fBshort\fP
+Show record data only.
+.TP
+\fB+\fP[\fBno\fP]\fBgeneric\fP
+Use the generic representation format when printing resource record types
+and data.
+.TP
+\fB+\fP[\fBno\fP]\fBcrypto\fP
+Display the DNSSEC keys and signatures values in base64, instead of omitting them.
+.TP
+\fB+\fP[\fBno\fP]\fBaaflag\fP
+Set the AA flag.
+.TP
+\fB+\fP[\fBno\fP]\fBtcflag\fP
+Set the TC flag.
+.TP
+\fB+\fP[\fBno\fP]\fBrdflag\fP
+Set the RD flag.
+.TP
+\fB+\fP[\fBno\fP]\fBrecurse\fP
+Same as \fB+\fP[\fBno\fP]\fBrdflag\fP
+.TP
+\fB+\fP[\fBno\fP]\fBraflag\fP
+Set the RA flag.
+.TP
+\fB+\fP[\fBno\fP]\fBzflag\fP
+Set the zero flag bit.
+.TP
+\fB+\fP[\fBno\fP]\fBadflag\fP
+Set the AD flag.
+.TP
+\fB+\fP[\fBno\fP]\fBcdflag\fP
+Set the CD flag.
+.TP
+\fB+\fP[\fBno\fP]\fBdnssec\fP
+Set the DO flag.
+.TP
+\fB+\fP[\fBno\fP]\fBall\fP
+Show all packet sections.
+.TP
+\fB+\fP[\fBno\fP]\fBqr\fP
+Show the query packet.
+.TP
+\fB+\fP[\fBno\fP]\fBheader\fP
+Show the packet header.
+.TP
+\fB+\fP[\fBno\fP]\fBcomments\fP
+Show commented section names.
+.TP
+\fB+\fP[\fBno\fP]\fBopt\fP
+Show the EDNS pseudosection.
+.TP
+\fB+\fP[\fBno\fP]\fBopttext\fP
+Try to show unknown EDNS options as text.
+.TP
+\fB+\fP[\fBno\fP]\fBoptpresent\fP
+Show EDNS in presentation format according to the specification in version
+\fI\%draft\-peltan\-edns\-presentation\-format\-01\fP\&.
+.TP
+\fB+\fP[\fBno\fP]\fBquestion\fP
+Show the question section.
+.TP
+\fB+\fP[\fBno\fP]\fBanswer\fP
+Show the answer section.
+.TP
+\fB+\fP[\fBno\fP]\fBauthority\fP
+Show the authority section.
+.TP
+\fB+\fP[\fBno\fP]\fBadditional\fP
+Show the additional section.
+.TP
+\fB+\fP[\fBno\fP]\fBtsig\fP
+Show the TSIG pseudosection.
+.TP
+\fB+\fP[\fBno\fP]\fBstats\fP
+Show trailing packet statistics.
+.TP
+\fB+\fP[\fBno\fP]\fBclass\fP
+Show the DNS class.
+.TP
+\fB+\fP[\fBno\fP]\fBttl\fP
+Show the TTL value.
+.TP
+\fB+\fP[\fBno\fP]\fBtcp\fP
+Use the TCP protocol (default is UDP for standard query and TCP for AXFR/IXFR).
+.TP
+\fB+\fP[\fBno\fP]\fBfastopen\fP
+Use TCP Fast Open.
+.TP
+\fB+\fP[\fBno\fP]\fBignore\fP
+Don\(aqt use TCP automatically if a truncated reply is received.
+.TP
+\fB+\fP[\fBno\fP]\fBkeepopen\fP
+Keep TCP connection open for the following query if it has the same connection
+configuration. This applies to +tcp, +tls, and +https operations. The connection
+is considered in the context of a single kdig call only.
+.TP
+\fB+\fP[\fBno\fP]\fBtls\fP
+Use TLS with the Opportunistic privacy profile (\fI\%RFC 7858#section\-4.1\fP).
+.TP
+\fB+\fP[\fBno\fP]\fBtls\-ca\fP[=\fIFILE\fP]
+Use TLS with a certificate validation. Certification authority certificates
+are loaded from the specified PEM file (default is system certificate storage
+if no argument is provided).
+Can be specified multiple times. If the +tls\-hostname option is not provided,
+the name of the target server (if specified) is used for strict authentication.
+.TP
+\fB+\fP[\fBno\fP]\fBtls\-pin\fP=\fIBASE64\fP
+Use TLS with the Out\-of\-Band key\-pinned privacy profile (\fI\%RFC 7858#section\-4.2\fP).
+The PIN must be a Base64 encoded SHA\-256 hash of the X.509 SubjectPublicKeyInfo.
+Can be specified multiple times.
+.TP
+\fB+\fP[\fBno\fP]\fBtls\-hostname\fP=\fISTR\fP
+Use TLS with a remote server hostname check.
+.TP
+\fB+\fP[\fBno\fP]\fBtls\-sni\fP=\fISTR\fP
+Use TLS with a Server Name Indication.
+.TP
+\fB+\fP[\fBno\fP]\fBtls\-keyfile\fP=\fIFILE\fP
+Use TLS with a client keyfile.
+.TP
+\fB+\fP[\fBno\fP]\fBtls\-certfile\fP=\fIFILE\fP
+Use TLS with a client certfile.
+.TP
+\fB+\fP[\fBno\fP]\fBtls\-ocsp\-stapling\fP[=\fIH\fP]
+Use TLS with a valid stapled OCSP response for the server certificate
+(%u or specify hours). OCSP responses older than the specified period are
+considered invalid.
+.TP
+\fB+\fP[\fBno\fP]\fBhttps\fP[=\fIURL\fP]
+Use HTTPS (DNS\-over\-HTTPS) in wire format (\fI\%RFC 1035#section\-4.2.1\fP).
+It is also possible to specify URL=[authority][/path] where request
+will be sent to. Any leading scheme and authority indicator (i.e. //) are ignored.
+Authority might also be specified as the \fIserver\fP (using the parameter \fI@\fP).
+If \fIpath\fP is specified and \fIauthority\fP is missing, then the \fIserver\fP
+is used as authority together with the specified \fIpath\fP\&.
+Library \fIlibnghttp2\fP is required.
+.TP
+\fB+\fP[\fBno\fP]\fBhttps\-get\fP
+Use HTTPS with HTTP/GET method instead of the default HTTP/POST method.
+Library \fIlibnghttp2\fP is required.
+.TP
+\fB+\fP[\fBno\fP]\fBquic\fP
+Use QUIC (DNS\-over\-QUIC).
+.TP
+\fB+\fP[\fBno\fP]\fBnsid\fP
+Request the nameserver identifier (NSID).
+.TP
+\fB+\fP[\fBno\fP]\fBbufsize\fP=\fIB\fP
+Set EDNS buffer size in bytes (default is 4096 bytes).
+.TP
+\fB+\fP[\fBno\fP]\fBpadding\fP[=\fIB\fP]
+Use EDNS(0) padding option to pad queries, optionally to a specific
+size. The default is to pad queries with a sensible amount when using
++tls, and not to pad at all when queries are sent without TLS. With
+no argument (i.e., just +padding) pad every query with a sensible
+amount regardless of the use of TLS. With +nopadding, never pad.
+.TP
+\fB+\fP[\fBno\fP]\fBalignment\fP[=\fIB\fP]
+Align the query to B\-byte\-block message using the EDNS(0) padding option
+(default is no or 128 if no argument is specified).
+.TP
+\fB+\fP[\fBno\fP]\fBsubnet\fP=\fISUBN\fP
+Set EDNS(0) client subnet SUBN=addr/prefix.
+.TP
+\fB+\fP[\fBno\fP]\fBedns\fP[=\fIN\fP]
+Use EDNS version (default is 0).
+.TP
+\fB+\fP[\fBno\fP]\fBtimeout\fP=\fIT\fP
+Set the wait\-for\-reply interval in seconds (default is 5 seconds). This timeout
+applies to each query attempt. Zero value or \fInotimeout\fP is interpreted as
+infinity.
+.TP
+\fB+\fP[\fBno\fP]\fBretry\fP=\fIN\fP
+Set the number (>=0) of UDP retries (default is 2). This doesn\(aqt apply to
+AXFR/IXFR.
+.TP
+\fB+\fP[\fBno\fP]\fBexpire\fP
+Sets the EXPIRE EDNS option.
+.TP
+\fB+\fP[\fBno\fP]\fBcookie\fP[=\fIHEX\fP]
+Attach EDNS(0) cookie to the query.
+.TP
+\fB+\fP[\fBno\fP]\fBbadcookie\fP
+Repeat a query with the correct cookie.
+.TP
+\fB+\fP[\fBno\fP]\fBednsopt\fP[=\fICODE\fP[:\fIHEX\fP]]
+Send custom EDNS option. The \fICODE\fP is EDNS option code in decimal, \fIHEX\fP
+is an optional hex encoded string to use as EDNS option value. This argument
+can be used multiple times. +noednsopt clears all EDNS options specified by
++ednsopt.
+.TP
+\fB+\fP[\fBno\fP]\fBproxy\fP=\fISRC_ADDR\fP[#\fISRC_PORT\fP]\-\fIDST_ADDR\fP[#\fIDST_PORT\fP]
+Add PROXYv2 header with the specified source and destination addresses to the query.
+The default source port is 0 and destination port 53.
+.TP
+\fB+\fP[\fBno\fP]\fBjson\fP
+Use JSON for output encoding (RFC 8427).
+.TP
+\fB+noidn\fP
+Disable the IDN transformation to ASCII and vice versa. IDN support depends
+on libidn availability during project building! If used in \fIcommon\-settings\fP,
+all IDN transformations are disabled. If used in the individual query \fIsettings\fP,
+transformation from ASCII is disabled on output for the particular query. Note
+that IDN transformation does not preserve domain name letter case.
+.UNINDENT
+.SH NOTES
+.sp
+Options \fB\-k\fP and \fB\-y\fP can not be used simultaneously.
+.sp
+Dnssec\-keygen keyfile format is not supported. Use \fBkeymgr(8)\fP instead.
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.INDENT 0.0
+.IP 1. 3
+Get A records for example.com:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ kdig example.com A
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 2. 3
+Perform AXFR for zone example.com from the server 192.0.2.1:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ kdig example.com \-t AXFR @192.0.2.1
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 3. 3
+Get A records for example.com from 192.0.2.1 and reverse lookup for address
+2001:DB8::1 from 192.0.2.2. Both using the TCP protocol:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ kdig +tcp example.com \-t A @192.0.2.1 \-x 2001:DB8::1 @192.0.2.2
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 4. 3
+Get SOA record for example.com, use TLS, use system certificates, check
+for specified hostname, check for certificate pin, and print additional
+debug info:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ kdig \-d @185.49.141.38 +tls\-ca +tls\-host=getdnsapi.net \e
+ +tls\-pin=foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S= soa example.com
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 5. 3
+DNS over HTTPS examples (various DoH implementations):
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ kdig @1.1.1.1 +https example.com.
+$ kdig @193.17.47.1 +https=/doh example.com.
+$ kdig @8.8.4.4 +https +https\-get example.com.
+$ kdig @8.8.8.8 +https +tls\-hostname=dns.google +fastopen example.com.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 6. 3
+More queries share one DoT connection:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ kdig @1.1.1.1 +tls +keepopen abc.example.com A mail.example.com AAAA
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH FILES
+.sp
+\fB/etc/resolv.conf\fP
+.SH SEE ALSO
+.sp
+\fBkhost(1)\fP, \fBknsupdate(1)\fP, \fBkeymgr(8)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/keymgr.8in b/doc/man/keymgr.8in
new file mode 100644
index 0000000..39c46a9
--- /dev/null
+++ b/doc/man/keymgr.8in
@@ -0,0 +1,372 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KEYMGR" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+keymgr \- Knot DNS key management utility
+.SH SYNOPSIS
+.sp
+\fBkeymgr\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP \fIcommand\fP
+.sp
+\fBkeymgr\fP [\fIconfig_option\fP] [\-j] \fB\-l\fP
+.sp
+\fBkeymgr\fP \fB\-t\fP \fIparameter\fP\&...
+.SH DESCRIPTION
+.sp
+The \fBkeymgr\fP utility serves for manual key management in Knot DNS server.
+.sp
+Functions for DNSSEC keys and KASP (Key And Signature Policy)
+management are provided.
+.sp
+The DNSSEC and KASP configuration is stored in a so called KASP database.
+The database is backed by LMDB.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIzone_name\fP
+Name of the zone the command is executed for.
+.UNINDENT
+.SS Config options
+.INDENT 0.0
+.TP
+\fB\-c\fP, \fB\-\-config\fP \fIfile\fP
+Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP).
+.TP
+\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP
+Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP).
+The default configuration database, if exists, has a preference to the default
+configuration file.
+.TP
+\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP
+Use specified KASP database path and default configuration.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-t\fP, \fB\-\-tsig\fP \fItsig_name\fP [\fItsig_algorithm\fP [\fItsig_bits\fP]]
+Generates a TSIG key for the given name. Optionally the key algorithm can
+be specified by its \fI\%name\fP (default: hmac\-sha256) and
+a bit length of the key (default: optimal length given by algorithm).
+The generated TSIG key is only displayed on \fIstdout\fP:
+the command does not create a file, nor include the key in a keystore.
+.TP
+\fB\-e\fP, \fB\-\-extended\fP
+Extended output (listing of keys with full description).
+.TP
+\fB\-j\fP, \fB\-\-json\fP
+Print the zones or keys in JSON format.
+.TP
+\fB\-l\fP, \fB\-\-list\fP
+Print the list of zones that have at least one key stored in the configured KASP
+database.
+.TP
+\fB\-x\fP, \fB\-\-mono\fP
+Don\(aqt generate colorized output.
+.TP
+\fB\-X\fP, \fB\-\-color\fP
+Force colorized output in the normal mode.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Keymgr runs with the same user privileges as configured for \fI\%knotd\fP\&.
+For example, if keymgr is run as \fBroot\fP, but the configured \fI\%user\fP
+is \fBknot\fP, it won\(aqt be able to read files (PEM files, KASP database, ...) readable
+only by \fBroot\fP\&.
+.UNINDENT
+.UNINDENT
+.SS Commands
+.INDENT 0.0
+.TP
+\fBlist\fP [\fItimestamp_format\fP]
+Prints the list of key IDs and parameters of keys belonging to the zone.
+.TP
+\fBgenerate\fP [\fIarguments\fP\&...]
+Generates new DNSSEC key and stores it in KASP database. Prints the key ID.
+This action takes some number of arguments (see below). Values for unspecified arguments are taken
+from corresponding policy (if \fI\-c\fP or \fI\-C\fP options used) or from Knot policy defaults.
+.TP
+\fBimport\-bind\fP \fIBIND_key_file\fP
+Imports a BIND\-style key into KASP database (converting it to PEM format).
+Takes one argument: path to BIND key file (private or public, but both MUST exist).
+.TP
+\fBimport\-pub\fP \fIBIND_pubkey_file\fP
+Imports a public key into KASP database. This key won\(aqt be rolled over nor used for signing.
+Takes one argument: path to BIND public key file.
+.TP
+\fBimport\-pem\fP \fIPEM_file\fP [\fIarguments\fP\&...]
+Imports a DNSSEC key from PEM file. The key parameters (same as for the generate action) need to be
+specified (mainly algorithm, timers...) because they are not contained in the PEM format.
+.TP
+\fBimport\-pkcs11\fP \fIkey_id\fP [\fIarguments\fP\&...]
+Imports a DNSSEC key from PKCS #11 storage. The key parameters (same as for the generate action) need to be
+specified (mainly algorithm, timers...) because they are not available. In fact, no key
+data is imported, only KASP database metadata is created.
+.TP
+\fBnsec3\-salt\fP [\fInew_salt\fP]
+Prints the current NSEC3 salt used for signing. If \fInew_salt\fP is specified, the salt is overwritten.
+The salt is printed and expected in hexadecimal, or dash if empty.
+.TP
+\fBlocal\-serial\fP [\fInew_serial\fP]
+Print SOA serial stored in KASP database when using on\-secondary DNSSEC signing.
+If \fInew_serial\fP is specified, the serial is overwritten. After updating the serial, expire the zone
+(\fBzone\-purge +expire +zonefile +journal\fP) if the server is running, or remove corresponding zone file
+and journal contents if the server is stopped.
+.TP
+\fBmaster\-serial\fP [\fInew_serial\fP]
+Print SOA serial of the remote master stored in KASP database when using on\-secondary DNSSEC signing.
+If \fInew_serial\fP is specified, the serial is overwritten (not recommended).
+.TP
+\fBset\fP \fIkey_spec\fP [\fIarguments\fP\&...]
+Changes a timing argument (or ksk/zsk) of an existing key to a new value. \fIKey_spec\fP is either the
+key tag or a prefix of the key ID, with an optional \fI[id=|keytag=]\fP prefix; \fIarguments\fP
+are like for \fBgenerate\fP, but just the related ones.
+.TP
+\fBds\fP [\fIkey_spec\fP]
+Generate DS record (all digest algorithms together) for specified key. \fIKey_spec\fP
+is like for \fBset\fP, if unspecified, all KSKs are used.
+.TP
+\fBdnskey\fP [\fIkey_spec\fP]
+Generate DNSKEY record for specified key. \fIKey_spec\fP
+is like for \fBds\fP, if unspecified, all KSKs are used.
+.TP
+\fBdelete\fP \fIkey_spec\fP
+Remove the specified key from zone. If the key was not shared, it is also deleted from keystore.
+.TP
+\fBshare\fP \fIkey_ID\fP \fIzone_from\fP
+Import a key (specified by full key ID) from another zone as shared. After this, the key is
+owned by both zones equally.
+.UNINDENT
+.SS Commands related to Offline KSK feature
+.INDENT 0.0
+.TP
+\fBpregenerate\fP [\fItimestamp\-from\fP] \fItimestamp\-to\fP
+Pre\-generate ZSKs for use with offline KSK, for the specified period starting from now or specified time.
+This function also applies to non\-offline KSK keys.
+.TP
+\fBshow\-offline\fP [\fItimestamp\-from\fP] [\fItimestamp\-to\fP]
+Print pre\-generated offline key\-related records for specified time interval. If \fItimestamp_to\fP
+is omitted, it will be to infinity. If \fItimestamp\-from\fP is omitted, it will start from the
+beginning.
+.TP
+\fBdel\-offline\fP \fItimestamp\-from\fP \fItimestamp\-to\fP
+Delete pre\-generated offline key\-related records in specified time interval.
+.TP
+\fBdel\-all\-old\fP
+Delete old keys that are in state \(aqremoved\(aq. This function also applies to
+non\-offline KSK keys.
+.TP
+\fBgenerate\-ksr\fP [\fItimestamp\-from\fP] \fItimestamp\-to\fP
+Print to stdout KeySigningRequest based on pre\-generated ZSKs for specified time period.
+If \fItimestamp\-from\fP is omitted, timestamp of the last offline records set is used
+or now if no records available.
+.TP
+\fBsign\-ksr\fP \fIksr_file\fP
+Read KeySigningRequest from a text file, sign it using local keyset and print SignedKeyResponse to stdout.
+.TP
+\fBvalidate\-skr\fP \fIskr_file\fP
+Read SignedKeyResponse from a text file and validate the RRSIGs in it if not corrupt.
+.TP
+\fBimport\-skr\fP \fIskr_file\fP
+Read SignedKeyResponse from a text file and import the signatures for later use in zone. If some
+signatures have already been imported, they will be deleted for the period from beginning of the SKR
+to infinity.
+.UNINDENT
+.SS Generate arguments
+.sp
+Arguments are separated by space, each of them is in format \(aqname=value\(aq.
+.INDENT 0.0
+.TP
+\fBalgorithm\fP
+Either an algorithm number (e.g. 14) or \fI\%algorithm name\fP
+without dashes (e.g. ECDSAP384SHA384).
+.TP
+\fBsize\fP
+Key length in bits.
+.TP
+\fBksk\fP
+If set to \fByes\fP, the key will be used for signing DNSKEY rrset. The generated key will also
+have the Secure Entry Point flag set to 1.
+.TP
+\fBzsk\fP
+If set to \fByes\fP, the key will be used for signing zone (except DNSKEY rrset). This flag can
+be set concurrently with the \fBksk\fP flag.
+.TP
+\fBsep\fP
+Overrides the standard setting of the Secure Entry Point flag.
+.UNINDENT
+.sp
+The following arguments are timestamps of key lifetime (see \fI\%DNSSEC key states\fP):
+.INDENT 0.0
+.TP
+\fBpre_active\fP
+Key started to be used for signing, not published (only for algorithm rollover).
+.TP
+\fBpublish\fP
+Key published.
+.TP
+\fBready\fP
+Key is waiting for submission (only for KSK).
+.TP
+\fBactive\fP
+Key used for signing.
+.TP
+\fBretire_active\fP
+Key still used for signing, but another key is active (only for KSK or algorithm rollover).
+.TP
+\fBretire\fP
+Key still published, but no longer used for signing.
+.TP
+\fBpost_active\fP
+Key no longer published, but still used for signing (only for algorithm rollover).
+.TP
+\fBrevoke\fP
+Key revoked according to \fI\%RFC 5011\fP trust anchor roll\-over.
+.TP
+\fBremove\fP
+Key deleted.
+.UNINDENT
+.SS Timestamps
+.INDENT 0.0
+.TP
+0
+Zero timestamp means infinite future.
+.TP
+\fIUNIX_time\fP
+Positive number of seconds since 1970 UTC.
+.TP
+\fIYYYYMMDDHHMMSS\fP
+Date and time in this format without any punctuation.
+.TP
+\fIrelative_timestamp\fP
+A sign character (\fB+\fP, \fB\-\fP), a number, and an optional time unit
+(\fBy\fP, \fBmo\fP, \fBd\fP, \fBh\fP, \fBmi\fP, \fBs\fP). The default unit is one second.
+E.g. +1mi, \-2mo.
+.UNINDENT
+.SS Output timestamp formats
+.INDENT 0.0
+.TP
+(none)
+The timestamps are printed as UNIX timestamp.
+.TP
+\fBhuman\fP
+The timestamps are printed relatively to now using time units (e.g. \-2y5mo, +1h13s).
+.TP
+\fBiso\fP
+The timestamps are printed in the ISO8601 format (e.g. 2016\-12\-31T23:59:00).
+.UNINDENT
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.INDENT 0.0
+.IP 1. 3
+Generate new TSIG key:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ keymgr \-t my_name hmac\-sha384
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 2. 3
+Generate new DNSSEC key:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ keymgr example.com. generate algorithm=ECDSAP256SHA256 size=256 \e
+ ksk=true created=1488034625 publish=20170223205611 retire=+10mo remove=+1y
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 3. 3
+Import a DNSSEC key from BIND:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ keymgr example.com. import\-bind ~/bind/Kharbinge4d5.+007+63089.key
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 4. 3
+Configure key timing:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ keymgr example.com. set 4208 active=+2mi retire=+4mi remove=+5mi
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 5. 3
+Share a KSK from another zone:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ keymgr example.com. share e687cf927029e9db7184d2ece6d663f5d1e5b0e9 another\-zone.com.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fI\%RFC 6781\fP \- DNSSEC Operational Practices.
+\fI\%RFC 7583\fP \- DNSSEC Key Rollover Timing Considerations.
+.sp
+\fBknot.conf(5)\fP,
+\fBknotc(8)\fP,
+\fBknotd(8)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/khost.1in b/doc/man/khost.1in
new file mode 100644
index 0000000..292f080
--- /dev/null
+++ b/doc/man/khost.1in
@@ -0,0 +1,156 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KHOST" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+khost \- Simple DNS lookup utility
+.SH SYNOPSIS
+.sp
+\fBkhost\fP [\fIoptions\fP] \fIname\fP [\fIserver\fP]
+.SH DESCRIPTION
+.sp
+This utility sends a DNS query for the \fIname\fP to the \fIserver\fP and prints a reply
+in more user\-readable form. For more advanced DNS queries use \fI\%kdig\fP
+instead.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIname\fP
+Is a domain name that is to be looked up. If the \fIname\fP is IPv4 or IPv6
+address the PTR query type is used.
+.TP
+\fIserver\fP
+Is a name or an address of the nameserver to send a query to. The address
+can be specified using [address]:port notation. If no server is specified,
+the servers from \fB/etc/resolv.conf\fP are used.
+.UNINDENT
+.sp
+If no arguments are provided, \fBkhost\fP prints a short help.
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-4\fP
+Use the IPv4 protocol only.
+.TP
+\fB\-6\fP
+Use the IPv6 protocol only.
+.TP
+\fB\-a\fP
+Send ANY query with verbose mode.
+.TP
+\fB\-d\fP
+Enable debug messages.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-r\fP
+Disable recursion.
+.TP
+\fB\-T\fP
+Use the TCP protocol.
+.TP
+\fB\-v\fP
+Enable verbose output.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.TP
+\fB\-w\fP
+Wait forever for the reply.
+.TP
+\fB\-c\fP \fIclass\fP
+Set the query class (e.g. CH, CLASS4). The default class is IN.
+.TP
+\fB\-t\fP \fItype\fP
+Set the query type (e.g. NS, IXFR=12345, TYPE65535). The default is to send 3
+queries (A, AAAA and MX).
+.TP
+\fB\-R\fP \fIretries\fP
+The number (>=0) of UDP retries to query a nameserver. The default is 1.
+.TP
+\fB\-W\fP \fIwait\fP
+The time to wait for a reply in seconds. This timeout applies to each query
+try. The default is 2 seconds.
+.UNINDENT
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.INDENT 0.0
+.IP 1. 3
+Get the A, AAAA and MX records for example.com:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ khost example.com
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 2. 3
+Get the reverse record for address 192.0.2.1:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ khost 192.0.2.1
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.IP 3. 3
+Perform a verbose zone transfer for zone example.com:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ khost \-t AXFR \-v example.com
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH FILES
+.sp
+\fB/etc/resolv.conf\fP
+.SH SEE ALSO
+.sp
+\fBkdig(1)\fP, \fBknsupdate(1)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/kjournalprint.8in b/doc/man/kjournalprint.8in
new file mode 100644
index 0000000..2a1303a
--- /dev/null
+++ b/doc/man/kjournalprint.8in
@@ -0,0 +1,120 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KJOURNALPRINT" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+kjournalprint \- Knot DNS journal print utility
+.SH SYNOPSIS
+.sp
+\fBkjournalprint\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP
+.sp
+\fBkjournalprint\fP [\fIconfig_option\fP] \fB\-z\fP
+.SH DESCRIPTION
+.sp
+The program prints zone history stored in a journal database. As default,
+changes are colored for terminal.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIzone_name\fP
+A name of the zone to print the history for.
+.UNINDENT
+.SS Config options
+.INDENT 0.0
+.TP
+\fB\-c\fP, \fB\-\-config\fP \fIfile\fP
+Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP).
+.TP
+\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP
+Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP).
+The default configuration database, if exists, has a preference to the default
+configuration file.
+.TP
+\fB\-D\fP, \fB\-\-dir\fP \fIpath\fP
+Use specified journal database path and default configuration.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-z\fP, \fB\-\-zone\-list\fP
+Instead of reading the journal, display the list of zones in the DB.
+.TP
+\fB\-l\fP, \fB\-\-limit\fP \fIlimit\fP
+Limits the number of displayed changes.
+.TP
+\fB\-s\fP, \fB\-\-serial\fP \fIsoa\fP
+Start at a specific SOA serial.
+.TP
+\fB\-H\fP, \fB\-\-check\fP
+Enable additional journal semantic checks during printing.
+.TP
+\fB\-d\fP, \fB\-\-debug\fP
+Debug mode brief output.
+.TP
+\fB\-x\fP, \fB\-\-mono\fP
+Don\(aqt generate colorized output.
+.TP
+\fB\-n\fP, \fB\-\-no\-color\fP
+An alias for \fB\-x\fP\&. Use of this option is deprecated, it will be removed in the future.
+.TP
+\fB\-X\fP, \fB\-\-color\fP
+Force colorized output.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.sp
+Last (most recent) 5 changes without colors:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ kjournalprint \-nl 5 /var/lib/knot/journal example.com.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBknotd(8)\fP, \fBknot.conf(5)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/knot.conf.5in b/doc/man/knot.conf.5in
new file mode 100644
index 0000000..72f0a4a
--- /dev/null
+++ b/doc/man/knot.conf.5in
@@ -0,0 +1,2826 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KNOT.CONF" "5" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+knot.conf \- Knot DNS configuration file
+.SH DESCRIPTION
+.sp
+Configuration files for Knot DNS use simplified YAML format. Simplified means
+that not all of the features are supported.
+.sp
+For the description of configuration items, we have to declare a meaning of
+the following symbols:
+.INDENT 0.0
+.IP \(bu 2
+\fBINT\fP – Integer
+.IP \(bu 2
+\fBSTR\fP – Textual string
+.IP \(bu 2
+\fBHEXSTR\fP – Hexadecimal string (with \fB0x\fP prefix)
+.IP \(bu 2
+\fBBOOL\fP – Boolean value (\fBon\fP/\fBoff\fP or \fBtrue\fP/\fBfalse\fP)
+.IP \(bu 2
+\fBTIME\fP – Number of seconds, an integer with possible time multiplier suffix
+(\fBs\fP ~ 1, \fBm\fP ~ 60, \fBh\fP ~ 3600 or \fBd\fP ~ 24 * 3600)
+.IP \(bu 2
+\fBSIZE\fP – Number of bytes, an integer with possible size multiplier suffix
+(\fBB\fP ~ 1, \fBK\fP ~ 1024, \fBM\fP ~ 1024^2 or \fBG\fP ~ 1024^3)
+.IP \(bu 2
+\fBBASE64\fP – Base64 encoded string
+.IP \(bu 2
+\fBADDR\fP – IPv4 or IPv6 address
+.IP \(bu 2
+\fBDNAME\fP – Domain name
+.IP \(bu 2
+\fB\&...\fP – Multi\-valued item, order of the values is preserved
+.IP \(bu 2
+\fB[\fP \fB]\fP – Optional value
+.IP \(bu 2
+\fB|\fP – Choice
+.UNINDENT
+.sp
+The configuration consists of several fixed sections and optional module
+sections. There are 16 fixed sections (\fBmodule\fP, \fBserver\fP, \fBxdp\fP, \fBcontrol\fP,
+\fBlog\fP, \fBstatistics\fP, \fBdatabase\fP, \fBkeystore\fP, \fBkey\fP, \fBremote\fP,
+\fBremotes\fP, \fBacl\fP, \fBsubmission\fP, \fBpolicy\fP, \fBtemplate\fP, \fBzone\fP).
+Module sections are prefixed with the \fBmod\-\fP prefix (e.g. \fBmod\-stats\fP).
+.sp
+Most of the sections (e.g. \fBzone\fP) are sequences of settings blocks. Each
+settings block begins with a unique identifier, which can be used as a reference
+from other sections (such an identifier must be defined in advance).
+.sp
+A multi\-valued item can be specified either as a YAML sequence:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+address: [10.0.0.1, 10.0.0.2]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+or as more single\-valued items each on an extra line:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+address: 10.0.0.1
+address: 10.0.0.2
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+If an item value contains spaces or other special characters, it is necessary
+to enclose such a value within double quotes \fB\(dq\fP \fB\(dq\fP\&.
+.sp
+If not specified otherwise, an item representing a file or a directory path may
+be defined either as an absolute path (starting with \fB/\fP), or a path relative
+to the same directory as the default value of the item.
+.SH COMMENTS
+.sp
+A comment begins with a \fB#\fP character and is ignored during processing.
+Also each configuration section or sequence block allows a permanent
+comment using the \fBcomment\fP item which is stored in the server beside the
+configuration.
+.SH INCLUDING CONFIGURATION
+.sp
+Another configuration file or files, matching a pattern, can be included at
+the top level in the current file.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+include: STR
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS include
+.sp
+A path or a matching pattern specifying one or more files that are included
+at the place of the include option position in the configuration.
+If the path is not absolute, then it is considered to be relative to the
+current file. The pattern can be an arbitrary string meeting POSIX \fIglob\fP
+requirements, e.g. dir/*.conf. Matching files are processed in sorted order.
+.sp
+\fIDefault:\fP not set
+.SH CLEARING CONFIGURATION SECTIONS
+.sp
+It\(aqs possible to clear specified configuration sections at given phases
+of the configuration parsing.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+clear: STR
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS clear
+.sp
+A matching pattern specifying configuration sections that are cleared when
+this item is parsed. This allows overriding of existing configuration
+in the configuration database when including a configuration file or
+ensures that some configuration wasn\(aqt specified in previous includes.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+For the pattern matching the POSIX function
+\fI\%fnmatch()\fP
+is used. On Linux, the GNU extension
+\fI\%FNM_EXTMATCH\fP
+is enabled, which allows extended pattern matching.
+Examples:
+.INDENT 0.0
+.IP \(bu 2
+\fBclear: zone\fP – Clears the \fBzone\fP section.
+.IP \(bu 2
+\fBclear: mod\-*\fP – Clears all module sections.
+.IP \(bu 2
+\fBclear: \(dq[!z]*\(dq\fP – Clears all sections not beginning with letter \fBz\fP\&.
+.IP \(bu 2
+\fBclear: !(zone)\fP – (GNU only) Clears all sections except the \fBzone\fP one.
+.IP \(bu 2
+\fBclear: @(zone|template)\fP – (GNU only) Clears the \fBzone\fP and \fBtemplate\fP sections.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SH MODULE SECTION
+.sp
+Dynamic modules loading configuration.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+If configured with non\-empty \fB\-\-with\-moduledir=path\fP parameter, all
+shared modules in this directory will be automatically loaded.
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+module:
+ \- id: STR
+ file: STR
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A module identifier in the form of the \fBmod\-\fP prefix and module name suffix.
+.SS file
+.sp
+A path to a shared library file with the module implementation.
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+If the path is not absolute, the library is searched in the set of
+system directories. See \fBman dlopen\fP for more details.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB${libdir}/knot/modules\-${version}\fP/module_name.so
+(or \fB${path}\fP/module_name.so if configured with \fB\-\-with\-moduledir=path\fP)
+.SH SERVER SECTION
+.sp
+General options related to the server.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+server:
+ identity: [STR]
+ version: [STR]
+ nsid: [STR|HEXSTR]
+ rundir: STR
+ user: STR[:STR]
+ pidfile: STR
+ udp\-workers: INT
+ tcp\-workers: INT
+ background\-workers: INT
+ async\-start: BOOL
+ tcp\-idle\-timeout: TIME
+ tcp\-io\-timeout: INT
+ tcp\-remote\-io\-timeout: INT
+ tcp\-max\-clients: INT
+ tcp\-reuseport: BOOL
+ tcp\-fastopen: BOOL
+ quic\-max\-clients: INT
+ quic\-outbuf\-max\-size: SIZE
+ quic\-idle\-close\-timeout: TIME
+ remote\-pool\-limit: INT
+ remote\-pool\-timeout: TIME
+ remote\-retry\-delay: TIME
+ socket\-affinity: BOOL
+ udp\-max\-payload: SIZE
+ udp\-max\-payload\-ipv4: SIZE
+ udp\-max\-payload\-ipv6: SIZE
+ key\-file: STR
+ cert\-file: STR
+ edns\-client\-subnet: BOOL
+ answer\-rotation: BOOL
+ automatic\-acl: BOOL
+ proxy\-allowlist: ADDR[/INT] | ADDR\-ADDR ...
+ dbus\-event: none | running | zone\-updated | ksk\-submission | dnssec\-invalid ...
+ dbus\-init\-delay: TIME
+ listen: ADDR[@INT] | STR ...
+ listen\-quic: ADDR[@INT] ...
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBCAUTION:\fP
+.INDENT 0.0
+.INDENT 3.5
+When you change configuration parameters dynamically or via configuration file
+reload, some parameters in the Server section require restarting the Knot server
+so that the changes take effect. See below for the details.
+.UNINDENT
+.UNINDENT
+.SS identity
+.sp
+An identity of the server returned in the response to the query for TXT
+record \fBid.server.\fP or \fBhostname.bind.\fP in the CHAOS class (\fI\%RFC 4892\fP).
+Set to an empty value to disable.
+.sp
+\fIDefault:\fP FQDN hostname
+.SS version
+.sp
+A version of the server software returned in the response to the query
+for TXT record \fBversion.server.\fP or \fBversion.bind.\fP in the CHAOS
+class (\fI\%RFC 4892\fP). Set to an empty value to disable.
+.sp
+\fIDefault:\fP server version
+.SS nsid
+.sp
+A DNS name server identifier (\fI\%RFC 5001\fP). Set to an empty value to disable.
+.sp
+\fIDefault:\fP FQDN hostname at the moment of the daemon start
+.SS rundir
+.sp
+A path for storing run\-time data (PID file, unix sockets, etc.). A non\-absolute
+path is relative to the \fI\%knotd\fP startup directory.
+.sp
+Depending on the usage of this parameter, its change may require restart of the Knot
+server to take effect.
+.sp
+\fIDefault:\fP \fB${localstatedir}/run/knot\fP (configured with \fB\-\-with\-rundir=path\fP)
+.SS user
+.sp
+A system user with an optional system group (\fBuser:group\fP) under which the
+server is run after starting and binding to interfaces. Linux capabilities
+are employed if supported.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fBroot:root\fP
+.SS pidfile
+.sp
+A PID file \fI\%location\fP\&.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fI\%rundir\fP\fB/knot.pid\fP
+.SS udp\-workers
+.sp
+A number of UDP workers (threads) used to process incoming queries
+over UDP.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP equal to the number of online CPUs
+.SS tcp\-workers
+.sp
+A number of TCP workers (threads) used to process incoming queries
+over TCP.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP equal to the number of online CPUs, default value is at least 10
+.SS background\-workers
+.sp
+A number of workers (threads) used to execute background operations (zone
+loading, zone updates, etc.).
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP equal to the number of online CPUs, default value is at most 10
+.SS async\-start
+.sp
+If enabled, server doesn\(aqt wait for the zones to be loaded and starts
+responding immediately with SERVFAIL answers until the zone loads.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS tcp\-idle\-timeout
+.sp
+Maximum idle time (in seconds) between requests on an inbound TCP connection.
+It means if there is no activity on an inbound TCP connection during this limit,
+the connection is closed by the server.
+.sp
+\fIMinimum:\fP \fB1\fP
+.sp
+\fIDefault:\fP \fB10\fP
+.SS tcp\-io\-timeout
+.sp
+Maximum time (in milliseconds) to receive or send one DNS message over an inbound
+TCP connection. It means this limit applies to normal DNS queries and replies,
+incoming DDNS, and \fBoutgoing zone transfers\fP\&. The timeout is measured since some
+data is already available for processing.
+Set to 0 for infinity.
+.sp
+\fIDefault:\fP \fB500\fP (milliseconds)
+.sp
+\fBCAUTION:\fP
+.INDENT 0.0
+.INDENT 3.5
+In order to reduce the risk of Slow Loris attacks, it\(aqs recommended setting
+this limit as low as possible on public servers.
+.UNINDENT
+.UNINDENT
+.SS tcp\-remote\-io\-timeout
+.sp
+Maximum time (in milliseconds) to receive or send one DNS message over an outbound
+TCP connection which has already been established to a configured remote server.
+It means this limit applies to incoming zone transfers, sending NOTIFY,
+DDNS forwarding, and DS check or push. This timeout includes the time needed
+for a network round\-trip and for a query processing by the remote.
+Set to 0 for infinity.
+.sp
+\fIDefault:\fP \fB5000\fP (milliseconds)
+.SS tcp\-reuseport
+.sp
+If enabled, each TCP worker listens on its own socket and the OS kernel
+socket load balancing is employed using SO_REUSEPORT (or SO_REUSEPORT_LB
+on FreeBSD). Due to the lack of one shared socket, the server can offer
+higher response rate processing over TCP. However, in the case of
+time\-consuming requests (e.g. zone transfers of a TLD zone), enabled reuseport
+may result in delayed or not being responded client requests. So it is
+advisable to use this option on secondary servers.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS tcp\-fastopen
+.sp
+If enabled, use TCP Fast Open for outbound TCP communication (client side):
+incoming zone transfers, sending NOTIFY, and DDNS forwarding. This mode simplifies
+TCP handshake and can result in better networking performance. TCP Fast Open
+for inbound TCP communication (server side) isn\(aqt affected by this
+configuration as it\(aqs enabled automatically if supported by OS.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The TCP Fast Open support must also be enabled on the OS level:
+.INDENT 0.0
+.IP \(bu 2
+Linux/macOS: ensure kernel parameter \fBnet.ipv4.tcp_fastopen\fP is \fB2\fP or
+\fB3\fP for server side, and \fB1\fP or \fB3\fP for client side.
+.IP \(bu 2
+FreeBSD: ensure kernel parameter \fBnet.inet.tcp.fastopen.server_enable\fP
+is \fB1\fP for server side, and \fBnet.inet.tcp.fastopen.client_enable\fP is
+\fB1\fP for client side.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS quic\-max\-clients
+.sp
+A maximum number of QUIC clients connected in parallel.
+.sp
+See also \fI\%quic\fP\&.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIMinimum:\fP \fB128\fP
+.sp
+\fIDefault:\fP \fB10000\fP (ten thousand)
+.SS quic\-outbuf\-max\-size
+.sp
+Maximum cumulative size of memory used for buffers of unACKed
+sent messages. This limit is per one UDP worker.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Set low if little memory is available (together with \fI\%quic\-max\-clients\fP
+since QUIC connections are memory\-heavy). Set to high value if outgoing zone
+transfers of big zone over QUIC are expected.
+.UNINDENT
+.UNINDENT
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIMinimum:\fP \fB1M\fP (1 MiB)
+.sp
+\fIDefault:\fP \fB100M\fP (100 MiB)
+.SS quic\-idle\-close\-timeout
+.sp
+Time in seconds, after which any idle QUIC connection is gracefully closed.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIMinimum:\fP \fB1\fP
+.sp
+\fIDefault:\fP \fB4\fP
+.SS remote\-pool\-limit
+.sp
+If nonzero, the server will keep up to this number of outgoing TCP connections
+open for later use. This is an optimization to avoid frequent opening of
+TCP connections to the same remote.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fB0\fP
+.SS remote\-pool\-timeout
+.sp
+The timeout in seconds after which the unused kept\-open outgoing TCP connections
+to remote servers are closed.
+.sp
+\fIDefault:\fP \fB5\fP
+.SS remote\-retry\-delay
+.sp
+When a connection attempt times out to some remote address, this information will be
+kept for this specified time (in milliseconds) and other connections to the same address won\(aqt
+be attempted. This prevents repetitive waiting for timeout on an unreachable remote.
+.sp
+\fIDefault:\fP \fB0\fP
+.SS socket\-affinity
+.sp
+If enabled and if SO_REUSEPORT is available on Linux, all configured network
+sockets are bound to UDP and TCP workers in order to increase the networking performance.
+This mode isn\(aqt recommended for setups where the number of network card queues
+is lower than the number of UDP or TCP workers.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS tcp\-max\-clients
+.sp
+A maximum number of TCP clients connected in parallel, set this below the file
+descriptor limit to avoid resource exhaustion.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+It is advisable to adjust the maximum number of open files per process in your
+operating system configuration.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP one half of the file descriptor limit for the server process
+.SS udp\-max\-payload
+.sp
+Maximum EDNS0 UDP payload size default for both IPv4 and IPv6.
+.sp
+\fIDefault:\fP \fB1232\fP
+.SS udp\-max\-payload\-ipv4
+.sp
+Maximum EDNS0 UDP payload size for IPv4.
+.sp
+\fIDefault:\fP \fB1232\fP
+.SS udp\-max\-payload\-ipv6
+.sp
+Maximum EDNS0 UDP payload size for IPv6.
+.sp
+\fIDefault:\fP \fB1232\fP
+.SS key\-file
+.sp
+Path to a server key PEM file which is used for DNS over QUIC communication.
+A non\-absolute path of a user specified key file is relative to the
+\fB@config_dir@\fP directory.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP auto\-generated key
+.SS cert\-file
+.sp
+Path to a server certificate PEM file which is used for DNS over QUIC communication.
+A non\-absolute path is relative to the \fB@config_dir@\fP directory.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP one\-time in\-memory certificate
+.SS edns\-client\-subnet
+.sp
+Enable or disable EDNS Client Subnet support. If enabled, responses to queries
+containing the EDNS Client Subnet option
+always contain a valid EDNS Client Subnet option according to \fI\%RFC 7871\fP\&.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS answer\-rotation
+.sp
+Enable or disable sorted\-rrset rotation in the answer section of normal replies.
+The rotation shift is simply determined by a query ID.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS automatic\-acl
+.sp
+If enabled, \fI\%automatic ACL\fP setting of
+configured remotes is considered when evaluating authorized operations.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS proxy\-allowlist
+.sp
+An ordered list of IP addresses, network subnets, or network ranges
+which are allowed as a source address of proxied DNS traffic over UDP.
+The supported proxy protocol is
+\fI\%haproxy PROXY v2\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+TCP is not supported.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS dbus\-event
+.sp
+Specification of server or zone states which emit a D\-Bus signal on the system
+bus. The bus name is \fBcz.nic.knotd\fP, the object path is \fB/cz/nic/knotd\fP, and
+the interface name is \fBcz.nic.knotd.events\fP\&.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBnone\fP – No signal is emitted.
+.IP \(bu 2
+\fBrunning\fP – There are two possible signals emitted:
+.INDENT 2.0
+.IP \(bu 2
+\fBstarted\fP when the server is started and all configured zones (including
+catalog zones and their members) are loaded or successfully bootstrapped.
+.IP \(bu 2
+\fBstopped\fP when the server shutdown sequence is initiated.
+.UNINDENT
+.IP \(bu 2
+\fBzone\-updated\fP – The signal \fBzone_updated\fP is emitted when a zone has been updated;
+the signal parameters are \fIzone name\fP and \fIzone SOA serial\fP\&.
+.IP \(bu 2
+\fBkeys\-updated\fP \- The signal \fBkeys_updated\fP is emitted when a DNSSEC key set
+of this zone is updated.
+.IP \(bu 2
+\fBksk\-submission\fP – The signal \fBzone_ksk_submission\fP is emitted if there is
+a ready KSK present when the zone is signed; the signal parameters are
+\fIzone name\fP, \fIKSK keytag\fP, and \fIKSK KASP id\fP\&.
+.IP \(bu 2
+\fBdnssec\-invalid\fP – The signal \fBzone_dnssec_invalid\fP is emitted when DNSSEC
+validation fails; the signal parameter is \fIzone name\fP\&.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This function requires systemd version at least 221.
+.UNINDENT
+.UNINDENT
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fBnone\fP
+.SS dbus\-init\-delay
+.sp
+Time in seconds which the server waits upon D\-Bus initialization to ensure
+the D\-Bus client is ready to receive signals.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIMinimum:\fP \fB0\fP
+.sp
+\fIDefault:\fP \fB1\fP
+.SS listen
+.sp
+One or more IP addresses where the server listens for incoming queries.
+Optional port specification (default is 53) can be appended to each address
+using \fB@\fP separator. Use \fB0.0.0.0\fP for all configured IPv4 addresses or
+\fB::\fP for all configured IPv6 addresses. Filesystem path can be specified
+for listening on local unix SOCK_STREAM socket. Non\-absolute path
+(i.e. not starting with \fB/\fP) is relative to \fI\%rundir\fP\&.
+Non\-local address binding is automatically enabled if supported by the operating system.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP not set
+.SS listen\-quic
+.sp
+One or more IP addresses (and optionally ports) where the server listens
+for incoming queries over QUIC protocol.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP not set
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Incoming \fI\%DDNS\fP over QUIC isn\(aqt supported.
+The server always responds with SERVFAIL.
+.UNINDENT
+.UNINDENT
+.SH XDP SECTION
+.sp
+Various options related to XDP listening, especially TCP.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+xdp:
+ listen: STR[@INT] | ADDR[@INT] ...
+ udp: BOOL
+ tcp: BOOL
+ quic: BOOL
+ quic\-port: INT
+ tcp\-max\-clients: INT
+ tcp\-inbuf\-max\-size: SIZE
+ tcp\-outbuf\-max\-size: SIZE
+ tcp\-idle\-close\-timeout: TIME
+ tcp\-idle\-reset\-timeout: TIME
+ tcp\-resend\-timeout: TIME
+ route\-check: BOOL
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBCAUTION:\fP
+.INDENT 0.0
+.INDENT 3.5
+When you change configuration parameters dynamically or via configuration file
+reload, some parameters in the XDP section require restarting the Knot server
+so that the changes take effect.
+.UNINDENT
+.UNINDENT
+.SS listen
+.sp
+One or more network device names (e.g. \fBens786f0\fP) on which the \fI\%Mode XDP\fP
+is enabled. Alternatively, an IP address can be used instead of a device name,
+but the server will still listen on all addresses belonging to the same interface!
+Optional port specification (default is 53) can be appended to each device name
+or address using \fB@\fP separator.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fBCAUTION:\fP
+.INDENT 0.0
+.INDENT 3.5
+If XDP workers only process regular DNS traffic over UDP, it is strongly
+recommended to also \fI\%listen\fP on the addresses which are
+intended to offer the DNS service, at least to fulfil the DNS requirement for
+working TCP.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Incoming \fI\%DDNS\fP over XDP isn\(aqt supported.
+The server always responds with SERVFAIL.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS udp
+.sp
+If enabled, DNS over UDP is processed with XDP workers.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fBon\fP
+.SS tcp
+.sp
+If enabled, DNS over TCP traffic is processed with XDP workers.
+.sp
+The TCP stack limitations:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP \(bu 2
+Congestion control is not implemented.
+.IP \(bu 2
+Lost packets that do not contain TCP payload may not be resend.
+.IP \(bu 2
+Not optimized for transfers of non\-trivial zones.
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS quic
+.sp
+If enabled, DNS over QUIC is processed with XDP workers.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS quic\-port
+.sp
+DNS over QUIC will listen on the interfaces configured by \fI\%listen\fP,
+but on different port, configured by this option.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fIDefault:\fP \fB853\fP
+.SS tcp\-max\-clients
+.sp
+A maximum number of TCP clients connected in parallel.
+.sp
+\fIMinimum:\fP \fB1024\fP
+.sp
+\fIDefault:\fP \fB1000000\fP (one million)
+.SS tcp\-inbuf\-max\-size
+.sp
+Maximum cumulative size of memory used for buffers of incompletely
+received messages.
+.sp
+\fIMinimum:\fP \fB1M\fP (1 MiB)
+.sp
+\fIDefault:\fP \fB100M\fP (100 MiB)
+.SS tcp\-outbuf\-max\-size
+.sp
+Maximum cumulative size of memory used for buffers of unACKed
+sent messages.
+.sp
+\fIMinimum:\fP \fB1M\fP (1 MiB)
+.sp
+\fIDefault:\fP \fB100M\fP (100 MiB)
+.SS tcp\-idle\-close\-timeout
+.sp
+Time in seconds, after which any idle connection is gracefully closed.
+.sp
+\fIMinimum:\fP \fB1\fP
+.sp
+\fIDefault:\fP \fB10\fP
+.SS tcp\-idle\-reset\-timeout
+.sp
+Time in seconds, after which any idle connection is forcibly closed.
+.sp
+\fIMinimum:\fP \fB1\fP
+.sp
+\fIDefault:\fP \fB20\fP
+.SS tcp\-resend\-timeout
+.sp
+Resend outgoing data packets (with DNS response payload) if not ACKed
+before this timeout.
+.sp
+\fIMinimum:\fP \fB1\fP
+.sp
+\fIDefault:\fP \fB5\fP
+.SS route\-check
+.sp
+If enabled, routing information from the operating system is considered
+when processing every incoming DNS packet received over the XDP interface:
+.INDENT 0.0
+.IP \(bu 2
+If the outgoing interface of the corresponding DNS response differs from
+the incoming one, the packet is processed normally by UDP/TCP workers
+(XDP isn\(aqt used).
+.IP \(bu 2
+If the destination address is blackholed, unreachable, or prohibited,
+the DNS packet is dropped without any response.
+.IP \(bu 2
+The destination MAC address and possible VLAN tag for the response are taken
+from the routing system.
+.UNINDENT
+.sp
+If disabled, symmetrical routing is applied. It means that the query source
+MAC address is used as a response destination MAC address. Possible VLAN tag
+is preserved.
+.sp
+Change of this parameter requires restart of the Knot server to take effect.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This mode requires forwarding enabled on the loopback interface
+(\fBsysctl \-w net.ipv4.conf.lo.forwarding=1\fP and \fBsysctl \-w net.ipv6.conf.lo.forwarding=1\fP).
+If forwarding is disabled, all incoming DNS packets are dropped!
+.sp
+Only VLAN 802.1Q is supported.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SH CONTROL SECTION
+.sp
+Configuration of the server control interface.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+control:
+ listen: STR
+ timeout: TIME
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS listen
+.sp
+A UNIX socket \fI\%path\fP where the server listens for
+control commands.
+.sp
+\fIDefault:\fP \fI\%rundir\fP\fB/knot.sock\fP
+.SS timeout
+.sp
+Maximum time (in seconds) the control socket operations can take.
+Set to 0 for infinity.
+.sp
+\fIDefault:\fP \fB5\fP
+.SH LOG SECTION
+.sp
+Server can be configured to log to the standard output, standard error
+output, syslog (or systemd journal if systemd is enabled) or into an arbitrary
+file.
+.sp
+There are 6 logging severity levels:
+.INDENT 0.0
+.IP \(bu 2
+\fBcritical\fP – Non\-recoverable error resulting in server shutdown.
+.IP \(bu 2
+\fBerror\fP – Recoverable error, action should be taken.
+.IP \(bu 2
+\fBwarning\fP – Warning that might require user action.
+.IP \(bu 2
+\fBnotice\fP – Server notice or hint.
+.IP \(bu 2
+\fBinfo\fP – Informational message.
+.IP \(bu 2
+\fBdebug\fP – Debug or detailed message.
+.UNINDENT
+.sp
+In the case of a missing log section, \fBwarning\fP or more serious messages
+will be logged to both standard error output and syslog. The \fBinfo\fP and
+\fBnotice\fP messages will be logged to standard output.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+log:
+ \- target: stdout | stderr | syslog | STR
+ server: critical | error | warning | notice | info | debug
+ control: critical | error | warning | notice | info | debug
+ zone: critical | error | warning | notice | info | debug
+ quic: critical | error | warning | notice | info | debug
+ any: critical | error | warning | notice | info | debug
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS target
+.sp
+A logging output.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBstdout\fP – Standard output.
+.IP \(bu 2
+\fBstderr\fP – Standard error output.
+.IP \(bu 2
+\fBsyslog\fP – Syslog or systemd journal.
+.IP \(bu 2
+\fIfile_name\fP – A specific file.
+.UNINDENT
+.sp
+With \fBsyslog\fP target, syslog service is used. However, if Knot DNS has been compiled
+with systemd support and operating system has been booted with systemd, systemd journal
+is used for logging instead of syslog.
+.sp
+A \fIfile_name\fP may be specified as an absolute path or a path relative to the
+\fI\%knotd\fP startup directory.
+.SS server
+.sp
+Minimum severity level for messages related to general operation of the server to be
+logged.
+.sp
+\fIDefault:\fP not set
+.SS control
+.sp
+Minimum severity level for messages related to server control to be logged.
+.sp
+\fIDefault:\fP not set
+.SS zone
+.sp
+Minimum severity level for messages related to zones to be logged.
+.sp
+\fIDefault:\fP not set
+.SS quic
+.sp
+Minimum severity level for messages related to QUIC to be logged.
+.sp
+\fIDefault:\fP not set
+.SS any
+.sp
+Minimum severity level for all message types, except \fBquic\fP, to be logged.
+.sp
+\fIDefault:\fP not set
+.SH STATS SECTION
+.sp
+Periodic server statistics dumping.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+statistics:
+ timer: TIME
+ file: STR
+ append: BOOL
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS timer
+.sp
+A period (in seconds) after which all available statistics metrics will by written to the
+\fI\%file\fP\&.
+.sp
+\fIDefault:\fP not set
+.SS file
+.sp
+A file \fI\%path\fP of statistics output in the YAML format.
+.sp
+\fIDefault:\fP \fI\%rundir\fP\fB/stats.yaml\fP
+.SS append
+.sp
+If enabled, the output will be appended to the \fI\%file\fP
+instead of file replacement.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SH DATABASE SECTION
+.sp
+Configuration of databases for zone contents, DNSSEC metadata, or event timers.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+database:
+ storage: STR
+ journal\-db: STR
+ journal\-db\-mode: robust | asynchronous
+ journal\-db\-max\-size: SIZE
+ kasp\-db: STR
+ kasp\-db\-max\-size: SIZE
+ timer\-db: STR
+ timer\-db\-max\-size: SIZE
+ catalog\-db: str
+ catalog\-db\-max\-size: SIZE
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS storage
+.sp
+A data directory for storing journal, KASP, and timer databases. A non\-absolute
+path is relative to the \fI\%knotd\fP startup directory.
+.sp
+\fIDefault:\fP \fB${localstatedir}/lib/knot\fP (configured with \fB\-\-with\-storage=path\fP)
+.SS journal\-db
+.sp
+An explicit \fI\%specification\fP of the persistent journal database
+directory.
+.sp
+\fIDefault:\fP \fI\%storage\fP\fB/journal\fP
+.SS journal\-db\-mode
+.sp
+Specifies journal LMDB backend configuration, which influences performance
+and durability.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBrobust\fP – The journal database disk synchronization ensures database
+durability but is generally slower.
+.IP \(bu 2
+\fBasynchronous\fP – The journal database disk synchronization is optimized for
+better performance at the expense of lower database durability in the case of
+a crash. This mode is recommended on secondary servers with many zones.
+.UNINDENT
+.sp
+\fIDefault:\fP \fBrobust\fP
+.SS journal\-db\-max\-size
+.sp
+The hard limit for the journal database maximum size. There is no cleanup logic
+in journal to recover from reaching this limit. Journal simply starts refusing
+changes across all zones. Decreasing this value has no effect if it is lower
+than the actual database file size.
+.sp
+It is recommended to limit \fI\%journal\-max\-usage\fP
+per\-zone instead of \fI\%journal\-db\-max\-size\fP
+in most cases. Please keep this value larger than the sum of all zones\(aq
+journal usage limits. See more details regarding
+\fI\%journal behaviour\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This value also influences server\(aqs usage of virtual memory.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB20G\fP (20 GiB), or \fB512M\fP (512 MiB) for 32\-bit
+.SS kasp\-db
+.sp
+An explicit \fI\%specification\fP of the KASP database directory.
+.sp
+\fIDefault:\fP \fI\%storage\fP\fB/keys\fP
+.SS kasp\-db\-max\-size
+.sp
+The hard limit for the KASP database maximum size.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This value also influences server\(aqs usage of virtual memory.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB500M\fP (500 MiB)
+.SS timer\-db
+.sp
+An explicit \fI\%specification\fP of the persistent timer
+database directory.
+.sp
+\fIDefault:\fP \fI\%storage\fP\fB/timers\fP
+.SS timer\-db\-max\-size
+.sp
+The hard limit for the timer database maximum size.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This value also influences server\(aqs usage of virtual memory.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB100M\fP (100 MiB)
+.SS catalog\-db
+.sp
+An explicit \fI\%specification\fP of the zone catalog
+database directory. Only useful if \fI\%Catalog zones\fP are enabled.
+.sp
+\fIDefault:\fP \fI\%storage\fP\fB/catalog\fP
+.SS catalog\-db\-max\-size
+.sp
+The hard limit for the catalog database maximum size.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This value also influences server\(aqs usage of virtual memory.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB20G\fP (20 GiB), or \fB512M\fP (512 MiB) for 32\-bit
+.SH KEYSTORE SECTION
+.sp
+DNSSEC keystore configuration.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+keystore:
+ \- id: STR
+ backend: pem | pkcs11
+ config: STR
+ key\-label: BOOL
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A keystore identifier.
+.SS backend
+.sp
+A key storage backend type.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBpem\fP – PEM files.
+.IP \(bu 2
+\fBpkcs11\fP – PKCS #11 storage.
+.UNINDENT
+.sp
+\fIDefault:\fP \fBpem\fP
+.SS config
+.sp
+A backend specific configuration. A directory with PEM files (the path can
+be specified as a relative path to \fI\%kasp\-db\fP) or
+a configuration string for PKCS #11 storage (\fI<pkcs11\-uri> <module\-path>\fP).
+The PKCS #11 URI Scheme is defined in \fI\%RFC 7512\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Example configuration string for PKCS #11:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+\(dqpkcs11:token=knot;pin\-value=1234 /usr/lib64/pkcs11/libsofthsm2.so\(dq
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fI\%kasp\-db\fP\fB/keys\fP
+.SS key\-label
+.sp
+If enabled in combination with the PKCS #11 \fI\%backend\fP, generated keys
+are labeled in the form \fB<zone_name> KSK|ZSK\fP\&.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SH KEY SECTION
+.sp
+Shared TSIG keys used to authenticate communication with the server.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+key:
+ \- id: DNAME
+ algorithm: hmac\-md5 | hmac\-sha1 | hmac\-sha224 | hmac\-sha256 | hmac\-sha384 | hmac\-sha512
+ secret: BASE64
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A key name identifier.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This value MUST be exactly the same as the name of the TSIG key on the
+opposite primary/secondary server(s).
+.UNINDENT
+.UNINDENT
+.SS algorithm
+.sp
+A TSIG key algorithm. See
+\fI\%TSIG Algorithm Numbers\fP\&.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBhmac\-md5\fP
+.IP \(bu 2
+\fBhmac\-sha1\fP
+.IP \(bu 2
+\fBhmac\-sha224\fP
+.IP \(bu 2
+\fBhmac\-sha256\fP
+.IP \(bu 2
+\fBhmac\-sha384\fP
+.IP \(bu 2
+\fBhmac\-sha512\fP
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS secret
+.sp
+Shared key secret.
+.sp
+\fIDefault:\fP not set
+.SH REMOTE SECTION
+.sp
+Definitions of remote servers for outgoing connections (source of a zone
+transfer, target for a notification, etc.).
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+remote:
+ \- id: STR
+ address: ADDR[@INT] | STR ...
+ via: ADDR[@INT] ...
+ quic: BOOL
+ key: key_id
+ cert\-key: BASE64 ...
+ block\-notify\-after\-transfer: BOOL
+ no\-edns: BOOL
+ automatic\-acl: BOOL
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A remote identifier.
+.SS address
+.sp
+An ordered list of destination IP addresses or UNIX socket paths which are
+used for communication with the remote server. Non\-absolute path
+(i.e. not starting with \fB/\fP) is relative to \fI\%rundir\fP\&.
+Optional destination port (default is 53 for UDP/TCP and 853 for QUIC)
+can be appended to the address using \fB@\fP separator.
+The addresses are tried in sequence until the
+remote is reached.
+.sp
+\fIDefault:\fP not set
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+If the remote is contacted and it refuses to perform requested action,
+no more addresses will be tried for this remote.
+.UNINDENT
+.UNINDENT
+.SS via
+.sp
+An ordered list of source IP addresses which are used as source addresses
+for communication with the remote. For the N\-th \fI\%remote address\fP,
+the last, but at most N\-th, specified \fI\%via address\fP
+of the same family is used.
+This option can help if the server listens on more addresses.
+Optional source port (default is random) can be appended
+to the address using \fB@\fP separator.
+.sp
+\fIDefault:\fP not set
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+For the following configuration:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+remote:
+ \- id: example
+ address: [198.51.100.10, 2001:db8::10, 198.51.100.20, 2001:db8::20]
+ via: [198.51.100.1, 198.51.100.2, 2001:db8::1]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+the (\fBvia\fP \-> \fBaddress\fP) mapping is:
+.INDENT 0.0
+.IP \(bu 2
+\fB198.51.100.1\fP \-> \fB198.51.100.10\fP
+.IP \(bu 2
+\fB2001:db8::1\fP \-> \fB2001:db8::10\fP
+.IP \(bu 2
+\fB198.51.100.2\fP \-> \fB198.51.100.20\fP
+.IP \(bu 2
+\fB2001:db8::1\fP \-> \fB2001:db8::20\fP
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS quic
+.sp
+If this option is set, the QUIC protocol will be used for outgoing communication
+with this remote.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+One connection per each remote is opened; \fI\%remote\-pool\-limit\fP
+does not take effect for QUIC. However, fast QUIC handshakes utilizing obtained
+session tickets are used for reopening connections to recently (up to 1 day)
+queried remotes.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS key
+.sp
+A \fI\%reference\fP to the TSIG key which is used to authenticate
+the communication with the remote server.
+.sp
+\fIDefault:\fP not set
+.SS cert\-key
+.sp
+An ordered list of remote certificate public key PINs. If the list is non\-empty,
+communication with the remote is possible only via QUIC protocol and
+a peer certificate is required. The peer certificate key must match one of the
+specified PINs.
+.sp
+A PIN is a unique identifier that represents the public key of the peer certificate.
+It\(aqs a base64\-encoded SHA\-256 hash of the public key. This identifier
+remains the same on a certificate renewal.
+.sp
+\fIDefault:\fP not set
+.SS block\-notify\-after\-transfer
+.sp
+When incoming AXFR/IXFR from this remote (as a primary server), suppress
+sending NOTIFY messages to all configured secondary servers.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS no\-edns
+.sp
+If enabled, no OPT record (EDNS) is inserted to outgoing requests to this
+remote server. This mode is necessary for communication with some broken
+implementations (e.g. Windows Server 2016).
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This option effectively disables \fI\%zone expire\fP timer
+updates via EDNS EXPIRE option specified in \fI\%RFC 7314\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS automatic\-acl
+.sp
+If enabled, some authorized operations for the remote are automatically allowed
+based on the context:
+.INDENT 0.0
+.IP \(bu 2
+Incoming NOTIFY is allowed from the remote if it\(aqs configured as a
+\fI\%primary server\fP for the zone.
+.IP \(bu 2
+Outgoing zone transfer is allowed to the remote if it\(aqs configured as a
+\fI\%NOTIFY target\fP for the zone.
+.UNINDENT
+.sp
+Automatic ACL rules are evaluated before explicit \fI\%zone ACL\fP configuration.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This functionality requires global activation via
+\fI\%automatic\-acl\fP in the server section.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBon\fP
+.SH REMOTES SECTION
+.sp
+Definitions of groups of remote servers. Remote grouping can simplify the
+configuration.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+remotes:
+ \- id: STR
+ remote: remote_id ...
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A remote group identifier.
+.SS remote
+.sp
+An ordered list of \fI\%references\fP to remote server definitions.
+.sp
+\fIDefault:\fP not set
+.SH ACL SECTION
+.sp
+Access control list rule definitions. An ACL rule is a description of one
+or more authorized operations (zone transfer request, zone change notification,
+and dynamic DNS update) which are allowed to be processed or denied.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+acl:
+ \- id: STR
+ address: ADDR[/INT] | ADDR\-ADDR | STR ...
+ key: key_id ...
+ cert\-key: BASE64 ...
+ remote: remote_id | remotes_id ...
+ action: query | notify | transfer | update ...
+ deny: BOOL
+ update\-type: STR ...
+ update\-owner: key | zone | name
+ update\-owner\-match: sub\-or\-equal | equal | sub | pattern
+ update\-owner\-name: STR ...
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+An ACL rule identifier.
+.SS address
+.sp
+An ordered list of IP addresses, absolute UNIX socket paths, network subnets,
+or network ranges. The query\(aqs
+source address must match one of them. If this item is not set, address match is not
+required.
+.sp
+\fIDefault:\fP not set
+.SS key
+.sp
+An ordered list of \fI\%reference\fPs to TSIG keys. The query must
+match one of them. If this item is not set, transaction authentication is not used.
+.sp
+\fIDefault:\fP not set
+.SS cert\-key
+.sp
+An ordered list of remote certificate public key PINs. If the list is non\-empty,
+communication with the remote is possible only via QUIC protocol and
+a peer certificate is required. The peer certificate key must match one of the
+specified PINs.
+.sp
+A PIN is a unique identifier that represents the public key of the peer certificate.
+It\(aqs a base64\-encoded SHA\-256 hash of the public key. This identifier
+remains the same on a certificate renewal.
+.sp
+\fIDefault:\fP not set
+.SS remote
+.sp
+An ordered list of references \fI\%remote\fP and
+\fI\%remotes\fP\&. The query must
+match one of the remotes. Specifically, one of the remote\(aqs addresses and remote\(aqs
+TSIG key if configured must match.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This option cannot be specified along with the \fI\%address\fP or
+\fI\%key\fP option at one ACL item.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS action
+.sp
+An ordered list of allowed (or denied) actions.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBquery\fP – Allow regular DNS query. As normal queries are always allowed,
+this action is only useful in combination with \fI\%TSIG key\fP\&.
+.IP \(bu 2
+\fBnotify\fP – Allow incoming notify (NOTIFY).
+.IP \(bu 2
+\fBtransfer\fP – Allow zone transfer (AXFR, IXFR).
+.IP \(bu 2
+\fBupdate\fP – Allow zone updates (DDNS).
+.UNINDENT
+.sp
+\fIDefault:\fP \fBquery\fP
+.SS deny
+.sp
+If enabled, instead of allowing, deny the specified \fI\%action\fP,
+\fI\%address\fP, \fI\%key\fP, or combination if these
+items. If no action is specified, deny all actions.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS update\-type
+.sp
+A list of allowed types of Resource Records in a zone update. Every record in an update
+must match one of the specified types.
+.sp
+\fIDefault:\fP not set
+.SS update\-owner
+.sp
+This option restricts possible owners of Resource Records in a zone update by comparing
+them to either the \fI\%TSIG key\fP identity, the current zone name, or to a list of
+domain names given by the \fI\%update\-owner\-name\fP option.
+The comparison method is given by the \fI\%update\-owner\-match\fP option.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBkey\fP — The owner of each updated RR must match the identity of the TSIG key if used.
+.IP \(bu 2
+\fBname\fP — The owner of each updated RR must match at least one name in the
+\fI\%update\-owner\-name\fP list.
+.IP \(bu 2
+\fBzone\fP — The owner of each updated RR must match the current zone name.
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS update\-owner\-match
+.sp
+This option defines how the owners of Resource Records in an update are matched to the domain name(s)
+set by the \fI\%update\-owner\fP option.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBsub\-or\-equal\fP — The owner of each RR in an update must either be equal to
+or be a subdomain of at least one domain name set by \fI\%update\-owner\fP\&.
+.IP \(bu 2
+\fBequal\fP — The owner of each updated RR must be equal to at least one domain
+name set by \fI\%update\-owner\fP\&.
+.IP \(bu 2
+\fBsub\fP — The owner of each updated RR must be a subdomain of, but MUST NOT
+be equal to at least one domain name set by \fI\%update\-owner\fP\&.
+.IP \(bu 2
+\fBpattern\fP — The owner of each updated RR must match a pattern specified by
+\fI\%update\-owner\fP\&. The pattern can be an arbitrary FQDN or non\-FQDN
+domain name. If a label consists of one \fB*\fP (asterisk) character, it
+matches any label. More asterisk labels can be specified.
+.UNINDENT
+.sp
+\fIDefault:\fP \fBsub\-or\-equal\fP
+.SS update\-owner\-name
+.sp
+A list of allowed owners of RRs in a zone update used with \fI\%update\-owner\fP
+set to \fBname\fP\&. Every listed owner name which is not FQDN (i.e. it doesn\(aqt end
+in a dot) is considered as if it was appended with the target zone name.
+Such a relative owner name specification allows better ACL rule reusability across
+multiple zones.
+.sp
+\fIDefault:\fP not set
+.SH SUBMISSION SECTION
+.sp
+Parameters of KSK submission checks.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+submission:
+ \- id: STR
+ parent: remote_id | remotes_id ...
+ check\-interval: TIME
+ timeout: TIME
+ parent\-delay: TIME
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A submission identifier.
+.SS parent
+.sp
+A list of references \fI\%remote\fP and \fI\%remotes\fP
+to parent\(aqs DNS servers to be checked for
+presence of corresponding DS records in the case of KSK submission. All of them must
+have a corresponding DS for the rollover to continue. If none is specified, the
+rollover must be pushed forward manually.
+.sp
+\fIDefault:\fP not set
+.sp
+\fBTIP:\fP
+.INDENT 0.0
+.INDENT 3.5
+A DNSSEC\-validating resolver can be set as a parent.
+.UNINDENT
+.UNINDENT
+.SS check\-interval
+.sp
+Interval for periodic checks of DS presence on parent\(aqs DNS servers, in the
+case of the KSK submission.
+.sp
+\fIDefault:\fP \fB1h\fP (1 hour)
+.SS timeout
+.sp
+After this time period (in seconds) the KSK submission is automatically considered
+successful, even if all the checks were negative or no parents are configured.
+Set to 0 for infinity.
+.sp
+\fIDefault:\fP \fB0\fP
+.SS parent\-delay
+.sp
+After successful parent DS check, wait for this period before continuing the next
+key roll\-over step. This delay shall cover the propagation delay of update in the
+parent zone.
+.sp
+\fIDefault:\fP \fB0\fP
+.SH DNSKEY-SYNC SECTION
+.sp
+Parameters of DNSKEY dynamic\-update synchrnization.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+dnskey\-sync:
+ \- id: STR
+ remote: remote_id | remotes_id ...
+ check\-interval: TIME
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A dnskey\-sync identifier.
+.SS remote
+.sp
+A list of references \fI\%remote\fP and \fI\%remotes\fP
+to other signers or common master, which the DDNS updates with
+DNSKEY/CDNSKEY/CDS records shall be sent to.
+.sp
+\fIDefault:\fP not set
+.SS check\-interval
+.sp
+If the last DNSKEY sync failed or resulted in any change, re\-check
+the consistence after this interval and re\-try if needed.
+.sp
+\fIDefault:\fP \fB60\fP (1 minute)
+.SH POLICY SECTION
+.sp
+DNSSEC policy configuration.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+policy:
+ \- id: STR
+ keystore: keystore_id
+ manual: BOOL
+ single\-type\-signing: BOOL
+ algorithm: rsasha1 | rsasha1\-nsec3\-sha1 | rsasha256 | rsasha512 | ecdsap256sha256 | ecdsap384sha384 | ed25519 | ed448
+ ksk\-size: SIZE
+ zsk\-size: SIZE
+ ksk\-shared: BOOL
+ dnskey\-ttl: TIME
+ zone\-max\-ttl: TIME
+ ksk\-lifetime: TIME
+ zsk\-lifetime: TIME
+ delete\-delay: TIME
+ propagation\-delay: TIME
+ rrsig\-lifetime: TIME
+ rrsig\-refresh: TIME
+ rrsig\-pre\-refresh: TIME
+ reproducible\-signing: BOOL
+ nsec3: BOOL
+ nsec3\-iterations: INT
+ nsec3\-opt\-out: BOOL
+ nsec3\-salt\-length: INT
+ nsec3\-salt\-lifetime: TIME
+ signing\-threads: INT
+ ksk\-submission: submission_id
+ ds\-push: remote_id | remotes_id ...
+ cds\-cdnskey\-publish: none | delete\-dnssec | rollover | always | double\-ds
+ cds\-digest\-type: sha256 | sha384
+ dnskey\-management: full | incremental
+ offline\-ksk: BOOL
+ unsafe\-operation: none | no\-check\-keyset | no\-update\-dnskey | no\-update\-nsec | no\-update\-expired ...
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A policy identifier.
+.SS keystore
+.sp
+A \fI\%reference\fP to a keystore holding private key material
+for zones.
+.sp
+\fIDefault:\fP an imaginary keystore with all default values
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+A configured keystore called \(dqdefault\(dq won\(aqt be used unless explicitly referenced.
+.UNINDENT
+.UNINDENT
+.SS manual
+.sp
+If enabled, automatic key management is not used.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS single\-type\-signing
+.sp
+If enabled, Single\-Type Signing Scheme is used in the automatic key management
+mode.
+.sp
+\fIDefault:\fP \fBoff\fP (\fI\%module onlinesign\fP has default \fBon\fP)
+.SS algorithm
+.sp
+An algorithm of signing keys and issued signatures. See
+\fI\%DNSSEC Algorithm Numbers\fP\&.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBrsasha1\fP
+.IP \(bu 2
+\fBrsasha1\-nsec3\-sha1\fP
+.IP \(bu 2
+\fBrsasha256\fP
+.IP \(bu 2
+\fBrsasha512\fP
+.IP \(bu 2
+\fBecdsap256sha256\fP
+.IP \(bu 2
+\fBecdsap384sha384\fP
+.IP \(bu 2
+\fBed25519\fP
+.IP \(bu 2
+\fBed448\fP
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Ed25519 algorithm is only available if compiled with GnuTLS 3.6.0+.
+.sp
+Ed448 algorithm is only available if compiled with GnuTLS 3.6.12+ and Nettle 3.6+.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBecdsap256sha256\fP
+.SS ksk\-size
+.sp
+A length of newly generated KSK or
+CSK keys.
+.sp
+\fIDefault:\fP \fB2048\fP (rsa*), \fB256\fP (ecdsap256), \fB384\fP (ecdsap384), \fB256\fP (ed25519),
+\fB456\fP (ed448)
+.SS zsk\-size
+.sp
+A length of newly generated ZSK keys.
+.sp
+\fIDefault:\fP see default for \fI\%ksk\-size\fP
+.SS ksk\-shared
+.sp
+If enabled, all zones with this policy assigned will share one or more KSKs.
+More KSKs can be shared during a KSK rollover.
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+As the shared KSK set is bound to the policy \fI\%id\fP, renaming the
+policy breaks this connection and new shared KSK set is initiated when
+a new KSK is needed.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS dnskey\-ttl
+.sp
+A TTL value for DNSKEY records added into zone apex.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Has influence over ZSK key lifetime.
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+Ensure all DNSKEYs with updated TTL are propagated before any subsequent
+DNSKEY rollover starts.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP zone SOA TTL
+.SS zone\-max\-ttl
+.sp
+Declare (override) maximal TTL value among all the records in zone.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+It\(aqs generally recommended to override the maximal TTL computation by setting this
+explicitly whenever possible. It\(aqs required for \fI\%DNSSEC Offline KSK\fP and
+really reasonable when records are generated dynamically
+(e.g. by a \fI\%module\fP).
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP computed after zone is loaded
+.SS ksk\-lifetime
+.sp
+A period between KSK generation and the next rollover initiation.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+KSK key lifetime is also influenced by propagation\-delay, dnskey\-ttl,
+and KSK submission delay.
+.sp
+Zero (aka infinity) value causes no KSK rollover as a result.
+.sp
+This applies for CSK lifetime if single\-type\-signing is enabled.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB0\fP
+.SS zsk\-lifetime
+.sp
+A period between ZSK activation and the next rollover initiation.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+More exactly, this period is measured since a ZSK is activated,
+and after this, a new ZSK is generated to replace it within
+following roll\-over.
+.sp
+ZSK key lifetime is also influenced by propagation\-delay and dnskey\-ttl
+.sp
+Zero (aka infinity) value causes no ZSK rollover as a result.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB30d\fP (30 days)
+.SS delete\-delay
+.sp
+Once a key (KSK or ZSK) is rolled\-over and removed from the zone,
+keep it in the KASP database for at least this period before deleting it completely.
+This might be useful in some troubleshooting cases when resurrection
+is needed.
+.sp
+\fIDefault:\fP \fB0\fP
+.SS propagation\-delay
+.sp
+An extra delay added for each key rollover step. This value should be high
+enough to cover propagation of data from the primary server to all
+secondary servers, as well as the duration of signing routine itself and
+possible outages in signing and propagation infrastructure. In other words,
+this delay should ensure that within this period of time after planned
+change of the key set, all public\-facing secondaries will already serve
+new DNSKEY RRSet for sure.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Has influence over ZSK key lifetime.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB1h\fP (1 hour)
+.SS rrsig\-lifetime
+.sp
+A validity period of newly issued signatures.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The RRSIG\(aqs signature inception time is set to 90 minutes in the past. This
+time period is not counted to the signature lifetime.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB14d\fP (14 days)
+.SS rrsig\-refresh
+.sp
+A period how long at least before a signature expiration the signature will be refreshed,
+in order to prevent expired RRSIGs on secondary servers or resolvers\(aq caches.
+.sp
+\fIDefault:\fP 0.1 * \fI\%rrsig\-lifetime\fP + \fI\%propagation\-delay\fP + \fI\%zone\-max\-ttl\fP
+.SS rrsig\-pre\-refresh
+.sp
+A period how long at most before a signature refresh time the signature might be refreshed,
+in order to refresh RRSIGs in bigger batches on a frequently updated zone
+(avoid re\-sign event too often).
+.sp
+\fIDefault:\fP \fB1h\fP (1 hour)
+.SS reproducible\-signing
+.sp
+For ECDSA algorithms, generate RRSIG signatures deterministically (\fI\%RFC 6979\fP).
+Besides better theoretical cryptographic security, this mode allows significant
+speed\-up of loading signed (by the same method) zones. However, the zone signing
+is a bit slower.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS nsec3
+.sp
+Specifies if NSEC3 will be used instead of NSEC.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS nsec3\-iterations
+.sp
+A number of additional times the hashing is performed.
+.sp
+\fIDefault:\fP \fB0\fP
+.SS nsec3\-opt\-out
+.sp
+If set, NSEC3 records won\(aqt be created for insecure delegations.
+This speeds up the zone signing and reduces overall zone size.
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+NSEC3 with the Opt\-Out bit set no longer works as a proof of non\-existence
+in this zone.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS nsec3\-salt\-length
+.sp
+A length of a salt field in octets, which is appended to the original owner
+name before hashing.
+.sp
+\fIDefault:\fP \fB8\fP
+.SS nsec3\-salt\-lifetime
+.sp
+A validity period of newly issued salt field.
+.sp
+Zero value means infinity.
+.sp
+Special value \fI\-1\fP triggers re\-salt every time when active ZSK changes.
+This optimizes the number of big changes to the zone.
+.sp
+\fIDefault:\fP \fB30d\fP (30 days)
+.SS signing\-threads
+.sp
+When signing zone or update, use this number of threads for parallel signing.
+.sp
+Those are extra threads independent of \fI\%Background workers\fP\&.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Some steps of the DNSSEC signing operation are not parallelized.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB1\fP (no extra threads)
+.SS ksk\-submission
+.sp
+A reference to \fI\%submission\fP section holding parameters of
+KSK submission checks.
+.sp
+\fIDefault:\fP not set
+.SS ds\-push
+.sp
+Optional references \fI\%remote\fP and \fI\%remotes\fP
+to authoritative DNS server of the
+parent\(aqs zone. The remote server must be configured to accept DS record
+updates via DDNS. Whenever a CDS record in the local zone is changed, the
+corresponding DS record is sent as a dynamic update (DDNS) to the parent
+DNS server. All previous DS records are deleted within the DDNS message.
+It\(aqs possible to manage both child and parent zones by the same Knot DNS server.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This feature requires \fI\%cds\-cdnskey\-publish\fP
+not to be set to \fBnone\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The mentioned change to CDS record usually means that a KSK roll\-over is running
+and the new key being rolled\-in is in \(dqready\(dq state already for the period of
+\fI\%propagation\-delay\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Module \fI\%Onlinesign\fP doesn\(aqt support DS push.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS dnskey\-sync
+.sp
+A reference to \fI\%dnskey\-sync\fP section holding parameters
+of DNSKEY synchronization.
+.sp
+\fIDefault:\fP not set
+.SS cds\-cdnskey\-publish
+.sp
+Controls if and how shall the CDS and CDNSKEY be published in the zone.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBnone\fP – Never publish any CDS or CDNSKEY records in the zone.
+.IP \(bu 2
+\fBdelete\-dnssec\fP – Publish special CDS and CDNSKEY records indicating turning off DNSSEC.
+.IP \(bu 2
+\fBrollover\fP – Publish CDS and CDNSKEY records for ready and not yet active KSK (submission phase of KSK rollover).
+.IP \(bu 2
+\fBalways\fP – Always publish one CDS and one CDNSKEY records for the current KSK.
+.IP \(bu 2
+\fBdouble\-ds\fP – Always publish up to two CDS and two CDNSKEY records for ready and/or active KSKs.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+If the zone keys are managed manually, the CDS and CDNSKEY rrsets may contain
+more records depending on the keys available.
+.UNINDENT
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+The \fBdouble\-ds\fP value does not trigger double\-DS roll\-over method. That method is
+only supported when performed manually, with unset \fI\%ksk\-submission\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBrollover\fP
+.SS cds\-digest\-type
+.sp
+Specify digest type for published CDS records.
+.sp
+\fIDefault:\fP \fBsha256\fP
+.SS dnskey\-management
+.sp
+Specify how the DNSKEY, CDNSKEY, and CDS RRSets at the zone apex are handled
+when (re\-)signing the zone.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBfull\fP – Upon every zone (re\-)sign, delete all unknown DNSKEY, CDNSKEY, and CDS
+records and keep just those that are related to the zone keys stored in the KASP database.
+.IP \(bu 2
+\fBincremental\fP – Keep unknown DNSKEY, CDNSKEY, and CDS records in the zone, and
+modify server\-managed records incrementally by employing changes in the KASP database.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Prerequisites for \fIincremental\fP:
+.INDENT 0.0
+.IP \(bu 2
+The \fI\%Offline KSK\fP isn\(aqt supported.
+.IP \(bu 2
+The \fI\%delete\-delay\fP is long enough to cover possible daemon
+shutdown (e.g. due to server maintenance).
+.IP \(bu 2
+Avoided manual deletion of keys with \fI\%keymgr\fP\&.
+.UNINDENT
+.sp
+Otherwise there might remain some DNSKEY records in the zone, belonging to
+deleted keys.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBfull\fP
+.SS offline\-ksk
+.sp
+Specifies if \fI\%Offline KSK\fP feature is enabled.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS unsafe\-operation
+.sp
+Turn off some DNSSEC safety features.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBnone\fP – Nothing disabled.
+.IP \(bu 2
+\fBno\-check\-keyset\fP – Don\(aqt check active keys in present algorithms. This may
+lead to violation of \fI\%RFC 4035#section\-2.2\fP\&.
+.IP \(bu 2
+\fBno\-update\-dnskey\fP – Don\(aqt maintain/update DNSKEY, CDNSKEY, and CDS records
+in the zone apex according to KASP database. Juste leave them as they are in the zone.
+.IP \(bu 2
+\fBno\-update\-nsec\fP – Don\(aqt maintain/update NSEC/NSEC3 chain. Leave all the records
+as they are in the zone.
+.IP \(bu 2
+\fBno\-update\-expired\fP – Don\(aqt update expired RRSIGs.
+.UNINDENT
+.sp
+Multiple values may be specified.
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+This mode is intended for DNSSEC experts who understand the corresponding consequences.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBnone\fP
+.SH TEMPLATE SECTION
+.sp
+A template is shareable zone settings, which can simplify configuration by
+reducing duplicates. A special default template (with the \fIdefault\fP identifier)
+can be used for global zone configuration or as an implicit configuration
+if a zone doesn\(aqt have another template specified.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+template:
+ \- id: STR
+ global\-module: STR/STR ...
+ # All zone options (excluding \(aqtemplate\(aq item)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+If an item is explicitly specified both in the referenced template and
+the zone, the template item value is overridden by the zone item value.
+.UNINDENT
+.UNINDENT
+.SS id
+.sp
+A template identifier.
+.SS global\-module
+.sp
+An ordered list of references to query modules in the form of \fImodule_name\fP or
+\fImodule_name/module_id\fP\&. These modules apply to all queries.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This option is only available in the \fIdefault\fP template.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SH ZONE SECTION
+.sp
+Definition of zones served by the server.
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+zone:
+ \- domain: DNAME
+ template: template_id
+ storage: STR
+ file: STR
+ master: remote_id | remotes_id ...
+ ddns\-master: remote_id
+ notify: remote_id | remotes_id ...
+ acl: acl_id ...
+ master\-pin\-tolerance: TIME
+ provide\-ixfr: BOOL
+ semantic\-checks: BOOL | soft
+ zonefile\-sync: TIME
+ zonefile\-load: none | difference | difference\-no\-serial | whole
+ journal\-content: none | changes | all
+ journal\-max\-usage: SIZE
+ journal\-max\-depth: INT
+ ixfr\-benevolent: BOOL
+ ixfr\-by\-one: BOOL
+ ixfr\-from\-axfr: BOOL
+ zone\-max\-size : SIZE
+ adjust\-threads: INT
+ dnssec\-signing: BOOL
+ dnssec\-validation: BOOL
+ dnssec\-policy: policy_id
+ ds\-push: remote_id | remotes_id ...
+ zonemd\-verify: BOOL
+ zonemd\-generate: none | zonemd\-sha384 | zonemd\-sha512 | remove
+ serial\-policy: increment | unixtime | dateserial
+ serial\-modulo: INT/INT
+ reverse\-generate: DNAME
+ refresh\-min\-interval: TIME
+ refresh\-max\-interval: TIME
+ retry\-min\-interval: TIME
+ retry\-max\-interval: TIME
+ expire\-min\-interval: TIME
+ expire\-max\-interval: TIME
+ catalog\-role: none | interpret | generate | member
+ catalog\-template: template_id ...
+ catalog\-zone: DNAME
+ catalog\-group: STR
+ module: STR/STR ...
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS domain
+.sp
+A zone name identifier.
+.SS template
+.sp
+A \fI\%reference\fP to a configuration template.
+.sp
+\fIDefault:\fP not set or \fBdefault\fP (if the template exists)
+.SS storage
+.sp
+A data directory for storing zone files. A non\-absolute path is relative to
+the \fI\%knotd\fP startup directory.
+.sp
+\fIDefault:\fP \fB${localstatedir}/lib/knot\fP (configured with \fB\-\-with\-storage=path\fP)
+.SS file
+.sp
+A \fI\%path\fP to the zone file. It is also possible to use
+the following formatters:
+.INDENT 0.0
+.IP \(bu 2
+\fB%c[\fP\fIN\fP\fB]\fP or \fB%c[\fP\fIN\fP\fB\-\fP\fIM\fP\fB]\fP – Means the \fIN\fPth
+character or a sequence of characters beginning from the \fIN\fPth and ending
+with the \fIM\fPth character of the textual zone name (see \fB%s\fP). The
+indexes are counted from 0 from the left. All dots (including the terminal
+one) are considered. If the character is not available, the formatter has no effect.
+.IP \(bu 2
+\fB%l[\fP\fIN\fP\fB]\fP – Means the \fIN\fPth label of the textual zone name
+(see \fB%s\fP). The index is counted from 0 from the right (0 ~ TLD).
+If the label is not available, the formatter has no effect.
+.IP \(bu 2
+\fB%s\fP – Means the current zone name in the textual representation.
+The zone name doesn\(aqt include the terminating dot (the result for the root
+zone is the empty string!).
+.IP \(bu 2
+\fB%%\fP – Means the \fB%\fP character.
+.UNINDENT
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+Beware of special characters which are escaped or encoded in the \eDDD form
+where DDD is corresponding decimal ASCII code.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fI\%storage\fP\fB/%s.zone\fP
+.SS master
+.sp
+An ordered list of references \fI\%remote\fP and
+\fI\%remotes\fP to zone primary servers
+(formerly known as master servers).
+.sp
+\fIDefault:\fP not set
+.SS ddns\-master
+.sp
+A \fI\%reference\fP to a zone primary master where DDNS messages
+should be forwarded to. If not specified, the first \fI\%master\fP
+server is used.
+.sp
+If set to the empty value (\(dq\(dq), incoming DDNS messages aren\(aqt forwarded but are applied
+to the local zone instead, no matter if it is a secondary server. This is only allowed in
+combination with \fI\%dnssec\-signing\fP enabled.
+.sp
+\fIDefault:\fP not set
+.SS notify
+.sp
+An ordered list of references \fI\%remote\fP and
+\fI\%remotes\fP to secondary servers to which notify
+message is sent if the zone changes.
+.sp
+\fIDefault:\fP not set
+.SS acl
+.sp
+An ordered list of \fI\%references\fP to ACL rules which can allow
+or disallow zone transfers, updates or incoming notifies.
+.sp
+\fIDefault:\fP not set
+.SS master\-pin\-tolerance
+.sp
+If set to a nonzero value on a secondary, always request AXFR/IXFR from the same
+primary as the last time, effectively pinning one primary. Only when another
+primary is updated and the current one lags behind for the specified amount of time
+(defined by this option), change to the updated primary and force AXFR.
+.sp
+This option is useful when multiple primaries may have different zone history
+in their journals, making it unsafe to combine interchanged IXFR
+from different primaries.
+.sp
+\fIDefault:\fP 0
+.SS provide\-ixfr
+.sp
+If disabled, the server is forced to respond with AXFR to IXFR queries.
+If enabled, IXFR requests are responded normally.
+.sp
+\fIDefault:\fP \fBon\fP
+.SS semantic\-checks
+.sp
+Selects if extra zone semantic checks are used or impacts of the mandatory checks.
+.sp
+There are several mandatory checks which are always enabled and cannot be turned
+off. An error in a mandatory check causes the zone not to be loaded. Most of
+the mandatory checks can be weakened by setting \fBsoft\fP, which allows the zone to
+be loaded even if the check fails.
+.sp
+If enabled, extra checks are used. These checks don\(aqt prevent the zone from loading.
+.sp
+The mandatory checks are applied to zone files, zone transfers, and updates via
+control interface. The extra checks are applied to zone files only!
+.sp
+Mandatory checks:
+.INDENT 0.0
+.IP \(bu 2
+Missing SOA record at the zone apex (\fI\%RFC 1034\fP) (*)
+.IP \(bu 2
+An extra record exists together with a CNAME record except for RRSIG and NSEC (\fI\%RFC 1034\fP)
+.IP \(bu 2
+Multiple CNAME records with the same owner exist (\fI\%RFC 1034\fP)
+.IP \(bu 2
+DNAME record having a record under it (\fI\%RFC 6672\fP)
+.IP \(bu 2
+Multiple DNAME records with the same owner exist (\fI\%RFC 6672\fP)
+.IP \(bu 2
+NS record exists together with a DNAME record (\fI\%RFC 6672\fP)
+.IP \(bu 2
+DS record exists at the zone apex (\fI\%RFC 3658\fP)
+.UNINDENT
+.sp
+(*) The marked check can\(aqt be weakened by the soft mode. All other mandatory checks
+are subject to the optional soft mode.
+.sp
+Extra checks:
+.INDENT 0.0
+.IP \(bu 2
+Missing NS record at the zone apex
+.IP \(bu 2
+Missing glue A or AAAA record
+.IP \(bu 2
+Invalid DS or NSEC3PARAM record
+.IP \(bu 2
+CDS or CDNSKEY inconsistency
+.IP \(bu 2
+All other DNSSEC checks executed during \fI\%dnssec\-validation\fP
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+The soft mode allows the refresh event to ignore a CNAME response to a SOA
+query (malformed message) and triggers a zone bootstrap instead.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS zonefile\-sync
+.sp
+The time after which the current zone in memory will be synced with a zone file
+on the disk (see \fI\%file\fP). The server will serve the latest
+zone even after a restart using zone journal, but the zone file on the disk will
+only be synced after \fBzonefile\-sync\fP time has expired (or after manual zone
+flush). This is applicable when the zone is updated via IXFR, DDNS or automatic
+DNSSEC signing. In order to completely disable automatic zone file synchronization,
+set the value to \-1. In that case, it is still possible to force a manual zone flush
+using the \fB\-f\fP option.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+If you are serving large zones with frequent updates where
+the immediate sync with a zone file is not desirable, increase the value.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB0\fP (immediate)
+.SS zonefile\-load
+.sp
+Selects how the zone file contents are applied during zone load.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBnone\fP – The zone file is not used at all.
+.IP \(bu 2
+\fBdifference\fP – If the zone contents are already available during server start or reload,
+the difference is computed between them and the contents of the zone file. This difference
+is then checked for semantic errors and applied to the current zone contents.
+.IP \(bu 2
+\fBdifference\-no\-serial\fP – Same as \fBdifference\fP, but the SOA serial in the zone file is
+ignored, the server takes care of incrementing the serial automatically.
+.IP \(bu 2
+\fBwhole\fP – Zone contents are loaded from the zone file.
+.UNINDENT
+.sp
+When \fBdifference\fP is configured and there are no zone contents yet (cold start
+and no zone contents in the journal), it behaves the same way as \fBwhole\fP\&.
+.sp
+\fIDefault:\fP \fBwhole\fP
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+See \fI\%Handling zone file, journal, changes, serials\fP for guidance on
+configuring these and related options to ensure reliable operation.
+.UNINDENT
+.UNINDENT
+.SS journal\-content
+.sp
+Selects how the journal shall be used to store zone and its changes.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBnone\fP – The journal is not used at all.
+.IP \(bu 2
+\fBchanges\fP – Zone changes history is stored in journal.
+.IP \(bu 2
+\fBall\fP – Zone contents and history is stored in journal.
+.UNINDENT
+.sp
+\fIDefault:\fP \fBchanges\fP
+.sp
+\fBWARNING:\fP
+.INDENT 0.0
+.INDENT 3.5
+When this option is changed, the journal still contains data respective to
+the previous setting. For example, changing it to \fBnone\fP does not purge
+the journal. Also, changing it from \fBall\fP to \fBchanges\fP
+does not cause the deletion of the zone\-in\-journal and the behaviour of the
+zone loading procedure might be different than expected. It is recommended
+to consider purging the journal when this option is changed.
+.UNINDENT
+.UNINDENT
+.SS journal\-max\-usage
+.sp
+Policy how much space in journal DB will the zone\(aqs journal occupy.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Journal DB may grow far above the sum of journal\-max\-usage across
+all zones, because of DB free space fragmentation.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB100M\fP (100 MiB)
+.SS journal\-max\-depth
+.sp
+Maximum history length of the journal.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Zone\-in\-journal changeset isn\(aqt counted to the limit.
+.UNINDENT
+.UNINDENT
+.sp
+\fIMinimum:\fP \fB2\fP
+.sp
+\fIDefault:\fP \fB20\fP
+.SS ixfr\-benevolent
+.sp
+If enabled, incoming IXFR is applied even when it contains removals of non\-existing
+or additions of existing records.
+.sp
+\fIDefault:\fP off
+.SS ixfr\-by\-one
+.sp
+Within incoming IXFR, process only one changeset at a time, not multiple together.
+This preserves the complete history in the journal and prevents the merging of
+changesets when multiple changesets are IXFRed simultaneously. However, this does not
+prevent the merging (or deletion) of old changesets in the journal to save space,
+as described in \fI\%journal behaviour\fP\&.
+.sp
+This option leads to increased server load when processing IXFR, including
+network traffic.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS ixfr\-from\-axfr
+.sp
+If a primary sends AXFR\-style\-IXFR upon an IXFR request, compute the difference
+and process it as an incremental zone update (e.g. by storing the changeset in
+the journal).
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS zone\-max\-size
+.sp
+Maximum size of the zone. The size is measured as size of the zone records
+in wire format without compression. The limit is enforced for incoming zone
+transfers and dynamic updates.
+.sp
+For incremental transfers (IXFR), the effective limit for the total size of
+the records in the transfer is twice the configured value. However the final
+size of the zone must satisfy the configured value.
+.sp
+\fIDefault:\fP unlimited
+.SS adjust\-threads
+.sp
+Parallelize internal zone adjusting procedures by using specified number of
+threads. This is useful with huge zones with NSEC3. Speedup observable at
+server startup and while processing NSEC3 re\-salt.
+.sp
+\fIDefault:\fP \fB1\fP (no extra threads)
+.SS dnssec\-signing
+.sp
+If enabled, automatic DNSSEC signing for the zone is turned on.
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS dnssec\-validation
+.sp
+If enabled, the zone contents are validated for being correctly signed
+(including NSEC/NSEC3 chain) with DNSSEC signatures every time the zone
+is loaded or changed (including AXFR/IXFR).
+.sp
+When the validation fails, the zone being loaded or update being applied
+is cancelled with an error, and either none or previous zone state is published.
+.sp
+List of DNSSEC checks:
+.INDENT 0.0
+.IP \(bu 2
+Every zone RRSet is correctly signed by at least one present DNSKEY.
+.IP \(bu 2
+DNSKEY RRSet is signed by KSK.
+.IP \(bu 2
+NSEC(3) RR exists for each name (unless opt\-out) with correct bitmap.
+.IP \(bu 2
+Every NSEC(3) RR is linked to the lexicographically next one.
+.UNINDENT
+.sp
+The validation is not affected by \fI\%dnssec\-policy\fP configuration,
+except for \fI\%signing\-threads\fP option, which specifies the number
+of threads for parallel validation.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Redundant or garbage NSEC3 records are ignored.
+.sp
+This mode is not compatible with \fI\%dnssec\-signing\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS dnssec\-policy
+.sp
+A \fI\%reference\fP to DNSSEC signing policy.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+A configured policy called \(dqdefault\(dq won\(aqt be used unless explicitly referenced.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP an imaginary policy with all default values
+.SS ds\-push
+.sp
+Per zone configuration of \fI\%ds\-push\fP\&. This option overrides possible
+per policy option.
+.sp
+\fIDefault:\fP not set
+.SS zonemd\-verify
+.sp
+On each zone load/update, verify that ZONEMD is present in the zone and valid.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+Zone digest calculation may take much time and CPU on large zones.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBoff\fP
+.SS zonemd\-generate
+.sp
+On each zone update, calculate ZONEMD and put it into the zone.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBnone\fP – No action regarding ZONEMD.
+.IP \(bu 2
+\fBzonemd\-sha384\fP – Generate ZONEMD using SHA384 algorithm.
+.IP \(bu 2
+\fBzonemd\-sha512\fP – Generate ZONEMD using SHA512 algorithm.
+.IP \(bu 2
+\fBremove\fP – Remove any ZONEMD from the zone apex.
+.UNINDENT
+.sp
+\fIDefault:\fP \fBnone\fP
+.SS serial\-policy
+.sp
+Specifies how the zone serial is updated after a dynamic update or
+automatic DNSSEC signing. If the serial is changed by the dynamic update,
+no change is made.
+.sp
+Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBincrement\fP – The serial is incremented according to serial number arithmetic.
+.IP \(bu 2
+\fBunixtime\fP – The serial is set to the current unix time.
+.IP \(bu 2
+\fBdateserial\fP – The 10\-digit serial (YYYYMMDDnn) is incremented, the first
+8 digits match the current iso\-date.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+If the resulting serial for \fBunixtime\fP or \fBdateserial\fP is lower than or
+equal to the current serial (this happens e.g. when migrating from other policy or
+frequent updates), the serial is incremented instead.
+.sp
+To avoid user confusion, use \fBdateserial\fP only if you expect at most
+100 updates per day per zone and \fBunixtime\fP only if you expect at most
+one update per second per zone.
+.sp
+Generated catalog zones use \fBunixtime\fP only.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBincrement\fP (\fBunixtime\fP for generated catalog zones)
+.SS serial\-modulo
+.sp
+Specifies that the zone serials shall be congruent by specified modulo.
+The option value must be a string in the format \fBR/M\fP, where \fBR < M <= 256\fP are
+positive integers. Whenever the zone serial is incremented, it is ensured
+that \fBserial % M == R\fP\&. This can be useful in the case of multiple inconsistent
+primaries, where distinct zone serial sequences prevent cross\-master\-IXFR
+by any secondary.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+In order to ensure the congruent policy, this option is only allowed
+with \fI\%DNSSEC signing enabled\fP and
+\fI\%zonefile\-load\fP to be either \fBdifference\-no\-serial\fP or \fBnone\fP\&.
+.sp
+Because the zone serial effectively always increments by \fBM\fP instead of
+\fB1\fP, it is not recommended to use \fBdateserial\fP \fI\%serial\-policy\fP
+or even \fBunixtime\fP in case of rapidly updated zone.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fB0/1\fP
+.SS reverse\-generate
+.sp
+This option triggers the automatic generation of reverse PTR records based on
+A/AAAA records in the specified zone. The entire generated zone is automatically
+stored in the journal.
+.sp
+Current limitations:
+.INDENT 0.0
+.IP \(bu 2
+Only one zone to be reversed can be specified.
+.IP \(bu 2
+Is slow for large zones (even when changing a little).
+.UNINDENT
+.sp
+\fIDefault:\fP none
+.SS refresh\-min\-interval
+.sp
+Forced minimum zone refresh interval (in seconds) to avoid flooding primary server.
+.sp
+\fIMinimum:\fP \fB2\fP
+.sp
+\fIDefault:\fP \fB2\fP
+.SS refresh\-max\-interval
+.sp
+Forced maximum zone refresh interval (in seconds).
+.sp
+\fIDefault:\fP not set
+.SS retry\-min\-interval
+.sp
+Forced minimum zone retry interval (in seconds) to avoid flooding primary server.
+.sp
+\fIMinimum:\fP \fB1\fP
+.sp
+\fIDefault:\fP \fB1\fP
+.SS retry\-max\-interval
+.sp
+Forced maximum zone retry interval (in seconds).
+.sp
+\fIDefault:\fP not set
+.SS expire\-min\-interval
+.sp
+Forced minimum zone expire interval (in seconds) to avoid flooding primary server.
+.sp
+\fIMinimum:\fP \fB3\fP
+.sp
+\fIDefault:\fP \fB3\fP
+.SS expire\-max\-interval
+.sp
+Forced maximum zone expire interval (in seconds).
+.sp
+\fIDefault:\fP not set
+.SS catalog\-role
+.sp
+Trigger zone catalog feature. Possible values:
+.INDENT 0.0
+.IP \(bu 2
+\fBnone\fP – Not a catalog zone.
+.IP \(bu 2
+\fBinterpret\fP – A catalog zone which is loaded from a zone file or XFR,
+and member zones shall be configured based on its contents.
+.IP \(bu 2
+\fBgenerate\fP – A catalog zone whose contents are generated according to
+assigned member zones.
+.IP \(bu 2
+\fBmember\fP – A member zone that is assigned to one generated catalog zone.
+.UNINDENT
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+If set to \fBgenerate\fP, the \fI\%zonefile\-load\fP option has no effect
+since a zone file is never loaded.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP \fBnone\fP
+.SS catalog\-template
+.sp
+For the catalog member zones, the specified configuration template will be applied.
+.sp
+Multiple catalog templates may be defined. The first one is used unless the member zone
+has the \fIgroup\fP property defined, matching another catalog template.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This option must be set if and only if \fI\%catalog\-role\fP is \fIinterpret\fP\&.
+.sp
+Nested catalog zones aren\(aqt supported. Therefore catalog templates can\(aqt use
+\fI\%catalog\-template\fP, \fI\%catalog\-role\fP, \fI\%catalog\-zone\fP,
+and \fI\%catalog\-group\fP options.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS catalog\-zone
+.sp
+Assign this member zone to specified generated catalog zone.
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This option must be set if and only if \fI\%catalog\-role\fP is \fImember\fP\&.
+.sp
+The referenced catalog zone must exist and have \fI\%catalog\-role\fP set to \fIgenerate\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS catalog\-group
+.sp
+Assign this member zone to specified catalog group (configuration template).
+.sp
+\fBNOTE:\fP
+.INDENT 0.0
+.INDENT 3.5
+This option has effect if and only if \fI\%catalog\-role\fP is \fImember\fP\&.
+.UNINDENT
+.UNINDENT
+.sp
+\fIDefault:\fP not set
+.SS module
+.sp
+An ordered list of references to query modules in the form of \fImodule_name\fP or
+\fImodule_name/module_id\fP\&. These modules apply only to the current zone queries.
+.sp
+\fIDefault:\fP not set
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/knotc.8in b/doc/man/knotc.8in
new file mode 100644
index 0000000..36e7c98
--- /dev/null
+++ b/doc/man/knotc.8in
@@ -0,0 +1,438 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KNOTC" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+knotc \- Knot DNS control utility
+.SH SYNOPSIS
+.sp
+\fBknotc\fP [\fIconfig_option\fP] [\fIoptions\fP] [\fIaction\fP]
+.SH DESCRIPTION
+.sp
+This program controls a running \fIknotd\fP process using a socket.
+.sp
+If an \fIaction\fP is specified, it is performed and \fIknotc\fP exits, otherwise the program
+is executed in the interactive mode.
+.SS Config options
+.INDENT 0.0
+.TP
+\fB\-c\fP, \fB\-\-config\fP \fIfile\fP
+Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP).
+.TP
+\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP
+Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP).
+The default configuration database, if exists, has a preference to the default
+configuration file.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-m\fP, \fB\-\-max\-conf\-size\fP \fIMiB\fP
+Set maximum size of the configuration database
+(default is @conf_mapsize@ MiB, maximum 10000 MiB).
+.TP
+\fB\-s\fP, \fB\-\-socket\fP \fIpath\fP
+Use a control UNIX socket path (default is \fB@run_dir@/knot.sock\fP).
+.TP
+\fB\-t\fP, \fB\-\-timeout\fP \fIseconds\fP
+Use a control timeout in seconds. Set to 0 for infinity (default is 60).
+The control socket operations are also subject to the \fI\%timeout\fP
+parameter set on the server side in server\(aqs Control configuration section.
+.TP
+\fB\-b\fP, \fB\-\-blocking\fP
+Zone event trigger commands wait until the event is finished. Control timeout
+is set to infinity if not forced by explicit timeout specification.
+.TP
+\fB\-e\fP, \fB\-\-extended\fP
+Show extended output (even empty items in zone status).
+.TP
+\fB\-f\fP, \fB\-\-force\fP
+Forced operation. Overrides some checks.
+.TP
+\fB\-x\fP, \fB\-\-mono\fP
+Don\(aqt generate colorized output.
+.TP
+\fB\-X\fP, \fB\-\-color\fP
+Force colorized output in extended output or to a pipe.
+.TP
+\fB\-v\fP, \fB\-\-verbose\fP
+Enable debug output.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.SS Actions
+.INDENT 0.0
+.TP
+\fBstatus\fP [\fIdetail\fP]
+Check if the server is running. Details are \fBversion\fP for the running
+server version, \fBworkers\fP for the numbers of worker threads,
+\fBconfigure\fP for the configure summary, or \fBcert\-key\fP for the
+public key pin of the currently used certificate.
+.TP
+\fBstop\fP
+Stop the server if running.
+.TP
+\fBreload\fP
+Reload the server configuration and modified zone files. All open zone
+transactions will be aborted!
+.TP
+\fBstats\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]]
+Show global statistics counter(s). To print also counters with value 0, use
+force option.
+.TP
+\fBzone\-check\fP [\fIzone\fP\&...]
+Test if the server can load the zone. Semantic checks are executed if enabled
+in the configuration. If invoked with the force option, an error is returned
+when semantic check warning appears. (*)
+.TP
+\fBzone\-status\fP [\fIzone\fP\&...] [\fIfilter\fP]
+Show the zone status. Filters are \fB+role\fP, \fB+serial\fP, \fB+transaction\fP,
+\fB+events\fP, \fB+freeze\fP, and \fB+catalog\fP\&. Empty zone parameters are omitted,
+unless the \fB\-\-extended\fP option is used. A single dash in the output represents
+an unset value. Automatic colorization can be overruled using the \fB\-\-mono\fP and
+\fB\-\-color\fP options.
+.sp
+The color code is:
+\fIgreen\fP \- zone acts as a master / \fIred\fP \- zone acts as a slave,
+\fIbold font (highlited)\fP \- zone is active / \fInormal\fP \- zone is empty,
+\fIunderscored\fP \- zone is an interpreted catalog member.
+.TP
+\fBzone\-reload\fP [\fIzone\fP\&...]
+Trigger a zone reload from a disk without checking its modification time. For
+secondary zone, the refresh event from primary server(s) is scheduled;
+for primary zone, the notify event to secondary server(s) is scheduled. An open
+zone transaction will be aborted! If invoked with the force option, also zone
+modules will be re\-loaded, but blocking mode might not work reliably. (#)
+.TP
+\fBzone\-refresh\fP [\fIzone\fP\&...]
+Trigger a check for the zone serial on the zone\(aqs primary server. If
+the primary server has a newer zone, a transfer is scheduled. This command is
+valid for secondary zones. (#)
+.TP
+\fBzone\-retransfer\fP [\fIzone\fP\&...]
+Trigger a zone transfer from the zone\(aqs primary server. The server
+doesn\(aqt check the serial of the primary server\(aqs zone. This command is valid
+for secondary zones. (#)
+.TP
+\fBzone\-notify\fP [\fIzone\fP\&...]
+Trigger a NOTIFY message to all configured remotes. This can help in cases
+when previous NOTIFY had been lost or the secondary servers have been
+offline. (#)
+.TP
+\fBzone\-flush\fP [\fIzone\fP\&...] [\fB+outdir\fP \fIdirectory\fP]
+Trigger a zone journal flush to the configured zone file. If an output
+directory is specified, the current zone is immediately dumped (in the
+blocking mode) to a zone file in the specified directory. See
+\fI\%Notes\fP below about the directory permissions. (#)
+.TP
+\fBzone\-backup\fP [\fIzone\fP\&...] \fB+backupdir\fP \fIdirectory\fP [\fIfilter\fP\&...]
+Trigger a zone data and metadata backup to a specified directory.
+Available filters are \fB+zonefile\fP, \fB+journal\fP, \fB+timers\fP, \fB+kaspdb\fP,
+\fB+keysonly\fP, \fB+catalog\fP, \fB+quic\fP, and their negative counterparts
+\fB+nozonefile\fP, \fB+nojournal\fP, \fB+notimers\fP, \fB+nokaspdb\fP, \fB+nokeysonly\fP,
+\fB+nocatalog\fP, and \fB+noquic\fP\&. With these filters set, zone contents,
+zone\(aqs journal, zone\-related timers, zone\-related data in the KASP database
+together with keys (or keys without the KASP database), zone\(aqs catalog,
+and the server QUIC key and certificate, respectively, are backed up,
+or omitted from the backup. By default, filters \fB+zonefile\fP, \fB+timers\fP,
+\fB+kaspdb\fP, \fB+nokeysonly\fP, \fB+catalog\fP, \fB+quic\fP, and \fB+nojournal\fP
+are set for backup. The same defaults are set for restore, with the only
+difference being \fB+noquic\fP\&. Setting a filter for an item doesn\(aqt change
+default settings for other items. If zone flushing is disabled, the original
+zone file is backed up instead of writing out zone contents to a file.
+When backing\-up a catalog zone, it is recommended to prevent ongoing changes
+to it by use of \fBzone\-freeze\fP\&.
+See \fI\%Notes\fP below about the directory permissions. (#)
+.TP
+\fBzone\-restore\fP [\fIzone\fP\&...] \fB+backupdir\fP \fIdirectory\fP [\fIfilter\fP\&...]
+Trigger a zone data and metadata restore from a specified backup directory.
+Optional filters are equivalent to the same filters of \fBzone\-backup\fP\&.
+Restore from backups created by Knot DNS releases prior to 3.1 is possible
+with the force option. See \fI\%Notes\fP below about the directory
+permissions. (#)
+.TP
+\fBzone\-sign\fP [\fIzone\fP\&...]
+Trigger a DNSSEC re\-sign of the zone. Existing signatures will be dropped.
+This command is valid for zones with DNSSEC signing enabled. (#)
+.TP
+\fBzone\-keys\-load\fP [\fIzone\fP\&...]
+Trigger a load of DNSSEC keys and other signing material from KASP database
+(which might have been altered manually). If suitable, re\-sign the zone
+afterwards (keeping valid signatures intact). (#)
+.TP
+\fBzone\-key\-rollover\fP \fIzone\fP \fIkey_type\fP
+Trigger immediate key rollover. Publish new key and start a key rollover,
+even when the key has a lifetime to go. Key type can be \fBksk\fP (also for CSK)
+or \fBzsk\fP\&. This command is valid for zones with DNSSEC signing and automatic
+key management enabled. Note that complete key rollover consists of several steps
+and the blocking mode relates to the initial one only! (#)
+.TP
+\fBzone\-ksk\-submitted\fP \fIzone\fP\&...
+Use when the zone\(aqs KSK rollover is in submission phase. By calling this command
+the user confirms manually that the parent zone contains DS record for the new
+KSK in submission phase and the old KSK can be retired. (#)
+.TP
+\fBzone\-freeze\fP [\fIzone\fP\&...]
+Trigger a zone freeze. All running events will be finished and all new and pending
+(planned) zone\-changing events (load, refresh, update, flush, and DNSSEC signing)
+will be held up until the zone is thawed. (#)
+.TP
+\fBzone\-thaw\fP [\fIzone\fP\&...]
+Trigger dismissal of zone freeze. (#)
+.TP
+\fBzone\-xfr\-freeze\fP [\fIzone\fP\&...]
+Temporarily disable outgoing AXFR/IXFR for the zone(s). (#)
+.TP
+\fBzone\-xfr\-thaw\fP [\fIzone\fP\&...]
+Dismiss outgoing XFR freeze. (#)
+.TP
+\fBzone\-read\fP \fIzone\fP [\fIowner\fP [\fItype\fP]]
+Get zone data that are currently being presented.
+.TP
+\fBzone\-begin\fP \fIzone\fP\&...
+Begin a zone transaction.
+.TP
+\fBzone\-commit\fP \fIzone\fP\&...
+Commit the zone transaction. All changes are applied to the zone.
+.TP
+\fBzone\-abort\fP \fIzone\fP\&...
+Abort the zone transaction. All changes are discarded.
+.TP
+\fBzone\-diff\fP \fIzone\fP
+Get zone changes within the transaction.
+.TP
+\fBzone\-get\fP \fIzone\fP [\fIowner\fP [\fItype\fP]]
+Get zone data within the transaction.
+.TP
+\fBzone\-set\fP \fIzone\fP \fIowner\fP [\fIttl\fP] \fItype\fP \fIrdata\fP
+Add zone record within the transaction. The first record in a rrset
+requires a ttl value specified.
+.TP
+\fBzone\-unset\fP \fIzone\fP \fIowner\fP [\fItype\fP [\fIrdata\fP]]
+Remove zone data within the transaction.
+.TP
+\fBzone\-purge\fP \fIzone\fP\&... [\fB+orphan\fP] [\fIfilter\fP\&...]
+Purge zone data, zone file, journal, timers, and/or KASP data of specified zones.
+Available filters are \fB+expire\fP, \fB+zonefile\fP, \fB+journal\fP, \fB+timers\fP,
+\fB+kaspdb\fP, and \fB+catalog\fP\&. If no filter is specified, all filters are enabled.
+If the zone is no longer configured, add \fB+orphan\fP parameter (zone file cannot
+be purged in this case). When purging orphans, always check the server log for
+possible errors. For proper operation, it\(aqs necessary to prevent ongoing changes
+to the zone and triggering of zone related events during purge; use of
+\fBzone\-freeze\fP is advisable. This command always requires the force option. (#)
+.TP
+\fBzone\-stats\fP \fIzone\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]]
+Show zone statistics counter(s). To print also counters with value 0, use
+force option.
+.TP
+\fBconf\-init\fP
+Initialize the configuration database. If the database doesn\(aqt exist yet,
+execute this command as an intended user to ensure the server is permitted
+to access the database (e.g. \fIsudo \-u knot knotc conf\-init\fP). (*)
+.TP
+\fBconf\-check\fP
+Check the server configuration. (*)
+.TP
+\fBconf\-import\fP \fIfilename\fP [+nopurge]
+Import a configuration file into the configuration database. If the database
+doesn\(aqt exist yet, execute this command as an intended user to ensure the server
+is permitted to access the database (e.g. \fIsudo \-u knot knotc conf\-import ...\fP).
+An optional filter \fB+nopurge\fP prevents possibly existing configuration
+database from purging before the import itself.
+Also ensure the server is not using the configuration database at the same time! (*)
+.TP
+\fBconf\-export\fP [\fIfilename\fP]
+Export the configuration database into a config file or stdout. (*)
+.TP
+\fBconf\-list\fP [\fIitem\fP]
+List the configuration database sections or section items.
+.TP
+\fBconf\-read\fP [\fIitem\fP]
+Read the item from the active configuration database.
+.TP
+\fBconf\-begin\fP
+Begin a writing configuration database transaction. Only one transaction
+can be opened at a time.
+.TP
+\fBconf\-commit\fP
+Commit the configuration database transaction.
+.TP
+\fBconf\-abort\fP
+Rollback the configuration database transaction.
+.TP
+\fBconf\-diff\fP [\fIitem\fP]
+Get the item difference in the transaction.
+.TP
+\fBconf\-get\fP [\fIitem\fP]
+Get the item data from the transaction.
+.TP
+\fBconf\-set\fP \fIitem\fP [\fIdata\fP\&...]
+Set the item data in the transaction.
+.TP
+\fBconf\-unset\fP [\fIitem\fP] [\fIdata\fP\&...]
+Unset the item data in the transaction.
+.UNINDENT
+.SS Notes
+.sp
+Empty or \fB\-\-\fP \fIzone\fP parameter means all zones or all zones with a transaction.
+.sp
+Use \fB@\fP \fIowner\fP to denote the zone name.
+.sp
+Type \fIitem\fP parameter in the form of \fIsection\fP[\fB[\fP\fIid\fP\fB]\fP][\fB\&.\fP\fIname\fP].
+.sp
+(*) indicates a local operation which requires a configuration.
+.sp
+(#) indicates an optionally blocking operation.
+.sp
+The \fB\-b\fP and \fB\-f\fP options can be placed right after the command name.
+.sp
+Responses returned by \fIknotc\fP commands depend on the mode:
+.INDENT 0.0
+.IP \(bu 2
+In the blocking mode, \fIknotc\fP reports if an error occurred during processing
+of the command by the server. If an error is reported, a more detailed information
+about the failure can usually be found in the server log.
+.IP \(bu 2
+In the non\-blocking (default) mode, \fIknotc\fP doesn\(aqt report processing errors.
+The \fIOK\fP response to triggering commands means that the command has been successfully
+sent to the server. To verify if the operation succeeded, it\(aqs necessary to
+check the server log.
+.UNINDENT
+.sp
+Actions \fBzone\-flush\fP, \fBzone\-backup\fP, and \fBzone\-restore\fP are carried out by
+the \fIknotd\fP process. The directory specified must be accessible to the user account
+that \fIknotd\fP runs under and if the directory already exists, its permissions must be
+appropriate for that user account.
+.SS Interactive mode
+.sp
+The utility provides interactive mode with basic line editing functionality,
+command completion, and command history.
+.sp
+Interactive mode behavior can be customized in \fI~/.editrc\fP\&. Refer to
+\fBeditrc(5)\fP for details.
+.sp
+Command history is saved in \fI~/.knotc_history\fP\&.
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.SS Reload the whole server configuration
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knotc reload
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Flush the example.com and example.org zones
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knotc zone\-flush example.com example.org
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Get the current server configuration
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knotc conf\-read server
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Get the list of the current zones
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knotc conf\-read zone.domain
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Get the primary servers for the example.com zone
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knotc conf\-read \(aqzone[example.com].master\(aq
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Add example.org zone with a zonefile location
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knotc conf\-begin
+$ knotc conf\-set \(aqzone[example.org]\(aq
+$ knotc conf\-set \(aqzone[example.org].file\(aq \(aq/var/zones/example.org.zone\(aq
+$ knotc conf\-commit
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Get the SOA record for each configured zone
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knotc zone\-read \-\- @ SOA
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBknotd(8)\fP, \fBknot.conf(5)\fP, \fBeditrc(5)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/knotd.8in b/doc/man/knotd.8in
new file mode 100644
index 0000000..1d02cc8
--- /dev/null
+++ b/doc/man/knotd.8in
@@ -0,0 +1,93 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KNOTD" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+knotd \- Knot DNS server daemon
+.SH SYNOPSIS
+.sp
+\fBknotd\fP [\fIconfig_option\fP] [\fIoptions\fP]
+.SH DESCRIPTION
+.sp
+Knot DNS is a high\-performance authoritative DNS server. The \fIknotd\fP program is
+the DNS server daemon.
+.SS Config options
+.INDENT 0.0
+.TP
+\fB\-c\fP, \fB\-\-config\fP \fIfile\fP
+Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP).
+.TP
+\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP
+Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP).
+The default configuration database, if exists, has a preference to the default
+configuration file.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-m\fP, \fB\-\-max\-conf\-size\fP \fIMiB\fP
+Set maximum size of the configuration database
+(default is @conf_mapsize@ MiB, maximum 10000 MiB).
+.TP
+\fB\-s\fP, \fB\-\-socket\fP \fIpath\fP
+Use a remote control UNIX socket path (default is \fB@run_dir@/knot.sock\fP).
+.TP
+\fB\-d\fP, \fB\-\-daemonize\fP [\fIdirectory\fP]
+Run the server as a daemon. New root directory may be specified
+(default is \fB/\fP).
+.TP
+\fB\-v\fP, \fB\-\-verbose\fP
+Enable debug output.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.SS Signals
+.sp
+If the \fIknotd\fP process receives a SIGHUP signal, it reloads its configuration and
+reopens the log files, if they are configured. When \fIknotd\fP receives a SIGUSR1
+signal, it reloads all configured zones. Upon receiving a SIGINT signal, \fIknotd\fP
+exits.
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH SEE ALSO
+.sp
+\fBknot.conf(5)\fP, \fBknotc(8)\fP, \fBkeymgr(8)\fP,
+\fBkjournalprint(8)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/knsec3hash.1in b/doc/man/knsec3hash.1in
new file mode 100644
index 0000000..d9fa4a3
--- /dev/null
+++ b/doc/man/knsec3hash.1in
@@ -0,0 +1,96 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KNSEC3HASH" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+knsec3hash \- Simple utility to compute NSEC3 hash
+.SH SYNOPSIS
+.sp
+\fBknsec3hash\fP \fIsalt\fP \fIalgorithm\fP \fIiterations\fP \fIname\fP
+.sp
+\fBknsec3hash\fP \fIalgorithm\fP \fIflags\fP \fIiterations\fP \fIsalt\fP \fIname\fP
+.SH DESCRIPTION
+.sp
+This utility generates a NSEC3 hash for a given domain name and parameters of NSEC3 hash.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIsalt\fP
+Specifies a binary salt encoded as a hexadecimal string.
+.TP
+\fIalgorithm\fP
+Specifies a hashing algorithm by number. Currently, the only supported algorithm is SHA\-1 (number 1).
+.TP
+\fIiterations\fP
+Specifies the number of additional iterations of the hashing algorithm.
+.TP
+\fIname\fP
+Specifies the domain name to be hashed.
+.TP
+\fIflags\fP
+Specifies NSEC3 flags as an unsigned integer.
+.UNINDENT
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knsec3hash 1 0 10 c01dcafe knot\-dns.cz
+7PTVGE7QV67EM61ROS9238P5RAKR2DM7 (salt=c01dcafe, hash=1, iterations=10)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knsec3hash \- 1 0 net
+A1RT98BS5QGC9NFI51S9HCI47ULJG6JH (salt=\-, hash=1, iterations=0)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fI\%RFC 5155\fP – DNS Security (DNSSEC) Hashed Authenticated Denial of Existence.
+.sp
+\fBknotc(8)\fP, \fBknotd(8)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/knsupdate.1in b/doc/man/knsupdate.1in
new file mode 100644
index 0000000..ed34dd2
--- /dev/null
+++ b/doc/man/knsupdate.1in
@@ -0,0 +1,218 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KNSUPDATE" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+knsupdate \- Dynamic DNS update utility
+.SH SYNOPSIS
+.sp
+\fBknsupdate\fP [\fIoptions\fP] [\fIfilename\fP]
+.SH DESCRIPTION
+.sp
+This utility sends Dynamic DNS update messages to a DNS server. Update content
+is read from a file (if the parameter \fIfilename\fP is given) or from the standard
+input.
+.sp
+The format of updates is textual and is made up of commands. Every command is
+placed on the separate line of the input. Lines starting with a semicolon are
+comments and are not processed.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIfilename\fP
+Path to the file with knsupdate commands.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-d\fP
+Enable debug messages.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-k\fP \fIkeyfile\fP
+Use the TSIG key stored in a file \fIkeyfile\fP to authenticate the request. The
+file should contain the key in the same format, which is accepted by the
+\fB\-y\fP option.
+.TP
+\fB\-p\fP \fIport\fP
+Set the port to use for connections to the server (if not explicitly specified
+in the update). The default is 53.
+.TP
+\fB\-r\fP \fIretries\fP
+The number of retries for UDP requests. The default is 3.
+.TP
+\fB\-t\fP \fItimeout\fP
+The total timeout (for all UDP update tries) of the update request in seconds.
+The default is 12. If set to zero, the timeout is infinite.
+.TP
+\fB\-v\fP
+Use a TCP connection.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.TP
+\fB\-y\fP [\fIalg\fP:]\fIname\fP:\fIkey\fP
+Use the TSIG key with a name \fIname\fP to authenticate the request. The \fIalg\fP
+part specifies the algorithm (the default is hmac\-sha256) and \fIkey\fP specifies
+the shared secret encoded in Base64.
+.UNINDENT
+.SS Commands
+.INDENT 0.0
+.TP
+\fBserver\fP \fIname\fP [\fIport\fP]
+Specifies a receiving server of the dynamic update message. The \fIname\fP parameter
+can be either a host name or an IP address. If the \fIport\fP is not specified,
+the default port is used. The default port value can be controlled using
+the \fB\-p\fP program option.
+.TP
+\fBlocal\fP \fIaddress\fP [\fIport\fP]
+Specifies outgoing \fIaddress\fP and \fIport\fP\&. If no local is specified, the
+address and port are set by the system automatically. The default port number
+is 0.
+.TP
+\fBzone\fP \fIname\fP
+Specifies that all updates are done within a zone \fIname\fP\&. The zone name doesn\(aqt
+have a default and must be set explicitly.
+.TP
+\fBorigin\fP \fIname\fP
+Specifies fully qualified domain name suffix which is appended to non\-fqd
+owners in update commands. The default is the terminal label (\fB\&.\fP).
+.TP
+\fBclass\fP \fIname\fP
+Sets \fIname\fP as the default class for all updates. If not used, the default
+class is IN.
+.TP
+\fBttl\fP \fIvalue\fP
+Sets \fIvalue\fP as the default TTL (in seconds). If not used, the default value
+is 3600.
+.TP
+\fBkey\fP [\fIalg\fP:]\fIname\fP \fIkey\fP
+Specifies the TSIG \fIkey\fP named \fIname\fP to authenticate the request. An optional
+\fIalg\fP algorithm can be specified. This command has the same effect as
+the program option \fB\-y\fP\&.
+.TP
+[\fBprereq\fP] \fBnxdomain\fP \fIname\fP
+Adds a prerequisite for a non\-existing record owned by \fIname\fP\&.
+.TP
+[\fBprereq\fP] \fByxdomain\fP \fIname\fP
+Adds a prerequisite for an existing record owned by \fIname\fP\&.
+.TP
+[\fBprereq\fP] \fBnxrrset\fP \fIname\fP [\fIclass\fP] \fItype\fP
+Adds a prerequisite for a non\-existing record of the \fItype\fP owned by \fIname\fP\&.
+Internet \fIclass\fP is expected.
+.TP
+[\fBprereq\fP] \fByxrrset\fP \fIname\fP [\fIclass\fP] \fItype\fP [\fIdata\fP]
+Adds a prerequisite for an existing record of the \fItype\fP owned by \fIname\fP
+with optional \fIdata\fP\&. Internet \fIclass\fP is expected.
+.TP
+[\fBupdate\fP] \fBadd\fP \fIname\fP [\fIttl\fP] [\fIclass\fP] \fItype\fP \fIdata\fP
+Adds a request to add a new resource record into the zone.
+Please note that if the \fIname\fP is not fully qualified domain name, the
+current origin name is appended to it.
+.TP
+[\fBupdate\fP] \fBdel\fP[\fBete\fP] \fIname\fP [\fIttl\fP] [\fIclass\fP] [\fItype\fP] [\fIdata\fP]
+Adds a request to remove all (or matching \fIclass\fP, \fItype\fP or \fIdata\fP)
+resource records from the zone. There is the same requirement for the \fIname\fP
+parameter as in \fBupdate add\fP command. The \fIttl\fP item is ignored.
+.TP
+\fBshow\fP
+Displays current content of the update message.
+.TP
+\fBsend\fP
+Sends the current update message and cleans the list of updates.
+.TP
+\fBanswer\fP
+Displays the last answer from the server.
+.TP
+\fBdebug\fP
+Enable debugging. This command has the same meaning as the \fB\-d\fP program option.
+.TP
+\fBexit\fP
+End the program.
+.UNINDENT
+.SH NOTES
+.sp
+Options \fB\-k\fP and \fB\-y\fP can not be used simultaneously.
+.sp
+Neither \fItsig\-keygen(8)\fP nor \fIdnssec\-keygen(1)\fP keyfile formats are supported.
+Use \fBkeymgr(8)\fP to construct a string for \fB\-y\fP or the file passed to \fB\-k\fP\&.
+.sp
+Zone name/server guessing is not supported if the zone name/server is not specified.
+.sp
+An empty line doesn\(aqt send the update.
+.SS Interactive mode
+.sp
+The utility provides interactive mode with basic line editing functionality,
+command completion, and command history.
+.sp
+Interactive mode behavior can be customized in \fI~/.editrc\fP\&. Refer to
+\fBeditrc(5)\fP for details.
+.sp
+Command history is saved in \fI~/.knsupdate_history\fP\&.
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.INDENT 0.0
+.IP 1. 3
+Send one update of the zone example.com to the server 192.168.1.1. The update
+contains two new records:
+.INDENT 3.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+$ knsupdate
+knsupdate> server 192.168.1.1
+knsupdate> zone example.com.
+knsupdate> origin example.com.
+knsupdate> ttl 3600
+knsupdate> add test1.example.com. 7200 A 192.168.2.2
+knsupdate> add test2 TXT \(dqhello\(dq
+knsupdate> show
+knsupdate> send
+knsupdate> answer
+knsupdate> exit
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBkdig(1)\fP, \fBkhost(1)\fP, \fBkeymgr(8)\fP, \fBeditrc(5)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/kxdpgun.8in b/doc/man/kxdpgun.8in
new file mode 100644
index 0000000..243f4f4
--- /dev/null
+++ b/doc/man/kxdpgun.8in
@@ -0,0 +1,278 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KXDPGUN" "8" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+kxdpgun \- XDP-powered DNS benchmarking tool
+.SH SYNOPSIS
+.sp
+\fBkxdpgun\fP [\fIoptions\fP] \fB\-i\fP \fIfilename\fP \fItarget_IP\fP
+.SH DESCRIPTION
+.sp
+Powerful generator of DNS traffic, sending and receiving packets through XDP.
+.sp
+Queries are generated according to a textual file which is read sequentially
+in a loop until a configured duration elapses. The order of queries is not
+guaranteed. Responses are received (unless disabled) and counted, but not
+checked against queries.
+.sp
+The number of parallel threads is autodetected according to the number of queues
+configured for the network interface.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIfilename\fP
+Path to the queries file. See the description below regarding the file format.
+.TP
+\fItarget_IP\fP
+The IPv4 or IPv6 address of remote destination.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-t\fP, \fB\-\-duration\fP \fIseconds\fP
+Duration of traffic generation, specified as a decimal number in seconds
+(default is 5.0).
+.TP
+\fB\-T\fP, \fB\-\-tcp\fP[\fB=\fP\fIdebug_mode\fP]
+Send queries over TCP. See the list of optional debug modes below.
+.TP
+\fB\-U\fP, \fB\-\-quic\fP[\fB=\fP\fIdebug_mode\fP]
+Send queries over QUIC. See the list of optional debug modes below.
+.TP
+\fB\-Q\fP, \fB\-\-qps\fP \fIqueries\fP
+Number of queries\-per\-second (approximately) to be sent (default is 1000).
+The program is not optimized for low speeds at which it may lose
+communication packets. The recommended minimum speed is 2 packets per thread
+(Rx/Tx queue).
+.TP
+\fB\-b\fP, \fB\-\-batch\fP \fIsize\fP
+Send more queries in a batch. Improves QPS but may affect the counterpart\(aqs
+packet loss (default is 10 for UDP and 1 for TCP/QUIC).
+.TP
+\fB\-r\fP, \fB\-\-drop\fP
+Drop incoming responses. Improves QPS, but disables response statistics.
+.TP
+\fB\-p\fP, \fB\-\-port\fP \fInumber\fP
+Remote destination port (default is 53 for UDP/TCP, 853 for QUIC).
+.TP
+\fB\-F\fP, \fB\-\-affinity\fP \fIcpu_spec\fP
+CPU affinity for all threads specified in the format [<cpu_start>][s<cpu_step>],
+where <cpu_start> is the CPU ID for the first thread and <cpu_step> is the
+CPU ID increment for next thread (default is 0s1).
+.TP
+\fB\-i\fP, \fB\-\-infile\fP \fIfilename\fP
+Path to a file with query templates.
+.TP
+\fB\-I\fP, \fB\-\-interface\fP \fIinterface\fP
+Network interface for outgoing communication. This can be useful in situations
+when the interfaces are in a bond for example.
+.TP
+\fB\-l\fP, \fB\-\-local\fP \fIlocalIP\fP[\fB/\fP\fIprefix\fP]
+Override the auto\-detected source IP address. If an address range is specified
+instead, various IPs from the range will be used for different queries uniformly
+(address range not supported in the QUIC mode).
+.TP
+\fB\-L\fP, \fB\-\-mac\-local\fP
+Override auto\-detected local MAC address.
+.TP
+\fB\-R\fP, \fB\-\-mac\-remote\fP
+Override auto\-detected remote MAC address.
+.TP
+\fB\-v\fP, \fB\-\-vlan\fP \fIid\fP
+Add VLAN 802.1Q header with the given id. VLAN offloading should be disabled.
+.TP
+\fB\-e\fP, \fB\-\-edns\-size\fP \fIsize\fP
+EDNS UDP payload size, range 512\-4096 (default is 1232). Note that over XDP
+the maximum supported MTU is 1790.
+.TP
+\fB\-m\fP, \fB\-\-mode\fP \fImode\fP
+Set the XDP mode. Supported values are:
+.INDENT 7.0
+.IP \(bu 2
+\fBauto\fP (default) – the XDP mode is selected automatically to achieve
+the best performance, which means that native driver support is preferred
+over the generic one, and zero\-copy is used if available.
+.IP \(bu 2
+\fBcopy\fP – the XDP socket copy mode is forced even if zero\-copy
+is available. This can resolve various driver issues, but at the cost
+of lower performance.
+.IP \(bu 2
+\fBgeneric\fP – the generic XDP implementation is forced even if native
+implementation is available. This mode doesn\(aqt require support from the
+driver nor hardware, but offers the worst performance.
+.UNINDENT
+.TP
+\fB\-G\fP, \fB\-\-qlog\fP \fIpath\fP
+Generate qlog files in the directory specified by \fIpath\fP\&. The directory
+has to exist.
+.sp
+This option is ignored if not in the QUIC mode. The recommended usage is
+with \fB\-\-quic=R\fP or with low QPS. Otherwise, too many files are generated.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.SS Queries file format
+.sp
+Each line describes a query in the form:
+.sp
+\fIquery_name\fP \fIquery_type\fP [\fIflags\fP]
+.sp
+Where \fIquery_name\fP is a domain name to be queried, \fIquery_type\fP is a record type
+name, and \fIflags\fP is a single character:
+.sp
+\fBE\fP Send query with EDNS.
+.sp
+\fBD\fP Request DNSSEC (EDNS + DO flag).
+.SS TCP/QUIC debug modes
+.INDENT 0.0
+.TP
+\fB0\fP
+Perform full handshake for all connections (QUIC only).
+.TP
+\fB1\fP
+Just send SYN (Initial) and receive SYN\-ACK (Handshake).
+.TP
+\fB2\fP
+Perform TCP/QUIC handshake and don\(aqt send anything, allow close initiated by counterpart.
+.TP
+\fB3\fP
+Perform TCP/QUIC handshake and don\(aqt react further.
+.TP
+\fB5\fP
+Send incomplete query (N\-1 bytes) and don\(aqt react further.
+.TP
+\fB7\fP
+Send query and don\(aqt ACK the response or anything further.
+.TP
+\fB8\fP
+Don\(aqt close the connection and ignore close by counterpart.
+.TP
+\fB9\fP
+Operate normally except for not ACKing the final FIN+ACK (TCP only).
+.TP
+\fBR\fP
+Instead of opening a connection for each query, reuse connections.
+.UNINDENT
+.SS Signals
+.sp
+Sending USR1 signal to a running process triggers current statistics dump
+to the standard output.
+.SH NOTES
+.sp
+Linux kernel 4.18+ is required.
+.sp
+The utility has to be executed under root or with these capabilities:
+CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN, CAP_IPC_LOCK, and CAP_SYS_RESOURCE
+(Linux < 5.11).
+.sp
+The utility allocates source UDP/TCP ports from the range 2000\-65535.
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH EXAMPLES
+.sp
+Manually created queries file:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+abc6.example.com. AAAA
+nxdomain.example.com. A
+notzone. A
+a.example.com. NS E
+ab.example.com. A D
+abcd.example.com. DS D
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Queries file generated from a zone file (Knot DNS format):
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+cat ZONE_FILE | awk \(dq{print \e$1,\e$3}\(dq | grep \-E \(dq(NS|DS|A|AAAA|PTR|MX|SOA)$\(dq | sort \-u \-R > queries.txt
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+Basic usage:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# kxdpgun \-i ~/queries.txt 2001:DB8::1
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fIUsing UDP with increased batch size\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# kxdpgun \-t 20 \-Q 1000000 \-i ~/queries.txt \-b 20 \-p 8853 192.0.2.1
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fIUsing TCP\fP:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# kxdpgun \-t 20 \-Q 100000 \-i ~/queries.txt \-T \-p 8853 192.0.2.1
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBkdig(1)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/kzonecheck.1in b/doc/man/kzonecheck.1in
new file mode 100644
index 0000000..380c41f
--- /dev/null
+++ b/doc/man/kzonecheck.1in
@@ -0,0 +1,91 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KZONECHECK" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+kzonecheck \- Knot DNS zone check tool
+.SH SYNOPSIS
+.sp
+\fBkzonecheck\fP [\fIoptions\fP] \fIfilename\fP
+.SH DESCRIPTION
+.sp
+The utility checks zone file syntax and runs semantic checks on the zone
+content. The executed checks are the same as the checks run by the Knot
+DNS server.
+.sp
+Please, refer to the \fBsemantic\-checks\fP configuration option in
+\fBknot.conf(5)\fP for the full list of available semantic checks.
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIfilename\fP
+Path to the zone file to be checked. For reading from \fBstdin\fP use \fB/dev/stdin\fP
+or just \fB\-\fP\&.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-o\fP, \fB\-\-origin\fP \fIorigin\fP
+Zone origin. If not specified, the origin is determined from the file name
+(possibly removing the \fB\&.zone\fP suffix).
+.TP
+\fB\-d\fP, \fB\-\-dnssec\fP \fBon\fP|\fBoff\fP
+Also check DNSSEC\-related records. The default is to decide based on the
+existence of a RRSIG for SOA.
+.TP
+\fB\-t\fP, \fB\-\-time\fP \fItime\fP
+Current time specification. Use UNIX timestamp, YYYYMMDDHHmmSS
+format, or [+/\-]\fItime\fP[unit] format, where unit can be \fBY\fP, \fBM\fP,
+\fBD\fP, \fBh\fP, \fBm\fP, or \fBs\fP\&. Default is current UNIX timestamp.
+.TP
+\fB\-p\fP, \fB\-\-print\fP
+Print the zone on stdout.
+.TP
+\fB\-v\fP, \fB\-\-verbose\fP
+Enable debug output.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH SEE ALSO
+.sp
+\fBknotd(8)\fP, \fBknot.conf(5)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man/kzonesign.1in b/doc/man/kzonesign.1in
new file mode 100644
index 0000000..147e112
--- /dev/null
+++ b/doc/man/kzonesign.1in
@@ -0,0 +1,95 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.TH "KZONESIGN" "1" "@RELEASE_DATE@" "@VERSION@" "Knot DNS"
+.SH NAME
+kzonesign \- DNSSEC signing utility
+.SH SYNOPSIS
+.sp
+\fBkzonesign\fP [\fIconfig_option\fP] [\fIoptions\fP] \fIzone_name\fP
+.SH DESCRIPTION
+.sp
+This utility reads the zone\(aqs zone file, signs the zone according to given
+configuration, and writes the signed zone file back. An alternative mode
+is DNSSEC validation of the given zone. The signing or validation
+can run in parallel if enabled in the configuration (see policy.signing\-threads
+and zone.adjust\-threads).
+.SS Parameters
+.INDENT 0.0
+.TP
+\fIzone_name\fP
+A name of the zone to be signed.
+.UNINDENT
+.SS Config options
+.INDENT 0.0
+.TP
+\fB\-c\fP, \fB\-\-config\fP \fIfile\fP
+Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP).
+.TP
+\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP
+Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP).
+The default configuration database, if exists, has a preference to the default
+configuration file.
+.UNINDENT
+.SS Options
+.INDENT 0.0
+.TP
+\fB\-o\fP, \fB\-\-outdir\fP \fIdir_name\fP
+Write the output zone file to the specified directory instead of the configured one.
+.TP
+\fB\-r\fP, \fB\-\-rollover\fP
+Allow key roll\-overs and NSEC3 re\-salt. In order to finish possible KSK submission,
+set the KSK\(aqs \fBactive\fP timestamp to now (\fB+0\fP) using \fI\%keymgr\fP\&.
+.TP
+\fB\-v\fP, \fB\-\-verify\fP
+Instead of (re\-)signing the zone, just verify that the zone is correctly signed.
+.TP
+\fB\-t\fP, \fB\-\-time\fP \fItimestamp\fP
+Sign/verify the zone (and roll the keys if necessary) as if it was at the time
+specified by timestamp.
+.TP
+\fB\-h\fP, \fB\-\-help\fP
+Print the program help.
+.TP
+\fB\-V\fP, \fB\-\-version\fP
+Print the program version.
+.UNINDENT
+.SH EXIT VALUES
+.sp
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+.SH SEE ALSO
+.sp
+\fBknot.conf(5)\fP, \fBkeymgr(8)\fP\&.
+.SH AUTHOR
+CZ.NIC Labs <https://www.knot-dns.cz>
+.SH COPYRIGHT
+Copyright 2010–2024, CZ.NIC, z.s.p.o.
+.\" Generated by docutils manpage writer.
+.
diff --git a/doc/man_kcatalogprint.rst b/doc/man_kcatalogprint.rst
new file mode 100644
index 0000000..cccc641
--- /dev/null
+++ b/doc/man_kcatalogprint.rst
@@ -0,0 +1,54 @@
+.. highlight:: none
+
+``kcatalogprint`` – Knot DNS catalog print utility
+==================================================
+
+Synopsis
+--------
+
+:program:`kcatalogprint` [*config_option*] [*options*]
+
+Description
+-----------
+
+The program prints zone catalog stored in a catalog database.
+
+Config options
+..............
+
+**-c**, **--config** *file*
+ Use a textual configuration file (default is :file:`@config_dir@/knot.conf`).
+
+**-C**, **--confdb** *directory*
+ Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`).
+ The default configuration database, if exists, has a preference to the default
+ configuration file.
+
+**-D**, **--dir** *path*
+ Use specified catalog database path and default configuration.
+
+Options
+.......
+
+**-a**, **--catalog**
+ Filter the output by catalog zone name.
+
+**-m**, **--member**
+ Filter the output by member zone name.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+See Also
+--------
+
+:manpage:`knotd(8)`, :manpage:`knot.conf(5)`.
diff --git a/doc/man_kdig.rst b/doc/man_kdig.rst
new file mode 100644
index 0000000..4457b68
--- /dev/null
+++ b/doc/man_kdig.rst
@@ -0,0 +1,396 @@
+.. highlight:: none
+
+``kdig`` – Advanced DNS lookup utility
+======================================
+
+Synopsis
+--------
+
+:program:`kdig` [*common-settings*] [*query* [*settings*]]...
+
+:program:`kdig` **-h**
+
+Description
+-----------
+
+This utility sends one or more DNS queries to a nameserver. Each query can have
+individual *settings*, or it can be specified globally via *common-settings*,
+which must precede *query* specification.
+
+Parameters
+..........
+
+*query*
+ *name* | **-q** *name* | **-x** *address* | **-G** *tapfile*
+
+*common-settings*, *settings*
+ [*query_class*] [*query_type*] [**@**\ *server*]... [*options*]
+
+*name*
+ Is a domain name that is to be looked up.
+
+*server*
+ Is a domain name or an IPv4 or IPv6 address of the nameserver to send a query
+ to. An additional port can be specified using address:port ([address]:port
+ for IPv6 address), address@port, or address#port notation. A value which begins
+ with '/' character is considered an absolute UNIX socket path. If no server is
+ specified, the servers from :file:`/etc/resolv.conf` are used.
+
+If no arguments are provided, :program:`kdig` sends NS query for the root
+zone.
+
+Query classes
+.............
+
+A *query_class* can be either a DNS class name (IN, CH) or generic class
+specification **CLASS**\ *XXXXX* where *XXXXX* is a corresponding decimal
+class number. The default query class is IN.
+
+Query types
+...........
+
+A *query_type* can be either a DNS resource record type
+(A, AAAA, NS, SOA, DNSKEY, ANY, etc.) or one of the following:
+
+**TYPE**\ *XXXXX*
+ Generic query type specification where *XXXXX* is a corresponding decimal
+ type number.
+
+**AXFR**
+ Full zone transfer request.
+
+**IXFR=**\ *serial*
+ Incremental zone transfer request for specified SOA serial number
+ (i.e. all zone updates since the specified zone version are to be returned).
+
+**NOTIFY=**\ *serial*
+ Notify message with a SOA serial hint specified.
+
+**NOTIFY**
+ Notify message with a SOA serial hint unspecified.
+
+The default query type is A.
+
+Options
+.......
+
+**-4**
+ Use the IPv4 protocol only.
+
+**-6**
+ Use the IPv6 protocol only.
+
+**-b** *address*
+ Set the source IP address of the query to *address*. The address must be a
+ valid address for local interface or :: or 0.0.0.0. An optional port
+ can be specified in the same format as the *server* value.
+
+**-c** *class*
+ An explicit *query_class* specification. See possible values above.
+
+**-d**
+ Enable debug messages.
+
+**-h**, **--help**
+ Print the program help.
+
+**-k** *keyfile*
+ Use the TSIG key stored in a file *keyfile* to authenticate the request. The
+ file must contain the key in the same format as accepted by the
+ **-y** option.
+
+**-p** *port*
+ Set the nameserver port number or service name to send a query to. The default
+ port is 53.
+
+**-q** *name*
+ Set the query name. An explicit variant of *name* specification. If no *name*
+ is provided, empty question section is set.
+
+**-t** *type*
+ An explicit *query_type* specification. See possible values above.
+
+**-V**, **--version**
+ Print the program version.
+
+**-x** *address*
+ Send a reverse (PTR) query for IPv4 or IPv6 *address*. The correct name, class
+ and type is set automatically.
+
+**-y** [*alg*:]\ *name*:*key*
+ Use the TSIG key named *name* to authenticate the request. The *alg*
+ part specifies the algorithm (the default is hmac-sha256) and *key* specifies
+ the shared secret encoded in Base64.
+
+**-E** *tapfile*
+ Export a dnstap trace of the query and response messages received to the
+ file *tapfile*.
+
+**-G** *tapfile*
+ Generate message output from a previously saved dnstap file *tapfile*.
+
+**+**\ [\ **no**\ ]\ **multiline**
+ Wrap long records to more lines and improve human readability.
+
+**+**\ [\ **no**\ ]\ **short**
+ Show record data only.
+
+**+**\ [\ **no**\ ]\ **generic**
+ Use the generic representation format when printing resource record types
+ and data.
+
+**+**\ [\ **no**\ ]\ **crypto**
+ Display the DNSSEC keys and signatures values in base64, instead of omitting them.
+
+**+**\ [\ **no**\ ]\ **aaflag**
+ Set the AA flag.
+
+**+**\ [\ **no**\ ]\ **tcflag**
+ Set the TC flag.
+
+**+**\ [\ **no**\ ]\ **rdflag**
+ Set the RD flag.
+
+**+**\ [\ **no**\ ]\ **recurse**
+ Same as **+**\ [\ **no**\ ]\ **rdflag**
+
+**+**\ [\ **no**\ ]\ **raflag**
+ Set the RA flag.
+
+**+**\ [\ **no**\ ]\ **zflag**
+ Set the zero flag bit.
+
+**+**\ [\ **no**\ ]\ **adflag**
+ Set the AD flag.
+
+**+**\ [\ **no**\ ]\ **cdflag**
+ Set the CD flag.
+
+**+**\ [\ **no**\ ]\ **dnssec**
+ Set the DO flag.
+
+**+**\ [\ **no**\ ]\ **all**
+ Show all packet sections.
+
+**+**\ [\ **no**\ ]\ **qr**
+ Show the query packet.
+
+**+**\ [\ **no**\ ]\ **header**
+ Show the packet header.
+
+**+**\ [\ **no**\ ]\ **comments**
+ Show commented section names.
+
+**+**\ [\ **no**\ ]\ **opt**
+ Show the EDNS pseudosection.
+
+**+**\ [\ **no**\ ]\ **opttext**
+ Try to show unknown EDNS options as text.
+
+**+**\ [\ **no**\ ]\ **optpresent**
+ Show EDNS in presentation format according to the specification in version
+ `draft-peltan-edns-presentation-format-01 <https://www.ietf.org/archive/id/draft-peltan-edns-presentation-format-01.html>`_.
+
+**+**\ [\ **no**\ ]\ **question**
+ Show the question section.
+
+**+**\ [\ **no**\ ]\ **answer**
+ Show the answer section.
+
+**+**\ [\ **no**\ ]\ **authority**
+ Show the authority section.
+
+**+**\ [\ **no**\ ]\ **additional**
+ Show the additional section.
+
+**+**\ [\ **no**\ ]\ **tsig**
+ Show the TSIG pseudosection.
+
+**+**\ [\ **no**\ ]\ **stats**
+ Show trailing packet statistics.
+
+**+**\ [\ **no**\ ]\ **class**
+ Show the DNS class.
+
+**+**\ [\ **no**\ ]\ **ttl**
+ Show the TTL value.
+
+**+**\ [\ **no**\ ]\ **tcp**
+ Use the TCP protocol (default is UDP for standard query and TCP for AXFR/IXFR).
+
+**+**\ [\ **no**\ ]\ **fastopen**
+ Use TCP Fast Open.
+
+**+**\ [\ **no**\ ]\ **ignore**
+ Don't use TCP automatically if a truncated reply is received.
+
+**+**\ [\ **no**\ ]\ **keepopen**
+ Keep TCP connection open for the following query if it has the same connection
+ configuration. This applies to +tcp, +tls, and +https operations. The connection
+ is considered in the context of a single kdig call only.
+
+**+**\ [\ **no**\ ]\ **tls**
+ Use TLS with the Opportunistic privacy profile (:rfc:`7858#section-4.1`).
+
+**+**\ [\ **no**\ ]\ **tls-ca**\[\ =\ *FILE*\]
+ Use TLS with a certificate validation. Certification authority certificates
+ are loaded from the specified PEM file (default is system certificate storage
+ if no argument is provided).
+ Can be specified multiple times. If the +tls-hostname option is not provided,
+ the name of the target server (if specified) is used for strict authentication.
+
+**+**\ [\ **no**\ ]\ **tls-pin**\ =\ *BASE64*
+ Use TLS with the Out-of-Band key-pinned privacy profile (:rfc:`7858#section-4.2`).
+ The PIN must be a Base64 encoded SHA-256 hash of the X.509 SubjectPublicKeyInfo.
+ Can be specified multiple times.
+
+**+**\ [\ **no**\ ]\ **tls-hostname**\ =\ *STR*
+ Use TLS with a remote server hostname check.
+
+**+**\ [\ **no**\ ]\ **tls-sni**\ =\ *STR*
+ Use TLS with a Server Name Indication.
+
+**+**\ [\ **no**\ ]\ **tls-keyfile**\ =\ *FILE*
+ Use TLS with a client keyfile.
+
+**+**\ [\ **no**\ ]\ **tls-certfile**\ =\ *FILE*
+ Use TLS with a client certfile.
+
+**+**\ [\ **no**\ ]\ **tls-ocsp-stapling**\[\ =\ *H*\]
+ Use TLS with a valid stapled OCSP response for the server certificate
+ (%u or specify hours). OCSP responses older than the specified period are
+ considered invalid.
+
+**+**\ [\ **no**\ ]\ **https**\[\ =\ *URL*\]
+ Use HTTPS (DNS-over-HTTPS) in wire format (:rfc:`1035#section-4.2.1`).
+ It is also possible to specify URL=\[authority\]\[/path\] where request
+ will be sent to. Any leading scheme and authority indicator (i.e. //) are ignored.
+ Authority might also be specified as the *server* (using the parameter `@`).
+ If *path* is specified and *authority* is missing, then the *server*
+ is used as authority together with the specified *path*.
+ Library *libnghttp2* is required.
+
+**+**\ [\ **no**\ ]\ **https-get**
+ Use HTTPS with HTTP/GET method instead of the default HTTP/POST method.
+ Library *libnghttp2* is required.
+
+**+**\ [\ **no**\ ]\ **quic**
+ Use QUIC (DNS-over-QUIC).
+
+**+**\ [\ **no**\ ]\ **nsid**
+ Request the nameserver identifier (NSID).
+
+**+**\ [\ **no**\ ]\ **bufsize**\ =\ *B*
+ Set EDNS buffer size in bytes (default is 4096 bytes).
+
+**+**\ [\ **no**\ ]\ **padding**\[\ =\ *B*\]
+ Use EDNS(0) padding option to pad queries, optionally to a specific
+ size. The default is to pad queries with a sensible amount when using
+ +tls, and not to pad at all when queries are sent without TLS. With
+ no argument (i.e., just +padding) pad every query with a sensible
+ amount regardless of the use of TLS. With +nopadding, never pad.
+
+**+**\ [\ **no**\ ]\ **alignment**\[\ =\ *B*\]
+ Align the query to B\-byte-block message using the EDNS(0) padding option
+ (default is no or 128 if no argument is specified).
+
+**+**\ [\ **no**\ ]\ **subnet**\ =\ *SUBN*
+ Set EDNS(0) client subnet SUBN=addr/prefix.
+
+**+**\ [\ **no**\ ]\ **edns**\[\ =\ *N*\]
+ Use EDNS version (default is 0).
+
+**+**\ [\ **no**\ ]\ **timeout**\ =\ *T*
+ Set the wait-for-reply interval in seconds (default is 5 seconds). This timeout
+ applies to each query attempt. Zero value or *notimeout* is interpreted as
+ infinity.
+
+**+**\ [\ **no**\ ]\ **retry**\ =\ *N*
+ Set the number (>=0) of UDP retries (default is 2). This doesn't apply to
+ AXFR/IXFR.
+
+**+**\ [\ **no**\ ]\ **expire**
+ Sets the EXPIRE EDNS option.
+
+**+**\ [\ **no**\ ]\ **cookie**\[\ =\ *HEX*\]
+ Attach EDNS(0) cookie to the query.
+
+**+**\ [\ **no**\ ]\ **badcookie**
+ Repeat a query with the correct cookie.
+
+**+**\ [\ **no**\ ]\ **ednsopt**\[\ =\ *CODE*\[:*HEX*\]\]
+ Send custom EDNS option. The *CODE* is EDNS option code in decimal, *HEX*
+ is an optional hex encoded string to use as EDNS option value. This argument
+ can be used multiple times. +noednsopt clears all EDNS options specified by
+ +ednsopt.
+
+**+**\ [\ **no**\ ]\ **proxy**\ =\ *SRC_ADDR*\[#\ *SRC_PORT*\]-*DST_ADDR*\[#\ *DST_PORT*\]
+ Add PROXYv2 header with the specified source and destination addresses to the query.
+ The default source port is 0 and destination port 53.
+
+**+**\ [\ **no**\ ]\ **json**
+ Use JSON for output encoding (RFC 8427).
+
+**+noidn**
+ Disable the IDN transformation to ASCII and vice versa. IDN support depends
+ on libidn availability during project building! If used in *common-settings*,
+ all IDN transformations are disabled. If used in the individual query *settings*,
+ transformation from ASCII is disabled on output for the particular query. Note
+ that IDN transformation does not preserve domain name letter case.
+
+Notes
+-----
+
+Options **-k** and **-y** can not be used simultaneously.
+
+Dnssec-keygen keyfile format is not supported. Use :manpage:`keymgr(8)` instead.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+1. Get A records for example.com::
+
+ $ kdig example.com A
+
+2. Perform AXFR for zone example.com from the server 192.0.2.1::
+
+ $ kdig example.com -t AXFR @192.0.2.1
+
+3. Get A records for example.com from 192.0.2.1 and reverse lookup for address
+ 2001:DB8::1 from 192.0.2.2. Both using the TCP protocol::
+
+ $ kdig +tcp example.com -t A @192.0.2.1 -x 2001:DB8::1 @192.0.2.2
+
+4. Get SOA record for example.com, use TLS, use system certificates, check
+ for specified hostname, check for certificate pin, and print additional
+ debug info::
+
+ $ kdig -d @185.49.141.38 +tls-ca +tls-host=getdnsapi.net \
+ +tls-pin=foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S= soa example.com
+
+5. DNS over HTTPS examples (various DoH implementations)::
+
+ $ kdig @1.1.1.1 +https example.com.
+ $ kdig @193.17.47.1 +https=/doh example.com.
+ $ kdig @8.8.4.4 +https +https-get example.com.
+ $ kdig @8.8.8.8 +https +tls-hostname=dns.google +fastopen example.com.
+
+6. More queries share one DoT connection::
+
+ $ kdig @1.1.1.1 +tls +keepopen abc.example.com A mail.example.com AAAA
+
+Files
+-----
+
+:file:`/etc/resolv.conf`
+
+See Also
+--------
+
+:manpage:`khost(1)`, :manpage:`knsupdate(1)`, :manpage:`keymgr(8)`.
diff --git a/doc/man_keymgr.rst b/doc/man_keymgr.rst
new file mode 100644
index 0000000..362790e
--- /dev/null
+++ b/doc/man_keymgr.rst
@@ -0,0 +1,300 @@
+.. highlight:: none
+
+``keymgr`` – Key management utility
+===================================
+
+Synopsis
+--------
+
+:program:`keymgr` [*config_option*] [*options*] *zone_name* *command*
+
+:program:`keymgr` [*config_option*] [-j] **-l**
+
+:program:`keymgr` **-t** *parameter*...
+
+Description
+-----------
+
+The :program:`keymgr` utility serves for manual key management in Knot DNS server.
+
+Functions for DNSSEC keys and KASP (Key And Signature Policy)
+management are provided.
+
+The DNSSEC and KASP configuration is stored in a so called KASP database.
+The database is backed by LMDB.
+
+Parameters
+..........
+
+*zone_name*
+ Name of the zone the command is executed for.
+
+Config options
+..............
+
+**-c**, **--config** *file*
+ Use a textual configuration file (default is :file:`@config_dir@/knot.conf`).
+
+**-C**, **--confdb** *directory*
+ Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`).
+ The default configuration database, if exists, has a preference to the default
+ configuration file.
+
+**-D**, **--dir** *path*
+ Use specified KASP database path and default configuration.
+
+Options
+.......
+
+**-t**, **--tsig** *tsig_name* [*tsig_algorithm* [*tsig_bits*]]
+ Generates a TSIG key for the given name. Optionally the key algorithm can
+ be specified by its :ref:`name<key_algorithm>` (default: hmac-sha256) and
+ a bit length of the key (default: optimal length given by algorithm).
+ The generated TSIG key is only displayed on `stdout`:
+ the command does not create a file, nor include the key in a keystore.
+
+**-e**, **--extended**
+ Extended output (listing of keys with full description).
+
+**-j**, **--json**
+ Print the zones or keys in JSON format.
+
+**-l**, **--list**
+ Print the list of zones that have at least one key stored in the configured KASP
+ database.
+
+**-x**, **--mono**
+ Don't generate colorized output.
+
+**-X**, **--color**
+ Force colorized output in the normal mode.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+.. NOTE::
+ Keymgr runs with the same user privileges as configured for :doc:`knotd<man_knotd>`.
+ For example, if keymgr is run as ``root``, but the configured :ref:`user<server_user>`
+ is ``knot``, it won't be able to read files (PEM files, KASP database, ...) readable
+ only by ``root``.
+
+Commands
+........
+
+**list** [*timestamp_format*]
+ Prints the list of key IDs and parameters of keys belonging to the zone.
+
+**generate** [*arguments*...]
+ Generates new DNSSEC key and stores it in KASP database. Prints the key ID.
+ This action takes some number of arguments (see below). Values for unspecified arguments are taken
+ from corresponding policy (if *-c* or *-C* options used) or from Knot policy defaults.
+
+**import-bind** *BIND_key_file*
+ Imports a BIND-style key into KASP database (converting it to PEM format).
+ Takes one argument: path to BIND key file (private or public, but both MUST exist).
+
+**import-pub** *BIND_pubkey_file*
+ Imports a public key into KASP database. This key won't be rolled over nor used for signing.
+ Takes one argument: path to BIND public key file.
+
+**import-pem** *PEM_file* [*arguments*...]
+ Imports a DNSSEC key from PEM file. The key parameters (same as for the generate action) need to be
+ specified (mainly algorithm, timers...) because they are not contained in the PEM format.
+
+**import-pkcs11** *key_id* [*arguments*...]
+ Imports a DNSSEC key from PKCS #11 storage. The key parameters (same as for the generate action) need to be
+ specified (mainly algorithm, timers...) because they are not available. In fact, no key
+ data is imported, only KASP database metadata is created.
+
+**nsec3-salt** [*new_salt*]
+ Prints the current NSEC3 salt used for signing. If *new_salt* is specified, the salt is overwritten.
+ The salt is printed and expected in hexadecimal, or dash if empty.
+
+**local-serial** [*new_serial*]
+ Print SOA serial stored in KASP database when using on-secondary DNSSEC signing.
+ If *new_serial* is specified, the serial is overwritten. After updating the serial, expire the zone
+ (**zone-purge +expire +zonefile +journal**) if the server is running, or remove corresponding zone file
+ and journal contents if the server is stopped.
+
+**master-serial** [*new_serial*]
+ Print SOA serial of the remote master stored in KASP database when using on-secondary DNSSEC signing.
+ If *new_serial* is specified, the serial is overwritten (not recommended).
+
+**set** *key_spec* [*arguments*...]
+ Changes a timing argument (or ksk/zsk) of an existing key to a new value. *Key_spec* is either the
+ key tag or a prefix of the key ID, with an optional *[id=|keytag=]* prefix; *arguments*
+ are like for **generate**, but just the related ones.
+
+**ds** [*key_spec*]
+ Generate DS record (all digest algorithms together) for specified key. *Key_spec*
+ is like for **set**, if unspecified, all KSKs are used.
+
+**dnskey** [*key_spec*]
+ Generate DNSKEY record for specified key. *Key_spec*
+ is like for **ds**, if unspecified, all KSKs are used.
+
+**delete** *key_spec*
+ Remove the specified key from zone. If the key was not shared, it is also deleted from keystore.
+
+**share** *key_ID* *zone_from*
+ Import a key (specified by full key ID) from another zone as shared. After this, the key is
+ owned by both zones equally.
+
+Commands related to Offline KSK feature
+.......................................
+
+**pregenerate** [*timestamp-from*] *timestamp-to*
+ Pre-generate ZSKs for use with offline KSK, for the specified period starting from now or specified time.
+ This function also applies to non-offline KSK keys.
+
+**show-offline** [*timestamp-from*] [*timestamp-to*]
+ Print pre-generated offline key-related records for specified time interval. If *timestamp_to*
+ is omitted, it will be to infinity. If *timestamp-from* is omitted, it will start from the
+ beginning.
+
+**del-offline** *timestamp-from* *timestamp-to*
+ Delete pre-generated offline key-related records in specified time interval.
+
+**del-all-old**
+ Delete old keys that are in state 'removed'. This function also applies to
+ non-offline KSK keys.
+
+**generate-ksr** [*timestamp-from*] *timestamp-to*
+ Print to stdout KeySigningRequest based on pre-generated ZSKs for specified time period.
+ If *timestamp-from* is omitted, timestamp of the last offline records set is used
+ or now if no records available.
+
+**sign-ksr** *ksr_file*
+ Read KeySigningRequest from a text file, sign it using local keyset and print SignedKeyResponse to stdout.
+
+**validate-skr** *skr_file*
+ Read SignedKeyResponse from a text file and validate the RRSIGs in it if not corrupt.
+
+**import-skr** *skr_file*
+ Read SignedKeyResponse from a text file and import the signatures for later use in zone. If some
+ signatures have already been imported, they will be deleted for the period from beginning of the SKR
+ to infinity.
+
+Generate arguments
+..................
+
+Arguments are separated by space, each of them is in format 'name=value'.
+
+**algorithm**
+ Either an algorithm number (e.g. 14) or :ref:`algorithm name<policy_algorithm>`
+ without dashes (e.g. ECDSAP384SHA384).
+
+**size**
+ Key length in bits.
+
+**ksk**
+ If set to **yes**, the key will be used for signing DNSKEY rrset. The generated key will also
+ have the Secure Entry Point flag set to 1.
+
+**zsk**
+ If set to **yes**, the key will be used for signing zone (except DNSKEY rrset). This flag can
+ be set concurrently with the **ksk** flag.
+
+**sep**
+ Overrides the standard setting of the Secure Entry Point flag.
+
+The following arguments are timestamps of key lifetime (see :ref:`DNSSEC Key states`):
+
+**pre_active**
+ Key started to be used for signing, not published (only for algorithm rollover).
+
+**publish**
+ Key published.
+
+**ready**
+ Key is waiting for submission (only for KSK).
+
+**active**
+ Key used for signing.
+
+**retire_active**
+ Key still used for signing, but another key is active (only for KSK or algorithm rollover).
+
+**retire**
+ Key still published, but no longer used for signing.
+
+**post_active**
+ Key no longer published, but still used for signing (only for algorithm rollover).
+
+**revoke**
+ Key revoked according to :rfc:`5011` trust anchor roll-over.
+
+**remove**
+ Key deleted.
+
+Timestamps
+..........
+
+0
+ Zero timestamp means infinite future.
+
+*UNIX_time*
+ Positive number of seconds since 1970 UTC.
+
+*YYYYMMDDHHMMSS*
+ Date and time in this format without any punctuation.
+
+*relative_timestamp*
+ A sign character (**+**, **-**), a number, and an optional time unit
+ (**y**, **mo**, **d**, **h**, **mi**, **s**). The default unit is one second.
+ E.g. +1mi, -2mo.
+
+Output timestamp formats
+........................
+
+(none)
+ The timestamps are printed as UNIX timestamp.
+
+**human**
+ The timestamps are printed relatively to now using time units (e.g. -2y5mo, +1h13s).
+
+**iso**
+ The timestamps are printed in the ISO8601 format (e.g. 2016-12-31T23:59:00).
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+1. Generate new TSIG key::
+
+ $ keymgr -t my_name hmac-sha384
+
+2. Generate new DNSSEC key::
+
+ $ keymgr example.com. generate algorithm=ECDSAP256SHA256 size=256 \
+ ksk=true created=1488034625 publish=20170223205611 retire=+10mo remove=+1y
+
+3. Import a DNSSEC key from BIND::
+
+ $ keymgr example.com. import-bind ~/bind/Kharbinge4d5.+007+63089.key
+
+4. Configure key timing::
+
+ $ keymgr example.com. set 4208 active=+2mi retire=+4mi remove=+5mi
+
+5. Share a KSK from another zone::
+
+ $ keymgr example.com. share e687cf927029e9db7184d2ece6d663f5d1e5b0e9 another-zone.com.
+
+See Also
+--------
+
+:rfc:`6781` - DNSSEC Operational Practices.
+:rfc:`7583` - DNSSEC Key Rollover Timing Considerations.
+
+:manpage:`knot.conf(5)`,
+:manpage:`knotc(8)`,
+:manpage:`knotd(8)`.
diff --git a/doc/man_khost.rst b/doc/man_khost.rst
new file mode 100644
index 0000000..1fcc0bf
--- /dev/null
+++ b/doc/man_khost.rst
@@ -0,0 +1,108 @@
+.. highlight:: none
+
+``khost`` – Simple DNS lookup utility
+=====================================
+
+Synopsis
+--------
+
+:program:`khost` [*options*] *name* [*server*]
+
+Description
+-----------
+
+This utility sends a DNS query for the *name* to the *server* and prints a reply
+in more user-readable form. For more advanced DNS queries use :doc:`kdig<man_kdig>`
+instead.
+
+Parameters
+..........
+
+*name*
+ Is a domain name that is to be looked up. If the *name* is IPv4 or IPv6
+ address the PTR query type is used.
+
+*server*
+ Is a name or an address of the nameserver to send a query to. The address
+ can be specified using [address]:port notation. If no server is specified,
+ the servers from :file:`/etc/resolv.conf` are used.
+
+If no arguments are provided, :program:`khost` prints a short help.
+
+Options
+.......
+
+**-4**
+ Use the IPv4 protocol only.
+
+**-6**
+ Use the IPv6 protocol only.
+
+**-a**
+ Send ANY query with verbose mode.
+
+**-d**
+ Enable debug messages.
+
+**-h**, **--help**
+ Print the program help.
+
+**-r**
+ Disable recursion.
+
+**-T**
+ Use the TCP protocol.
+
+**-v**
+ Enable verbose output.
+
+**-V**, **--version**
+ Print the program version.
+
+**-w**
+ Wait forever for the reply.
+
+**-c** *class*
+ Set the query class (e.g. CH, CLASS4). The default class is IN.
+
+**-t** *type*
+ Set the query type (e.g. NS, IXFR=12345, TYPE65535). The default is to send 3
+ queries (A, AAAA and MX).
+
+**-R** *retries*
+ The number (>=0) of UDP retries to query a nameserver. The default is 1.
+
+**-W** *wait*
+ The time to wait for a reply in seconds. This timeout applies to each query
+ try. The default is 2 seconds.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+1. Get the A, AAAA and MX records for example.com::
+
+ $ khost example.com
+
+2. Get the reverse record for address 192.0.2.1::
+
+ $ khost 192.0.2.1
+
+3. Perform a verbose zone transfer for zone example.com::
+
+ $ khost -t AXFR -v example.com
+
+Files
+-----
+
+:file:`/etc/resolv.conf`
+
+See Also
+--------
+
+:manpage:`kdig(1)`, :manpage:`knsupdate(1)`.
diff --git a/doc/man_kjournalprint.rst b/doc/man_kjournalprint.rst
new file mode 100644
index 0000000..f83a137
--- /dev/null
+++ b/doc/man_kjournalprint.rst
@@ -0,0 +1,88 @@
+.. highlight:: none
+
+``kjournalprint`` – Knot DNS journal print utility
+==================================================
+
+Synopsis
+--------
+
+:program:`kjournalprint` [*config_option*] [*options*] *zone_name*
+
+:program:`kjournalprint` [*config_option*] **-z**
+
+Description
+-----------
+
+The program prints zone history stored in a journal database. As default,
+changes are colored for terminal.
+
+Parameters
+..........
+
+*zone_name*
+ A name of the zone to print the history for.
+
+Config options
+..............
+
+**-c**, **--config** *file*
+ Use a textual configuration file (default is :file:`@config_dir@/knot.conf`).
+
+**-C**, **--confdb** *directory*
+ Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`).
+ The default configuration database, if exists, has a preference to the default
+ configuration file.
+
+**-D**, **--dir** *path*
+ Use specified journal database path and default configuration.
+
+Options
+.......
+
+**-z**, **--zone-list**
+ Instead of reading the journal, display the list of zones in the DB.
+
+**-l**, **--limit** *limit*
+ Limits the number of displayed changes.
+
+**-s**, **--serial** *soa*
+ Start at a specific SOA serial.
+
+**-H**, **--check**
+ Enable additional journal semantic checks during printing.
+
+**-d**, **--debug**
+ Debug mode brief output.
+
+**-x**, **--mono**
+ Don't generate colorized output.
+
+**-n**, **--no-color**
+ An alias for **-x**. Use of this option is deprecated, it will be removed in the future.
+
+**-X**, **--color**
+ Force colorized output.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+Last (most recent) 5 changes without colors::
+
+ $ kjournalprint -nl 5 /var/lib/knot/journal example.com.
+
+See Also
+--------
+
+:manpage:`knotd(8)`, :manpage:`knot.conf(5)`.
diff --git a/doc/man_knotc.rst b/doc/man_knotc.rst
new file mode 100644
index 0000000..f9a5509
--- /dev/null
+++ b/doc/man_knotc.rst
@@ -0,0 +1,390 @@
+.. highlight:: none
+
+``knotc`` – Knot DNS control utility
+====================================
+
+Synopsis
+--------
+
+:program:`knotc` [*config_option*] [*options*] [*action*]
+
+Description
+-----------
+
+This program controls a running `knotd` process using a socket.
+
+If an *action* is specified, it is performed and `knotc` exits, otherwise the program
+is executed in the interactive mode.
+
+Config options
+..............
+
+**-c**, **--config** *file*
+ Use a textual configuration file (default is :file:`@config_dir@/knot.conf`).
+
+**-C**, **--confdb** *directory*
+ Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`).
+ The default configuration database, if exists, has a preference to the default
+ configuration file.
+
+Options
+.......
+
+**-m**, **--max-conf-size** *MiB*
+ Set maximum size of the configuration database
+ (default is @conf_mapsize@ MiB, maximum 10000 MiB).
+
+**-s**, **--socket** *path*
+ Use a control UNIX socket path (default is :file:`@run_dir@/knot.sock`).
+
+**-t**, **--timeout** *seconds*
+ Use a control timeout in seconds. Set to 0 for infinity (default is 60).
+ The control socket operations are also subject to the :ref:`timeout<control_timeout>`
+ parameter set on the server side in server's Control configuration section.
+
+**-b**, **--blocking**
+ Zone event trigger commands wait until the event is finished. Control timeout
+ is set to infinity if not forced by explicit timeout specification.
+
+**-e**, **--extended**
+ Show extended output (even empty items in zone status).
+
+**-f**, **--force**
+ Forced operation. Overrides some checks.
+
+**-x**, **--mono**
+ Don't generate colorized output.
+
+**-X**, **--color**
+ Force colorized output in extended output or to a pipe.
+
+**-v**, **--verbose**
+ Enable debug output.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+Actions
+.......
+
+**status** [*detail*]
+ Check if the server is running. Details are **version** for the running
+ server version, **workers** for the numbers of worker threads,
+ **configure** for the configure summary, or **cert-key** for the
+ public key pin of the currently used certificate.
+
+**stop**
+ Stop the server if running.
+
+**reload**
+ Reload the server configuration and modified zone files. All open zone
+ transactions will be aborted!
+
+**stats** [*module*\ [\ **.**\ *counter*\ ]]
+ Show global statistics counter(s). To print also counters with value 0, use
+ force option.
+
+**zone-check** [*zone*...]
+ Test if the server can load the zone. Semantic checks are executed if enabled
+ in the configuration. If invoked with the force option, an error is returned
+ when semantic check warning appears. (*)
+
+**zone-status** [*zone*...] [*filter*]
+ Show the zone status. Filters are **+role**, **+serial**, **+transaction**,
+ **+events**, **+freeze**, and **+catalog**. Empty zone parameters are omitted,
+ unless the **--extended** option is used. A single dash in the output represents
+ an unset value. Automatic colorization can be overruled using the **--mono** and
+ **--color** options.
+
+ The color code is:
+ *green* - zone acts as a master / *red* - zone acts as a slave,
+ *bold font (highlited)* - zone is active / *normal* - zone is empty,
+ *underscored* - zone is an interpreted catalog member.
+
+**zone-reload** [*zone*...]
+ Trigger a zone reload from a disk without checking its modification time. For
+ secondary zone, the refresh event from primary server(s) is scheduled;
+ for primary zone, the notify event to secondary server(s) is scheduled. An open
+ zone transaction will be aborted! If invoked with the force option, also zone
+ modules will be re-loaded, but blocking mode might not work reliably. (#)
+
+**zone-refresh** [*zone*...]
+ Trigger a check for the zone serial on the zone's primary server. If
+ the primary server has a newer zone, a transfer is scheduled. This command is
+ valid for secondary zones. (#)
+
+**zone-retransfer** [*zone*...]
+ Trigger a zone transfer from the zone's primary server. The server
+ doesn't check the serial of the primary server's zone. This command is valid
+ for secondary zones. (#)
+
+**zone-notify** [*zone*...]
+ Trigger a NOTIFY message to all configured remotes. This can help in cases
+ when previous NOTIFY had been lost or the secondary servers have been
+ offline. (#)
+
+**zone-flush** [*zone*...] [**+outdir** *directory*]
+ Trigger a zone journal flush to the configured zone file. If an output
+ directory is specified, the current zone is immediately dumped (in the
+ blocking mode) to a zone file in the specified directory. See
+ :ref:`Notes<notes>` below about the directory permissions. (#)
+
+**zone-backup** [*zone*...] **+backupdir** *directory* [*filter*...]
+ Trigger a zone data and metadata backup to a specified directory.
+ Available filters are **+zonefile**, **+journal**, **+timers**, **+kaspdb**,
+ **+keysonly**, **+catalog**, **+quic**, and their negative counterparts
+ **+nozonefile**, **+nojournal**, **+notimers**, **+nokaspdb**, **+nokeysonly**,
+ **+nocatalog**, and **+noquic**. With these filters set, zone contents,
+ zone's journal, zone-related timers, zone-related data in the KASP database
+ together with keys (or keys without the KASP database), zone's catalog,
+ and the server QUIC key and certificate, respectively, are backed up,
+ or omitted from the backup. By default, filters **+zonefile**, **+timers**,
+ **+kaspdb**, **+nokeysonly**, **+catalog**, **+quic**, and **+nojournal**
+ are set for backup. The same defaults are set for restore, with the only
+ difference being **+noquic**. Setting a filter for an item doesn't change
+ default settings for other items. If zone flushing is disabled, the original
+ zone file is backed up instead of writing out zone contents to a file.
+ When backing-up a catalog zone, it is recommended to prevent ongoing changes
+ to it by use of **zone-freeze**.
+ See :ref:`Notes<notes>` below about the directory permissions. (#)
+
+**zone-restore** [*zone*...] **+backupdir** *directory* [*filter*...]
+ Trigger a zone data and metadata restore from a specified backup directory.
+ Optional filters are equivalent to the same filters of **zone-backup**.
+ Restore from backups created by Knot DNS releases prior to 3.1 is possible
+ with the force option. See :ref:`Notes<notes>` below about the directory
+ permissions. (#)
+
+**zone-sign** [*zone*...]
+ Trigger a DNSSEC re-sign of the zone. Existing signatures will be dropped.
+ This command is valid for zones with DNSSEC signing enabled. (#)
+
+**zone-keys-load** [*zone*...]
+ Trigger a load of DNSSEC keys and other signing material from KASP database
+ (which might have been altered manually). If suitable, re-sign the zone
+ afterwards (keeping valid signatures intact). (#)
+
+**zone-key-rollover** *zone* *key_type*
+ Trigger immediate key rollover. Publish new key and start a key rollover,
+ even when the key has a lifetime to go. Key type can be **ksk** (also for CSK)
+ or **zsk**. This command is valid for zones with DNSSEC signing and automatic
+ key management enabled. Note that complete key rollover consists of several steps
+ and the blocking mode relates to the initial one only! (#)
+
+**zone-ksk-submitted** *zone*...
+ Use when the zone's KSK rollover is in submission phase. By calling this command
+ the user confirms manually that the parent zone contains DS record for the new
+ KSK in submission phase and the old KSK can be retired. (#)
+
+**zone-freeze** [*zone*...]
+ Trigger a zone freeze. All running events will be finished and all new and pending
+ (planned) zone-changing events (load, refresh, update, flush, and DNSSEC signing)
+ will be held up until the zone is thawed. (#)
+
+**zone-thaw** [*zone*...]
+ Trigger dismissal of zone freeze. (#)
+
+**zone-xfr-freeze** [*zone*...]
+ Temporarily disable outgoing AXFR/IXFR for the zone(s). (#)
+
+**zone-xfr-thaw** [*zone*...]
+ Dismiss outgoing XFR freeze. (#)
+
+**zone-read** *zone* [*owner* [*type*]]
+ Get zone data that are currently being presented.
+
+**zone-begin** *zone*...
+ Begin a zone transaction.
+
+**zone-commit** *zone*...
+ Commit the zone transaction. All changes are applied to the zone.
+
+**zone-abort** *zone*...
+ Abort the zone transaction. All changes are discarded.
+
+**zone-diff** *zone*
+ Get zone changes within the transaction.
+
+**zone-get** *zone* [*owner* [*type*]]
+ Get zone data within the transaction.
+
+**zone-set** *zone* *owner* [*ttl*] *type* *rdata*
+ Add zone record within the transaction. The first record in a rrset
+ requires a ttl value specified.
+
+**zone-unset** *zone* *owner* [*type* [*rdata*]]
+ Remove zone data within the transaction.
+
+**zone-purge** *zone*... [**+orphan**] [*filter*...]
+ Purge zone data, zone file, journal, timers, and/or KASP data of specified zones.
+ Available filters are **+expire**, **+zonefile**, **+journal**, **+timers**,
+ **+kaspdb**, and **+catalog**. If no filter is specified, all filters are enabled.
+ If the zone is no longer configured, add **+orphan** parameter (zone file cannot
+ be purged in this case). When purging orphans, always check the server log for
+ possible errors. For proper operation, it's necessary to prevent ongoing changes
+ to the zone and triggering of zone related events during purge; use of
+ **zone-freeze** is advisable. This command always requires the force option. (#)
+
+**zone-stats** *zone* [*module*\ [\ **.**\ *counter*\ ]]
+ Show zone statistics counter(s). To print also counters with value 0, use
+ force option.
+
+**conf-init**
+ Initialize the configuration database. If the database doesn't exist yet,
+ execute this command as an intended user to ensure the server is permitted
+ to access the database (e.g. *sudo -u knot knotc conf-init*). (*)
+
+**conf-check**
+ Check the server configuration. (*)
+
+**conf-import** *filename* [+nopurge]
+ Import a configuration file into the configuration database. If the database
+ doesn't exist yet, execute this command as an intended user to ensure the server
+ is permitted to access the database (e.g. *sudo -u knot knotc conf-import ...*).
+ An optional filter **+nopurge** prevents possibly existing configuration
+ database from purging before the import itself.
+ Also ensure the server is not using the configuration database at the same time! (*)
+
+**conf-export** [*filename*]
+ Export the configuration database into a config file or stdout. (*)
+
+**conf-list** [*item*]
+ List the configuration database sections or section items.
+
+**conf-read** [*item*]
+ Read the item from the active configuration database.
+
+**conf-begin**
+ Begin a writing configuration database transaction. Only one transaction
+ can be opened at a time.
+
+**conf-commit**
+ Commit the configuration database transaction.
+
+**conf-abort**
+ Rollback the configuration database transaction.
+
+**conf-diff** [*item*]
+ Get the item difference in the transaction.
+
+**conf-get** [*item*]
+ Get the item data from the transaction.
+
+**conf-set** *item* [*data*...]
+ Set the item data in the transaction.
+
+**conf-unset** [*item*] [*data*...]
+ Unset the item data in the transaction.
+
+.. _notes:
+
+Notes
+.....
+
+Empty or **--** *zone* parameter means all zones or all zones with a transaction.
+
+Use **@** *owner* to denote the zone name.
+
+Type *item* parameter in the form of *section*\ [**[**\ *id*\ **]**\ ][**.**\ *name*].
+
+(*) indicates a local operation which requires a configuration.
+
+(\#) indicates an optionally blocking operation.
+
+The **-b** and **-f** options can be placed right after the command name.
+
+Responses returned by `knotc` commands depend on the mode:
+
+- In the blocking mode, `knotc` reports if an error occurred during processing
+ of the command by the server. If an error is reported, a more detailed information
+ about the failure can usually be found in the server log.
+
+- In the non-blocking (default) mode, `knotc` doesn't report processing errors.
+ The `OK` response to triggering commands means that the command has been successfully
+ sent to the server. To verify if the operation succeeded, it's necessary to
+ check the server log.
+
+Actions **zone-flush**, **zone-backup**, and **zone-restore** are carried out by
+the `knotd` process. The directory specified must be accessible to the user account
+that `knotd` runs under and if the directory already exists, its permissions must be
+appropriate for that user account.
+
+Interactive mode
+................
+
+The utility provides interactive mode with basic line editing functionality,
+command completion, and command history.
+
+Interactive mode behavior can be customized in `~/.editrc`. Refer to
+:manpage:`editrc(5)` for details.
+
+Command history is saved in `~/.knotc_history`.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+Reload the whole server configuration
+.....................................
+
+::
+
+ $ knotc reload
+
+Flush the example.com and example.org zones
+...........................................
+
+::
+
+ $ knotc zone-flush example.com example.org
+
+Get the current server configuration
+....................................
+
+::
+
+ $ knotc conf-read server
+
+Get the list of the current zones
+.................................
+
+::
+
+ $ knotc conf-read zone.domain
+
+Get the primary servers for the example.com zone
+................................................
+
+::
+
+ $ knotc conf-read 'zone[example.com].master'
+
+Add example.org zone with a zonefile location
+.............................................
+
+::
+
+ $ knotc conf-begin
+ $ knotc conf-set 'zone[example.org]'
+ $ knotc conf-set 'zone[example.org].file' '/var/zones/example.org.zone'
+ $ knotc conf-commit
+
+Get the SOA record for each configured zone
+...........................................
+
+::
+
+ $ knotc zone-read -- @ SOA
+
+See Also
+--------
+
+:manpage:`knotd(8)`, :manpage:`knot.conf(5)`, :manpage:`editrc(5)`.
diff --git a/doc/man_knotd.rst b/doc/man_knotd.rst
new file mode 100644
index 0000000..d0fe83b
--- /dev/null
+++ b/doc/man_knotd.rst
@@ -0,0 +1,69 @@
+.. highlight:: none
+
+``knotd`` – Knot DNS server daemon
+==================================
+
+Synopsis
+--------
+
+:program:`knotd` [*config_option*] [*options*]
+
+Description
+-----------
+
+Knot DNS is a high-performance authoritative DNS server. The `knotd` program is
+the DNS server daemon.
+
+Config options
+..............
+
+**-c**, **--config** *file*
+ Use a textual configuration file (default is :file:`@config_dir@/knot.conf`).
+
+**-C**, **--confdb** *directory*
+ Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`).
+ The default configuration database, if exists, has a preference to the default
+ configuration file.
+
+Options
+.......
+
+**-m**, **--max-conf-size** *MiB*
+ Set maximum size of the configuration database
+ (default is @conf_mapsize@ MiB, maximum 10000 MiB).
+
+**-s**, **--socket** *path*
+ Use a remote control UNIX socket path (default is :file:`@run_dir@/knot.sock`).
+
+**-d**, **--daemonize** [*directory*]
+ Run the server as a daemon. New root directory may be specified
+ (default is :file:`/`).
+
+**-v**, **--verbose**
+ Enable debug output.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+Signals
+.......
+
+If the `knotd` process receives a SIGHUP signal, it reloads its configuration and
+reopens the log files, if they are configured. When `knotd` receives a SIGUSR1
+signal, it reloads all configured zones. Upon receiving a SIGINT signal, `knotd`
+exits.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+See Also
+--------
+
+:manpage:`knot.conf(5)`, :manpage:`knotc(8)`, :manpage:`keymgr(8)`,
+:manpage:`kjournalprint(8)`.
diff --git a/doc/man_knsec3hash.rst b/doc/man_knsec3hash.rst
new file mode 100644
index 0000000..bf0688c
--- /dev/null
+++ b/doc/man_knsec3hash.rst
@@ -0,0 +1,60 @@
+.. highlight:: none
+
+``knsec3hash`` – NSEC hash computation utility
+==============================================
+
+Synopsis
+--------
+
+:program:`knsec3hash` *salt* *algorithm* *iterations* *name*
+
+:program:`knsec3hash` *algorithm* *flags* *iterations* *salt* *name*
+
+Description
+-----------
+
+This utility generates a NSEC3 hash for a given domain name and parameters of NSEC3 hash.
+
+Parameters
+..........
+
+*salt*
+ Specifies a binary salt encoded as a hexadecimal string.
+
+*algorithm*
+ Specifies a hashing algorithm by number. Currently, the only supported algorithm is SHA-1 (number 1).
+
+*iterations*
+ Specifies the number of additional iterations of the hashing algorithm.
+
+*name*
+ Specifies the domain name to be hashed.
+
+*flags*
+ Specifies NSEC3 flags as an unsigned integer.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+::
+
+ $ knsec3hash 1 0 10 c01dcafe knot-dns.cz
+ 7PTVGE7QV67EM61ROS9238P5RAKR2DM7 (salt=c01dcafe, hash=1, iterations=10)
+
+::
+
+ $ knsec3hash - 1 0 net
+ A1RT98BS5QGC9NFI51S9HCI47ULJG6JH (salt=-, hash=1, iterations=0)
+
+See Also
+--------
+
+:rfc:`5155` – DNS Security (DNSSEC) Hashed Authenticated Denial of Existence.
+
+:manpage:`knotc(8)`, :manpage:`knotd(8)`.
diff --git a/doc/man_knsupdate.rst b/doc/man_knsupdate.rst
new file mode 100644
index 0000000..40a419b
--- /dev/null
+++ b/doc/man_knsupdate.rst
@@ -0,0 +1,188 @@
+.. highlight:: none
+
+``knsupdate`` – Dynamic DNS update utility
+==========================================
+
+Synopsis
+--------
+
+:program:`knsupdate` [*options*] [*filename*]
+
+Description
+-----------
+
+This utility sends Dynamic DNS update messages to a DNS server. Update content
+is read from a file (if the parameter *filename* is given) or from the standard
+input.
+
+The format of updates is textual and is made up of commands. Every command is
+placed on the separate line of the input. Lines starting with a semicolon are
+comments and are not processed.
+
+Parameters
+..........
+
+*filename*
+ Path to the file with knsupdate commands.
+
+Options
+.......
+
+**-d**
+ Enable debug messages.
+
+**-h**, **--help**
+ Print the program help.
+
+**-k** *keyfile*
+ Use the TSIG key stored in a file *keyfile* to authenticate the request. The
+ file should contain the key in the same format, which is accepted by the
+ **-y** option.
+
+**-p** *port*
+ Set the port to use for connections to the server (if not explicitly specified
+ in the update). The default is 53.
+
+**-r** *retries*
+ The number of retries for UDP requests. The default is 3.
+
+**-t** *timeout*
+ The total timeout (for all UDP update tries) of the update request in seconds.
+ The default is 12. If set to zero, the timeout is infinite.
+
+**-v**
+ Use a TCP connection.
+
+**-V**, **--version**
+ Print the program version.
+
+**-y** [*alg*:]\ *name*:*key*
+ Use the TSIG key with a name *name* to authenticate the request. The *alg*
+ part specifies the algorithm (the default is hmac-sha256) and *key* specifies
+ the shared secret encoded in Base64.
+
+Commands
+........
+
+**server** *name* [*port*]
+ Specifies a receiving server of the dynamic update message. The *name* parameter
+ can be either a host name or an IP address. If the *port* is not specified,
+ the default port is used. The default port value can be controlled using
+ the **-p** program option.
+
+**local** *address* [*port*]
+ Specifies outgoing *address* and *port*. If no local is specified, the
+ address and port are set by the system automatically. The default port number
+ is 0.
+
+**zone** *name*
+ Specifies that all updates are done within a zone *name*. The zone name doesn't
+ have a default and must be set explicitly.
+
+**origin** *name*
+ Specifies fully qualified domain name suffix which is appended to non-fqd
+ owners in update commands. The default is the terminal label (**.**).
+
+**class** *name*
+ Sets *name* as the default class for all updates. If not used, the default
+ class is IN.
+
+**ttl** *value*
+ Sets *value* as the default TTL (in seconds). If not used, the default value
+ is 3600.
+
+**key** [*alg*:]\ *name* *key*
+ Specifies the TSIG *key* named *name* to authenticate the request. An optional
+ *alg* algorithm can be specified. This command has the same effect as
+ the program option **-y**.
+
+[**prereq**] **nxdomain** *name*
+ Adds a prerequisite for a non-existing record owned by *name*.
+
+[**prereq**] **yxdomain** *name*
+ Adds a prerequisite for an existing record owned by *name*.
+
+[**prereq**] **nxrrset** *name* [*class*] *type*
+ Adds a prerequisite for a non-existing record of the *type* owned by *name*.
+ Internet *class* is expected.
+
+[**prereq**] **yxrrset** *name* [*class*] *type* [*data*]
+ Adds a prerequisite for an existing record of the *type* owned by *name*
+ with optional *data*. Internet *class* is expected.
+
+[**update**] **add** *name* [*ttl*] [*class*] *type* *data*
+ Adds a request to add a new resource record into the zone.
+ Please note that if the *name* is not fully qualified domain name, the
+ current origin name is appended to it.
+
+[**update**] **del**\[**ete**] *name* [*ttl*] [*class*] [*type*] [*data*]
+ Adds a request to remove all (or matching *class*, *type* or *data*)
+ resource records from the zone. There is the same requirement for the *name*
+ parameter as in **update add** command. The *ttl* item is ignored.
+
+**show**
+ Displays current content of the update message.
+
+**send**
+ Sends the current update message and cleans the list of updates.
+
+**answer**
+ Displays the last answer from the server.
+
+**debug**
+ Enable debugging. This command has the same meaning as the **-d** program option.
+
+**exit**
+ End the program.
+
+Notes
+-----
+
+Options **-k** and **-y** can not be used simultaneously.
+
+Neither `tsig-keygen(8)` nor `dnssec-keygen(1)` keyfile formats are supported.
+Use :manpage:`keymgr(8)` to construct a string for **-y** or the file passed to **-k**.
+
+Zone name/server guessing is not supported if the zone name/server is not specified.
+
+An empty line doesn't send the update.
+
+Interactive mode
+................
+
+The utility provides interactive mode with basic line editing functionality,
+command completion, and command history.
+
+Interactive mode behavior can be customized in `~/.editrc`. Refer to
+:manpage:`editrc(5)` for details.
+
+Command history is saved in `~/.knsupdate_history`.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+1. Send one update of the zone example.com to the server 192.168.1.1. The update
+ contains two new records::
+
+ $ knsupdate
+ knsupdate> server 192.168.1.1
+ knsupdate> zone example.com.
+ knsupdate> origin example.com.
+ knsupdate> ttl 3600
+ knsupdate> add test1.example.com. 7200 A 192.168.2.2
+ knsupdate> add test2 TXT "hello"
+ knsupdate> show
+ knsupdate> send
+ knsupdate> answer
+ knsupdate> exit
+
+See Also
+--------
+
+:manpage:`kdig(1)`, :manpage:`khost(1)`, :manpage:`keymgr(8)`, :manpage:`editrc(5)`.
diff --git a/doc/man_kxdpgun.rst b/doc/man_kxdpgun.rst
new file mode 100644
index 0000000..4664a1e
--- /dev/null
+++ b/doc/man_kxdpgun.rst
@@ -0,0 +1,218 @@
+.. highlight:: none
+
+``kxdpgun`` – DNS benchmarking tool
+===================================
+
+Synopsis
+--------
+
+:program:`kxdpgun` [*options*] **-i** *filename* *target_IP*
+
+Description
+-----------
+
+Powerful generator of DNS traffic, sending and receiving packets through XDP.
+
+Queries are generated according to a textual file which is read sequentially
+in a loop until a configured duration elapses. The order of queries is not
+guaranteed. Responses are received (unless disabled) and counted, but not
+checked against queries.
+
+The number of parallel threads is autodetected according to the number of queues
+configured for the network interface.
+
+Parameters
+..........
+
+*filename*
+ Path to the queries file. See the description below regarding the file format.
+
+*target_IP*
+ The IPv4 or IPv6 address of remote destination.
+
+Options
+.......
+
+**-t**, **--duration** *seconds*
+ Duration of traffic generation, specified as a decimal number in seconds
+ (default is 5.0).
+
+**-T**, **--tcp**\[\ **=**\ *debug_mode*\]
+ Send queries over TCP. See the list of optional debug modes below.
+
+**-U**, **--quic**\[\ **=**\ *debug_mode*\]
+ Send queries over QUIC. See the list of optional debug modes below.
+
+**-Q**, **--qps** *queries*
+ Number of queries-per-second (approximately) to be sent (default is 1000).
+ The program is not optimized for low speeds at which it may lose
+ communication packets. The recommended minimum speed is 2 packets per thread
+ (Rx/Tx queue).
+
+**-b**, **--batch** *size*
+ Send more queries in a batch. Improves QPS but may affect the counterpart's
+ packet loss (default is 10 for UDP and 1 for TCP/QUIC).
+
+**-r**, **--drop**
+ Drop incoming responses. Improves QPS, but disables response statistics.
+
+**-p**, **--port** *number*
+ Remote destination port (default is 53 for UDP/TCP, 853 for QUIC).
+
+**-F**, **--affinity** *cpu_spec*
+ CPU affinity for all threads specified in the format [<cpu_start>][s<cpu_step>],
+ where <cpu_start> is the CPU ID for the first thread and <cpu_step> is the
+ CPU ID increment for next thread (default is 0s1).
+
+**-i**, **--infile** *filename*
+ Path to a file with query templates.
+
+**-I**, **--interface** *interface*
+ Network interface for outgoing communication. This can be useful in situations
+ when the interfaces are in a bond for example.
+
+**-l**, **--local** *localIP*\ [**/**\ *prefix*]
+ Override the auto-detected source IP address. If an address range is specified
+ instead, various IPs from the range will be used for different queries uniformly
+ (address range not supported in the QUIC mode).
+
+**-L**, **--mac-local**
+ Override auto-detected local MAC address.
+
+**-R**, **--mac-remote**
+ Override auto-detected remote MAC address.
+
+**-v**, **--vlan** *id*
+ Add VLAN 802.1Q header with the given id. VLAN offloading should be disabled.
+
+**-e**, **--edns-size** *size*
+ EDNS UDP payload size, range 512-4096 (default is 1232). Note that over XDP
+ the maximum supported MTU is 1790.
+
+**-m**, **--mode** *mode*
+ Set the XDP mode. Supported values are:
+
+ - **auto** (default) – the XDP mode is selected automatically to achieve
+ the best performance, which means that native driver support is preferred
+ over the generic one, and zero-copy is used if available.
+
+ - **copy** – the XDP socket copy mode is forced even if zero-copy
+ is available. This can resolve various driver issues, but at the cost
+ of lower performance.
+
+ - **generic** – the generic XDP implementation is forced even if native
+ implementation is available. This mode doesn't require support from the
+ driver nor hardware, but offers the worst performance.
+
+**-G**, **--qlog** *path*
+ Generate qlog files in the directory specified by *path*. The directory
+ has to exist.
+
+ This option is ignored if not in the QUIC mode. The recommended usage is
+ with **--quic=R** or with low QPS. Otherwise, too many files are generated.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+Queries file format
+...................
+
+Each line describes a query in the form:
+
+*query_name* *query_type* [*flags*]
+
+Where *query_name* is a domain name to be queried, *query_type* is a record type
+name, and *flags* is a single character:
+
+**E** Send query with EDNS.
+
+**D** Request DNSSEC (EDNS + DO flag).
+
+TCP/QUIC debug modes
+....................
+
+**0**
+ Perform full handshake for all connections (QUIC only).
+
+**1**
+ Just send SYN (Initial) and receive SYN-ACK (Handshake).
+
+**2**
+ Perform TCP/QUIC handshake and don't send anything, allow close initiated by counterpart.
+
+**3**
+ Perform TCP/QUIC handshake and don't react further.
+
+**5**
+ Send incomplete query (N-1 bytes) and don't react further.
+
+**7**
+ Send query and don't ACK the response or anything further.
+
+**8**
+ Don't close the connection and ignore close by counterpart.
+
+**9**
+ Operate normally except for not ACKing the final FIN+ACK (TCP only).
+
+**R**
+ Instead of opening a connection for each query, reuse connections.
+
+Signals
+.......
+
+Sending USR1 signal to a running process triggers current statistics dump
+to the standard output.
+
+Notes
+-----
+
+Linux kernel 4.18+ is required.
+
+The utility has to be executed under root or with these capabilities:
+CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN, CAP_IPC_LOCK, and CAP_SYS_RESOURCE
+(Linux < 5.11).
+
+The utility allocates source UDP/TCP ports from the range 2000-65535.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+Examples
+--------
+
+Manually created queries file::
+
+ abc6.example.com. AAAA
+ nxdomain.example.com. A
+ notzone. A
+ a.example.com. NS E
+ ab.example.com. A D
+ abcd.example.com. DS D
+
+Queries file generated from a zone file (Knot DNS format)::
+
+ cat ZONE_FILE | awk "{print \$1,\$3}" | grep -E "(NS|DS|A|AAAA|PTR|MX|SOA)$" | sort -u -R > queries.txt
+
+Basic usage::
+
+ # kxdpgun -i ~/queries.txt 2001:DB8::1
+
+*Using UDP with increased batch size*::
+
+ # kxdpgun -t 20 -Q 1000000 -i ~/queries.txt -b 20 -p 8853 192.0.2.1
+
+*Using TCP*::
+
+ # kxdpgun -t 20 -Q 100000 -i ~/queries.txt -T -p 8853 192.0.2.1
+
+See Also
+--------
+
+:manpage:`kdig(1)`.
diff --git a/doc/man_kzonecheck.rst b/doc/man_kzonecheck.rst
new file mode 100644
index 0000000..4a815a4
--- /dev/null
+++ b/doc/man_kzonecheck.rst
@@ -0,0 +1,65 @@
+.. highlight:: none
+
+``kzonecheck`` – Knot DNS zone file checking tool
+=================================================
+
+Synopsis
+--------
+
+:program:`kzonecheck` [*options*] *filename*
+
+Description
+-----------
+
+The utility checks zone file syntax and runs semantic checks on the zone
+content. The executed checks are the same as the checks run by the Knot
+DNS server.
+
+Please, refer to the ``semantic-checks`` configuration option in
+:manpage:`knot.conf(5)` for the full list of available semantic checks.
+
+Parameters
+..........
+
+*filename*
+ Path to the zone file to be checked. For reading from **stdin** use **/dev/stdin**
+ or just **-**.
+
+Options
+.......
+
+**-o**, **--origin** *origin*
+ Zone origin. If not specified, the origin is determined from the file name
+ (possibly removing the ``.zone`` suffix).
+
+**-d**, **--dnssec** **on**\|\ **off**
+ Also check DNSSEC-related records. The default is to decide based on the
+ existence of a RRSIG for SOA.
+
+**-t**, **--time** *time*
+ Current time specification. Use UNIX timestamp, YYYYMMDDHHmmSS
+ format, or [+/-]\ *time*\ [unit] format, where unit can be **Y**, **M**,
+ **D**, **h**, **m**, or **s**. Default is current UNIX timestamp.
+
+**-p**, **--print**
+ Print the zone on stdout.
+
+**-v**, **--verbose**
+ Enable debug output.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+See Also
+--------
+
+:manpage:`knotd(8)`, :manpage:`knot.conf(5)`.
diff --git a/doc/man_kzonesign.rst b/doc/man_kzonesign.rst
new file mode 100644
index 0000000..c759c57
--- /dev/null
+++ b/doc/man_kzonesign.rst
@@ -0,0 +1,69 @@
+.. highlight:: none
+
+``kzonesign`` – DNSSEC signing utility
+======================================
+
+Synopsis
+--------
+
+:program:`kzonesign` [*config_option*] [*options*] *zone_name*
+
+Description
+-----------
+
+This utility reads the zone's zone file, signs the zone according to given
+configuration, and writes the signed zone file back. An alternative mode
+is DNSSEC validation of the given zone. The signing or validation
+can run in parallel if enabled in the configuration (see policy.signing-threads
+and zone.adjust-threads).
+
+Parameters
+..........
+
+*zone_name*
+ A name of the zone to be signed.
+
+Config options
+..............
+
+**-c**, **--config** *file*
+ Use a textual configuration file (default is :file:`@config_dir@/knot.conf`).
+
+**-C**, **--confdb** *directory*
+ Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`).
+ The default configuration database, if exists, has a preference to the default
+ configuration file.
+
+Options
+.......
+
+**-o**, **--outdir** *dir_name*
+ Write the output zone file to the specified directory instead of the configured one.
+
+**-r**, **--rollover**
+ Allow key roll-overs and NSEC3 re-salt. In order to finish possible KSK submission,
+ set the KSK's **active** timestamp to now (**+0**) using :doc:`keymgr<man_keymgr>`.
+
+**-v**, **--verify**
+ Instead of (re-)signing the zone, just verify that the zone is correctly signed.
+
+**-t**, **--time** *timestamp*
+ Sign/verify the zone (and roll the keys if necessary) as if it was at the time
+ specified by timestamp.
+
+**-h**, **--help**
+ Print the program help.
+
+**-V**, **--version**
+ Print the program version.
+
+Exit values
+-----------
+
+Exit status of 0 means successful operation. Any other exit status indicates
+an error.
+
+See Also
+--------
+
+:manpage:`knot.conf(5)`, :manpage:`keymgr(8)`.
diff --git a/doc/migration.rst b/doc/migration.rst
new file mode 100644
index 0000000..f79539c
--- /dev/null
+++ b/doc/migration.rst
@@ -0,0 +1,437 @@
+.. highlight:: none
+.. _Migration:
+
+*********
+Migration
+*********
+
+.. _Upgrade 2.4.x to 2.5.x:
+
+Upgrade 2.4.x to 2.5.x
+======================
+
+This chapter describes some steps necessary after upgrading Knot DNS from
+version 2.4.x to 2.5.x.
+
+.. _Building changes:
+
+Building changes
+----------------
+
+The ``--enable-dnstap`` configure option now enables the dnstap support in
+:doc:`kdig<man_kdig>` only! To build the dnstap query module, ``--with-module-dnstap``
+have to be used.
+
+Since Knot DNS version 2.5.0 each query module can be configured to be:
+
+- disabled: ``--with-module-``\ MODULE_NAME\ ``=no``
+- embedded: ``--with-module-``\ MODULE_NAME\ ``=yes``
+- external: ``--with-module-``\ MODULE_NAME\ ``=shared`` (excluding
+ ``dnsproxy`` and ``onlinesign``)
+
+The ``--with-timer-mapsize`` configure option was replaced with the runtime
+``template.max-timer-db-size`` configuration option.
+
+.. _KASP DB migration:
+
+KASP DB migration
+-----------------
+
+Knot DNS version 2.4.x and earlier uses JSON files to store DNSSEC keys metadata,
+one for each zone. 2.5.x versions store those in binary format in a LMDB, all zones
+together. The migration is possible with the
+`pykeymgr <https://gitlab.nic.cz/knot/knot-dns/blob/2.6/src/utils/pykeymgr/pykeymgr.in>`_
+script::
+
+ $ pykeymgr -i path/to/keydir
+
+The path to KASP DB directory is configuration-dependent, usually it is the ``keys``
+subdirectory in the zone storage.
+
+In rare installations, the JSON files might be spread across more directories. In such
+case, it is necessary to put them together into one directory and migrate at once.
+
+.. _Configuration changes 2.5:
+
+Configuration changes
+---------------------
+
+It is no longer possible to configure KASP DB per zone or in a non-default
+template. Ensure just one common KASP DB configuration in the default
+template.
+
+As Knot DNS version 2.5.0 brings dynamically loaded modules, some modules
+were renamed for technical reasons. So it is necessary to rename all
+occurrences (module section names and references from zones or templates)
+of the following module names in the configuration::
+
+ mod-online-sign -> mod-onlinesign
+
+ mod-synth-record -> mod-synthrecord
+
+.. _Upgrade 2.5.x to 2.6.x:
+
+Upgrade 2.5.x to 2.6.x
+======================
+
+Upgrading from Knot DNS version 2.5.x to 2.6.x is almost seamless.
+
+.. _Configuration changes 2.6:
+
+Configuration changes
+---------------------
+
+The ``dsa`` and ``dsa-nsec3-sha1`` algorithm values are no longer supported
+by the :ref:`policy_algorithm` option.
+
+The ``ixfr-from-differences`` zone/template option was deprecated in favor of
+the :ref:`zone_zonefile-load` option.
+
+.. _Upgrade 2.6.x to 2.7.x:
+
+Upgrade 2.6.x to 2.7.x
+======================
+
+Upgrading from Knot DNS version 2.6.x to 2.7.x is seamless if no obsolete
+configuration or module rosedb is used.
+
+.. _Upgrade 2.7.x to 2.8.x:
+
+Upgrade 2.7.x to 2.8.x
+======================
+
+Upgrading from Knot DNS version 2.7.x to 2.8.x is seamless.
+
+However, if the previous version was migrated (possibly indirectly)
+from version 2.5.x, the format of the keys stored in
+Keys And Signature Policy Database
+is no longer compatible and needs to be updated.
+
+The easiest ways to update how keys are stored in KASP DB is to modify
+with Keymgr version 2.7.x
+some of each key's parameters in an undamaging way, e.g.::
+
+ $ keymgr example.com. list
+ $ keymgr example.com. set <keyTag> created=1
+ $ keymgr example.com. set <keyTag2> created=1
+ ...
+
+.. _Upgrade 2.8.x to 2.9.x:
+
+Upgrade 2.8.x to 2.9.x
+======================
+
+Upgrading from Knot DNS version 2.8.x to 2.9.x is almost seamless but check
+the following changes first.
+
+Configuration changes
+---------------------
+
+- Imperfect runtime reconfiguration of :ref:`server_udp-workers`,
+ :ref:`server_tcp-workers`, and :ref:`server_listen`
+ is no longer supported.
+
+- Replaced options (with backward compatibility):
+
+ .. csv-table::
+ :header: Old section, Old item name, New section, New item name
+ :widths: 35, 60, 35, 60
+
+ :ref:`server<Server section>` , ``tcp-reply-timeout`` [s] , :ref:`server<Server section>` , :ref:`server_tcp-remote-io-timeout` [ms]
+ :ref:`server<Server section>` , ``max-tcp-clients`` , :ref:`server<Server section>` , :ref:`server_tcp-max-clients`
+ :ref:`server<Server section>` , ``max-udp-payload`` , :ref:`server<Server section>` , :ref:`server_udp-max-payload`
+ :ref:`server<Server section>` , ``max-ipv4-udp-payload`` , :ref:`server<Server section>` , :ref:`server_udp-max-payload-ipv4`
+ :ref:`server<Server section>` , ``max-ipv6-udp-payload`` , :ref:`server<Server section>` , :ref:`server_udp-max-payload-ipv6`
+ :ref:`template<Template section>` , ``journal-db`` , :ref:`database<Database section>` , :ref:`database_journal-db`
+ :ref:`template<Template section>` , ``journal-db-mode`` , :ref:`database<Database section>` , :ref:`database_journal-db-mode`
+ :ref:`template<Template section>` , ``max-journal-db-size`` , :ref:`database<Database section>` , :ref:`database_journal-db-max-size`
+ :ref:`template<Template section>` , ``kasp-db`` , :ref:`database<Database section>` , :ref:`database_kasp-db`
+ :ref:`template<Template section>` , ``max-kasp-db-size`` , :ref:`database<Database section>` , :ref:`database_kasp-db-max-size`
+ :ref:`template<Template section>` , ``timer-db`` , :ref:`database<Database section>` , :ref:`database_timer-db`
+ :ref:`template<Template section>` , ``max-timer-db-size`` , :ref:`database<Database section>` , :ref:`database_timer-db-max-size`
+ :ref:`zone<Zone section>` , ``max-journal-usage`` , :ref:`zone<Zone section>` , :ref:`zone_journal-max-usage`
+ :ref:`zone<Zone section>` , ``max-journal-depth`` , :ref:`zone<Zone section>` , :ref:`zone_journal-max-depth`
+ :ref:`zone<Zone section>` , ``max-zone-size`` , :ref:`zone<Zone section>` , :ref:`zone_zone-max-size`
+ :ref:`zone<Zone section>` , ``max-refresh-interval`` , :ref:`zone<Zone section>` , :ref:`zone_refresh-max-interval`
+ :ref:`zone<Zone section>` , ``min-refresh-interval`` , :ref:`zone<Zone section>` , :ref:`zone_refresh-min-interval`
+
+- Removed options (no backward compatibility):
+
+ - ``server.tcp-handshake-timeout``
+ - ``zone.request-edns-option``
+
+- New default value for:
+
+ - :ref:`server_tcp-workers`
+ - :ref:`server_tcp-max-clients`
+ - :ref:`server_udp-max-payload`
+ - :ref:`server_udp-max-payload-ipv4`
+ - :ref:`server_udp-max-payload-ipv6`
+
+- New DNSSEC policy option :ref:`policy_rrsig-pre-refresh` may affect
+ configuration validity, which is ``rrsig-refresh + rrsig-pre-refresh < rrsig-lifetime``
+
+Miscellaneous changes
+---------------------
+
+- Memory use estimation via ``knotc zone-memstats`` was removed
+- Based on `<https://tools.ietf.org/html/draft-ietf-dnsop-server-cookies>`_
+ the module :ref:`DNS Cookies<mod-cookies>` was updated to be interoperable
+- Number of open files limit is set to 1048576 in upstream packages
+
+.. _Upgrade 2.9.x to 3.0.x:
+
+Upgrade 2.9.x to 3.0.x
+======================
+
+Knot DNS version 3.0.x is functionally compatible with 2.9.x with the following
+exceptions.
+
+ACL
+---
+
+Configuration option :ref:`acl_update-owner-name` is newly FQDN-sensitive.
+It means that values ``a.example.com`` and ``a.example.com.`` are not equivalent.
+
+Module synthrecord
+------------------
+
+:ref:`Reverse IPv6 address shortening<mod-synthrecord_reverse-short>` is enabled by default.
+For example, the module generates::
+
+ dynamic-2620-0-b61-100--1.test. 400 IN AAAA 2620:0:b61:100::1
+
+instead of::
+
+ dynamic-2620-0000-0b61-0100-0000-0000-0000-0001.test. 400 IN AAAA 2620:0:b61:100::1
+
+Query module API change
+-----------------------
+
+The following functions require additional parameter (thread id – ``qdata->params->thread_id``)
+on the second position::
+
+ knotd_mod_stats_incr()
+ knotd_mod_stats_decr()
+ knotd_mod_stats_store()
+
+Building notes
+--------------
+
+- The embedded library *LMDB* is no longer part of the source code. Almost every
+ modern operating system has a sufficient version of this library.
+- DoH support in kdig requires optional library *libnghttp2*.
+- XDP support on Linux requires optional library *libbpf >= 0.0.6*. If not available,
+ an embedded library can be used via ``--enable-xdp=yes`` configure option.
+
+.. _Upgrade 3.0.x to 3.1.x:
+
+Upgrade 3.0.x to 3.1.x
+======================
+
+Knot DNS version 3.1.x is functionally compatible with 3.0.x with the following
+exceptions.
+
+Configuration changes
+---------------------
+
+- Automatic SOA serial incrementation (``zonefile-load: difference-no-serial``)
+ requires having full zone stored in the journal (``journal-content: all``).
+ This change is necessary for reliable operation.
+
+- Replaced options (with backward compatibility):
+
+ .. csv-table::
+ :header: Old section, Old item name, New section, New item name
+ :widths: 40, 60, 40, 60
+
+ :ref:`server<Server section>`, ``listen-xdp``, :ref:`xdp<XDP section>`, :ref:`xdp_listen`
+
+- Ignored obsolete options (with a notice log):
+
+ - ``server.max-journal-depth``
+ - ``server.max-journal-usage``
+ - ``server.max-refresh-interval``
+ - ``server.min-refresh-interval``
+ - ``server.max-ipv4-udp-payload``
+ - ``server.max-ipv6-udp-payload``
+ - ``server.max-udp-payload``
+ - ``server.max-tcp-clients``
+ - ``server.tcp-reply-timeout``
+ - ``template.journal-db``
+ - ``template.kasp-db``
+ - ``template.timer-db``
+ - ``template.max-zone-size``
+ - ``template.max-journal-db-size``
+ - ``template.max-timer-db-size``
+ - ``template.max-kasp-db-size``
+ - ``template.journal-db-mode``
+
+- Silently ignored obsolete options:
+
+ - ``server.tcp-handshake-timeout``
+ - ``zone.disable-any``
+
+Zone backup and restore
+-----------------------
+
+The online backup format has changed slightly since 3.0 version. For zone-restore
+from backups in the previous format, it's necessary to set the *-f* option.
+Offline restore procedure of zone files from online backups is different than
+what it was before. The details are described in :ref:`Data and metadata backup`.
+
+Building notes
+--------------
+
+- The configure option ``--enable-xdp=yes`` has slightly changed its semantics.
+ It first tries to find an external library *libbpf*. If it's not detected,
+ the embedded one is used instead.
+- The kxdpgun tool also depends on library *libmnl*.
+
+Packaging
+---------
+
+Users who use module :ref:`geoip<mod-geoip>` or :ref:`dnstap<mod-dnstap>` might
+need installing an additional package with the module.
+
+.. _Upgrade 3.1.x to 3.2.x:
+
+Upgrade 3.1.x to 3.2.x
+======================
+
+Knot DNS version 3.2.x is functionally compatible with 3.1.x with the following
+exceptions.
+
+Configuration changes
+---------------------
+
+- Default value for:
+
+ - :ref:`zone_journal-max-depth` was lowered to 20.
+ This change may trigger journal history merging.
+ - :ref:`policy_nsec3-iterations` was lowered to 0.
+ This change may trigger complete NSEC3 chain reconstruction!
+ - :ref:`policy_rrsig-refresh` is set to :ref:`policy_propagation-delay` + "zone maximum TTL".
+ This change affects effective RRSIG lifetime!
+
+- New checks:
+
+ - :ref:`policy_rrsig-refresh` must be high enough to ensure all RRSIGs are
+ refreshed before their expiration.
+ - A notice log message is emitted if :ref:`policy_algorithm` is deprecated.
+
+- Ignored obsolete option (with a notice log):
+
+ - ``server.listen-xdp``
+
+Utilities:
+----------
+
+- :doc:`knotc<man_knotc>` prints simplified zones status by default. Use ``-e``
+ for full output.
+- :doc:`keymgr<man_keymgr>` uses the brief key listing mode by default. Use ``-e``
+ for full output.
+- :doc:`keymgr<man_keymgr>` parameter ``-d`` was renamed to ``-D``.
+- :doc:`kjournalprint<man_kjournalprint>` parameter ``-c`` was renamed to ``-H``.
+
+Packaging
+---------
+
+- Linux distributions Debian 9 and Ubuntu 16.04 are no longer supported.
+
+- Packages for CentOS 7 are stored in a separate COPR repository
+ ``cznic/knot-dns-latest-centos7``.
+
+- Utilities :doc:`kzonecheck<man_kzonecheck>`, :doc:`kzonesign<man_kzonesign>`,
+ and :doc:`knsec3hash<man_knsec3hash>` are located in a new ``knot-dnssecutils``
+ package.
+
+Python
+------
+
+- Compatibility with Python 2 was removed.
+
+.. _Upgrade 3.2.x to 3.3.x:
+
+Upgrade 3.2.x to 3.3.x
+======================
+
+There are some changes between Knot DNS versions 3.3.x and 3.2.x that should be
+taken into consideration before upgrading.
+
+Configuration changes
+---------------------
+
+- The configuration option ``xdp_quic-log`` has been replaced with a more general
+ logging option :ref:`log_quic`, which applies to both conventional QUIC and
+ QUIC over XDP.
+
+Functionality
+-------------
+
+- Responses to forwarded DDNS requests are signed with the local TSIG key instead
+ of the remote one if the TSIG secret is known. To forward DDNS requests
+ signed with a locally unknown key, an ACL rule for the action ``update`` without
+ a key must be configured for the zone.
+- Addresses for the remote which is considered the source of the NOTIFY are tried
+ in the order they are specified in the remote configuration, regardless of which
+ address the NOTIFY came from.
+- Semantic checks don't allow DS record at non-delegation point.
+- The ``Version:`` prefix has been removed from the ``status version`` control output.
+- DNS over QUIC requires ``doq`` ALPN. The previous versions ``doq-i03`` and
+ ``doq-i11`` are no longer supported.
+
+XDP
+---
+
+The embedded library ``libbpf`` has been removed from the project, and an external
+one is required for the XDP support. If ``libbpf`` is version 1.0 or higher,
+an additional library ``libxdp`` is also required.
+
+Query module API change
+-----------------------
+
+The function ``knotd_qdata_local_addr()`` only takes one parameter.
+
+.. _Knot DNS for BIND users:
+
+Knot DNS for BIND users
+=======================
+
+.. _Automatic DNSSEC signing:
+
+Automatic DNSSEC signing
+------------------------
+
+Migrating automatically signed zones from BIND to Knot DNS requires copying
+up-to-date zone files from BIND, importing existing private keys, and updating
+server configuration:
+
+1. To obtain current content of the zone which is being migrated,
+ request BIND to flush the zone into the zone file: ``rndc sync
+ example.com``.
+
+ .. NOTE::
+ If dynamic updates (DDNS) are enabled for the given zone, you
+ might need to freeze the zone before flushing it. That can be done
+ similarly::
+
+ $ rndc freeze example.com
+
+2. Copy the fresh zone file into the zones :ref:`storage<zone_storage>`
+ directory of Knot DNS.
+
+3. Import all existing zone keys into the KASP database. Make sure that all
+ the keys were imported correctly::
+
+ $ keymgr example.com. import-bind path/to/Kexample.com.+013+11111
+ $ keymgr example.com. import-bind path/to/Kexample.com.+013+22222
+ $ ...
+ $ keymgr example.com. list
+
+ .. NOTE::
+ If the server configuration file or database is not at the default location,
+ add a configuration parameter (-c or -C). See :doc:`keymgr<man_keymgr>`
+ for more info about required access rights to the key files.
+
+4. Follow :ref:`Automatic DNSSEC signing` steps to configure DNSSEC signing.
diff --git a/doc/modules.rst.in b/doc/modules.rst.in
new file mode 100644
index 0000000..727e9e0
--- /dev/null
+++ b/doc/modules.rst.in
@@ -0,0 +1,8 @@
+.. highlight:: none
+.. _Modules:
+
+*******
+Modules
+*******
+
+@DOC_MODULES@
diff --git a/doc/operation.rst b/doc/operation.rst
new file mode 100644
index 0000000..f953719
--- /dev/null
+++ b/doc/operation.rst
@@ -0,0 +1,1387 @@
+.. highlight:: none
+.. _Operation:
+
+*********
+Operation
+*********
+
+The Knot DNS server part :doc:`knotd<man_knotd>` can run either in the foreground,
+or in the background using the ``-d`` option. When run in the foreground, it
+doesn't create a PID file. Other than that, there are no differences and you
+can control both the same way.
+
+The tool :doc:`knotc<man_knotc>` is designed as a user front-end, making it easier
+to control a running server daemon. If you want to control the daemon directly,
+use ``SIGINT`` to quit the process or ``SIGHUP`` to reload the configuration.
+
+If you pass neither configuration file (``-c`` parameter) nor configuration
+database (``-C`` parameter), the server will first attempt to use the default
+configuration database stored in ``/var/lib/knot/confdb`` or the
+default configuration file stored in ``/etc/knot/knot.conf``. Both the
+default paths can be reconfigured with ``--with-storage=path`` or
+``--with-configdir=path`` respectively.
+
+Example of server start as a daemon::
+
+ $ knotd -d -c knot.conf
+
+Example of server shutdown::
+
+ $ knotc -c knot.conf stop
+
+For a complete list of actions refer to the program help (``-h`` parameter)
+or to the corresponding manual page.
+
+Also, the server needs to create :ref:`server_rundir` and :ref:`zone_storage`
+directories in order to run properly.
+
+.. _Configuration database:
+
+Configuration database
+======================
+
+In the case of a huge configuration file, the configuration can be stored
+in a binary database. Such a database can be simply initialized::
+
+ $ knotc conf-init
+
+or preloaded from a file::
+
+ $ knotc conf-import input.conf
+
+Also the configuration database can be exported into a textual file::
+
+ $ knotc conf-export output.conf
+
+.. WARNING::
+ The import and export commands access the configuration database
+ directly, without any interaction with the server. Therefore, any data
+ not yet committed to the database won't be exported. And the server won't
+ reflect imported configuration correctly. So it is strictly recommended to
+ import new configuration when the server is not running.
+
+.. _Dynamic configuration:
+
+Dynamic configuration
+=====================
+
+The configuration database can be accessed using the server control interface
+while the server is running. To get the full power of the dynamic configuration,
+the server must be started with a specified configuration database location
+or with the default database initialized. Otherwise all the changes to the
+configuration will be temporary (until the server is stopped).
+
+.. NOTE::
+ The database can be :ref:`imported<Configuration database>` in advance.
+
+Most of the commands get an item name and value parameters. The item name is
+in the form of ``section[identifier].name``. If the item is multivalued,
+more values can be specified as individual (command line) arguments.
+
+.. CAUTION::
+ Beware of the possibility of pathname expansion by the shell. For this reason,
+ it is advisable to escape (with backslash) square brackets or to quote command parameters if
+ not executed in the interactive mode.
+
+To get the list of configuration sections or to get the list of section items::
+
+ $ knotc conf-list
+ $ knotc conf-list 'server'
+
+To get the whole configuration or to get the whole configuration section or
+to get all section identifiers or to get a specific configuration item::
+
+ $ knotc conf-read
+ $ knotc conf-read 'remote'
+ $ knotc conf-read 'zone.domain'
+ $ knotc conf-read 'zone[example.com].master'
+
+.. WARNING::
+ The following operations don't work on OpenBSD!
+
+Modifying operations require an active configuration database transaction.
+Just one transaction can be active at a time. Such a transaction then can
+be aborted or committed. A semantic check is executed automatically before
+every commit::
+
+ $ knotc conf-begin
+ $ knotc conf-abort
+ $ knotc conf-commit
+
+To set a configuration item value or to add more values or to add a new
+section identifier or to add a value to all identified sections::
+
+ $ knotc conf-set 'server.identity' 'Knot DNS'
+ $ knotc conf-set 'server.listen' '0.0.0.0@53' '::@53'
+ $ knotc conf-set 'zone[example.com]'
+ $ knotc conf-set 'zone.slave' 'slave2'
+
+.. NOTE::
+ Also the include operation can be performed. A non-absolute file
+ location is relative to the server binary path, not to the control binary
+ path!
+
+ ::
+
+ $ knotc conf-set 'include' '/tmp/new_zones.conf'
+
+To unset the whole configuration or to unset the whole configuration section
+or to unset an identified section or to unset an item or to unset a specific
+item value::
+
+ $ knotc conf-unset
+ $ knotc conf-unset 'zone'
+ $ knotc conf-unset 'zone[example.com]'
+ $ knotc conf-unset 'zone[example.com].master'
+ $ knotc conf-unset 'zone[example.com].master' 'remote2' 'remote5'
+
+To get the change between the current configuration and the active transaction
+for the whole configuration or for a specific section or for a specific
+identified section or for a specific item::
+
+ $ knotc conf-diff
+ $ knotc conf-diff 'zone'
+ $ knotc conf-diff 'zone[example.com]'
+ $ knotc conf-diff 'zone[example.com].master'
+
+.. CAUTION::
+ While it is possible to change most of the configuration parameters
+ dynamically or via configuration file reload, a few of the parameters
+ in the section ``server`` require restarting the server, such that the changes
+ take effect. These parameters are:
+ :ref:`rundir<server_rundir>`,
+ :ref:`user<server_user>`,
+ :ref:`pidfile<server_pidfile>`,
+ :ref:`tcp-reuseport<server_tcp-reuseport>`,
+ :ref:`udp-workers<server_udp-workers>`,
+ :ref:`tcp-workers<server_tcp-workers>`,
+ :ref:`background-workers<server_background-workers>`, and
+ :ref:`listen<server_listen>`.
+
+An example of possible configuration initialization::
+
+ $ knotc conf-begin
+ $ knotc conf-set 'server.listen' '0.0.0.0@53' '::@53'
+ $ knotc conf-set 'remote[master_server]'
+ $ knotc conf-set 'remote[master_server].address' '192.168.1.1'
+ $ knotc conf-set 'template[default]'
+ $ knotc conf-set 'template[default].storage' '/var/lib/knot/zones/'
+ $ knotc conf-set 'template[default].master' 'master_server'
+ $ knotc conf-set 'zone[example.com]'
+ $ knotc conf-diff
+ $ knotc conf-commit
+
+.. _Secondary mode:
+
+Secondary (slave) mode
+======================
+
+Running the server as a secondary is very straightforward as the zone
+is transfered automatically from a remote server. The received zone is
+usually stored in a zone file after the :ref:`zone_zonefile-sync` period
+elapses. Zone differences are stored in the :ref:`zone journal <Journal behaviour>`.
+
+.. _Primary mode:
+
+Primary (master) mode
+=====================
+
+If you just want to check the zone files before starting, you can use::
+
+ $ knotc zone-check example.com
+
+.. _Editing zones:
+
+Reading and editing zones
+=========================
+
+Knot DNS allows you to read or change zone contents online using the server
+control interface.
+
+.. WARNING::
+ Avoid concurrent zone access when a zone event (zone file load, refresh,
+ DNSSEC signing, dynamic update) is in progress or pending. In such a case
+ zone events must be frozen before. For more information on how to freeze the
+ zone read :ref:`Editing zone file`.
+
+To get contents of all configured zones, or a specific zone contents, or zone
+records with a specific owner, or even with a specific record type::
+
+ $ knotc zone-read --
+ $ knotc zone-read example.com
+ $ knotc zone-read example.com ns1
+ $ knotc zone-read example.com ns1 NS
+
+.. NOTE::
+ If the record owner is not a fully qualified domain name, then it is
+ considered as a relative name to the zone name.
+
+To start a writing transaction on all zones or on specific zones::
+
+ $ knotc zone-begin --
+ $ knotc zone-begin example.com example.net
+
+Now you can list all nodes within the transaction using the ``zone-get``
+command, which always returns current data with all changes included. The
+command has the same syntax as ``zone-read``.
+
+Within the transaction, you can add a record to a specific zone or to all
+zones with an open transaction::
+
+ $ knotc zone-set example.com ns1 3600 A 192.168.0.1
+ $ knotc zone-set -- ns1 3600 A 192.168.0.1
+
+To remove all records with a specific owner, or a specific rrset, or
+specific record data::
+
+ $ knotc zone-unset example.com ns1
+ $ knotc zone-unset example.com ns1 A
+ $ knotc zone-unset example.com ns1 A 192.168.0.2
+
+To see the difference between the original zone and the current version::
+
+ $ knotc zone-diff example.com
+
+Finally, either commit or abort your transaction::
+
+ $ knotc zone-commit example.com
+ $ knotc zone-abort example.com
+
+A full example of setting up a completely new zone from scratch::
+
+ $ knotc conf-begin
+ $ knotc conf-set zone.domain example.com
+ $ knotc conf-commit
+ $ knotc zone-begin example.com
+ $ knotc zone-set example.com @ 3600 SOA ns admin 1 86400 900 691200 3600
+ $ knotc zone-set example.com @ 3600 NS ns
+ $ knotc zone-set example.com ns 3600 A 192.168.0.1
+ $ knotc zone-set example.com ns 3600 AAAA 2001:DB8::1
+ $ knotc zone-commit example.com
+
+.. NOTE::
+ If quotes are necessary for record data specification, remember to escape them::
+
+ $ knotc zone-set example.com @ 3600 TXT \"v=spf1 a:mail.example.com -all\"
+
+.. _Editing zone file:
+
+Reading and editing the zone file safely
+========================================
+
+It's always possible to read and edit zone contents via zone file manipulation.
+It may lead to confusion, however, if the zone contents are continuously being
+changed by DDNS, DNSSEC signing and the like. In such a case, the safe way to
+modify the zone file is to freeze zone events first::
+
+ $ knotc -b zone-freeze example.com.
+ $ knotc -b zone-flush example.com.
+
+After calling freeze on the zone, there still may be running zone operations (e.g. signing),
+causing freeze pending. Because of this, the blocking mode is used to ensure
+the operation was finished. Then the zone can be flushed to a file.
+
+Now the zone file can be safely modified (e.g. using a text editor).
+If :ref:`zone_zonefile-load` is not set to `difference-no-serial`, it's also necessary to
+**increase SOA serial** in this step to keep consistency. Finally, we can load the
+modified zone file and if successful, thaw the zone::
+
+ $ knotc -b zone-reload example.com.
+ $ knotc zone-thaw example.com.
+
+.. _Zone loading:
+
+Zone loading
+============
+
+The process of how the server loads a zone is influenced by the configuration of the
+:ref:`zonefile-load <zone_zonefile-load>` and :ref:`journal-content <zone_journal-content>`
+parameters (also DNSSEC signing applies), the existence of a zone file and journal
+(and their relative out-of-dateness), and whether it is a cold start of the server
+or a zone reload (e.g. invoked by the :doc:`knotc<man_knotc>` interface). Please note
+that zone transfers are not taken into account here – they are planned after the zone
+is loaded (including :ref:`zone bootstrap<Zone bootstrap>`).
+
+If the zone file exists and is not excluded by the configuration, it is first loaded
+and according to its SOA serial number, relevant journal changesets are applied.
+If this is a zone reload and we have :ref:`zone_zonefile-load` set to `difference`, the difference
+between old and new contents is computed and stored in the journal like an update.
+The zone file should be either unchanged since last load or changed with incremented
+SOA serial. In the case of a decreased SOA serial, the load is interrupted with
+an error; if unchanged, it is increased by the server.
+
+If the procedure described above succeeds without errors, the resulting zone contents are (after potential DNSSEC signing)
+used as the new zone.
+
+The option :ref:`zone_journal-content` set to `all` lets the server, beside better performance, keep
+track of the zone contents also across server restarts. It makes the cold start
+effectively work like a zone reload with the old contents loaded from the journal
+(unless this is the very first start with the zone not yet saved into the journal).
+
+.. _Journal behaviour:
+
+Journal behaviour
+=================
+
+The zone journal keeps some history of changes made to the zone. It is useful for
+responding to IXFR queries. Also if :ref:`zone file flush <zone_zonefile-sync>` is disabled, the
+journal keeps the difference between the zone file and the current zone in case of server shutdown.
+The history is stored in changesets – differences of zone contents between two
+(usually subsequent) zone versions (specified by SOA serials).
+
+Journals of all zones are stored in a common LMDB database. Huge changesets are
+split into 15-70 KiB [#fn-hc]_ blocks to prevent fragmentation of the DB. The
+journal does each operation in one transaction to keep consistency of the DB and performance.
+
+Each zone journal has its own occupation limits :ref:`maximum usage <zone_journal-max-usage>`
+and :ref:`maximum depth <zone_journal-max-depth>`. Changesets are stored in the journal
+one by one. When hitting any of the limits, the zone is flushed into the zone file
+if there are no redundant changesets to delete, and the oldest changesets are deleted.
+In the case of the size limit, twice [#fn-hc]_ the needed amount of space is purged
+to prevent overly frequent deletes.
+
+If :ref:`zone file flush <zone_zonefile-sync>` is disabled, then instead of flushing
+the zone, the journal tries to save space by merging the changesets into a special one.
+This approach is effective if the changes rewrite each other, e.g. periodically
+changing the same zone records, re-signing the whole zone etc. Thus the difference between the zone
+file and the zone is still preserved even if the journal deletes some older changesets.
+
+If the journal is used to store both zone history and contents, a special changeset
+is present with zone contents. When the journal gets full, the changes are merged into this
+special changeset.
+
+There is also a :ref:`safety hard limit <database_journal-db-max-size>` for overall
+journal database size, but it's strongly recommended to set the per-zone limits in
+a way to prevent hitting this one. For LMDB, it's hard to recover from the
+database-full state. For wiping one zone's journal, see *knotc zone-purge +journal*
+command.
+
+.. [#fn-hc] This constant is hardcoded.
+
+.. _Handling, zone file, journal, changes, serials:
+
+Handling zone file, journal, changes, serials
+=============================================
+
+Some configuration options regarding the zone file and journal, together with operation
+procedures, might lead to unexpected results. This chapter points out
+potential interference and both recommends and warns before some combinations thereof.
+Unfortunately, there is no optimal combination of configuration options,
+every approach has some disadvantages.
+
+Example 1
+---------
+
+Keep the zone file updated::
+
+ zonefile-sync: 0
+ zonefile-load: whole
+ journal-content: changes
+
+These are default values. The user can always check the current zone
+contents in the zone file, and also modify it (recommended with server turned-off or
+taking the :ref:`safe way<Editing zone file>`). The journal serves here just as a source of
+history for secondary servers' IXFR. Some users dislike that the server overwrites their
+prettily prepared zone file.
+
+Example 2
+---------
+
+Zonefileless setup::
+
+ zonefile-sync: -1
+ zonefile-load: none
+ journal-content: all
+
+Zone contents are stored only in the journal. The zone is updated by DDNS,
+zone transfer, or via the control interface. The user might have filled the
+zone contents initially from a zone file by setting :ref:`zone_zonefile-load` to
+`whole` temporarily.
+It's also a good setup for secondary servers. Anyway, it's recommended to carefully tune
+the journal-size-related options to avoid surprises like the journal getting full
+(see :ref:`Journal behaviour`).
+
+Example 3
+---------
+
+Input-only zone file::
+
+ zonefile-sync: -1
+ zonefile-load: difference
+ journal-content: changes
+
+The user can make changes to the zone by editing the zone file, and his pretty zone file
+is never overwritten or filled with DNSSEC-related autogenerated records – they are
+only stored in the journal.
+
+.. WARNING::
+ The zone file's SOA serial must be properly set to a number which is higher than the
+ current SOA serial in the zone (not in the zone file) if manually updated!
+ This is important to ensure consistency of the journal and outgoing IXFR.
+
+Example 4
+---------
+
+Auto-increment SOA serial::
+
+ zonefile-sync: -1
+ zonefile-load: difference-no-serial
+ journal-content: all
+
+This is similar to the previous setup, but the SOA serial is handled by the server
+automatically. So the user no longer needs to care about it in the zone file.
+
+However, this requires setting :ref:`zone_journal-content` to `all` so that
+the information about the last real SOA serial is preserved in case of server re-start.
+The sizing of journal limits needs to be taken into consideration
+(see :ref:`Journal behaviour`).
+
+.. _Zone bootstrap:
+
+Zone bootstrapping on secondary
+===============================
+
+When zone refresh from the primary fails, the ``retry`` value from SOA is used
+as the interval between refresh attempts. In a case that SOA isn't known to the
+secondary (either because the zone hasn't been retrieved from the primary yet,
+or the zone has expired), a backoff is used for repeated retry attempts.
+
+With every retry, the delay rises as a quadratic polynomial (5 * n^2, where n
+represents the sequence number of the retry attempt) up to two hours, each time
+with a random delay of 0 to 30 seconds added to spread the load on the primary.
+In each attempt, the retry interval is subject to :ref:`zone_retry-min-interval`
+and :ref:`zone_retry-max-interval`.
+
+Until the refresh has been successfully completed, the backoff is restarted from
+the beginning by every ``zone-refresh`` or ``zone-retransfer`` of the zone
+triggered manually via :doc:`knotc<man_knotc>`, by ``zone-purge`` or
+``zone-restore`` of the zone's timers, or by a restart of :doc:`knotd<man_knotd>`.
+
+.. _Zone expiration:
+
+Zone expiration
+===============
+
+On a primary, zone normally never expires. On a secondary, zone expiration results
+in removal of the current zone contents and a trigger of immediate zone refresh.
+The zone file and zone's journal are kept, but not used for answering requests
+until the refresh is successfully completed.
+
+The zone expire timer is set according to the zone's SOA expire field. In addition
+to it, Knot DNS also supports EDNS EXPIRE extension of the expire timer in both
+primary and secondary roles as described in :rfc:`7314`.
+
+When Knot DNS is configured as a secondary, EDNS EXPIRE option present in a SOA,
+IXFR, or AFXR response from the primary is processed and used to update the zone
+timer when necessary. This functionality (together with requests of any other EDNS
+options) for a specified primary may be disabled using the :ref:`remote_no-edns`
+configuration parameter.
+
+If it's necessary, any zone may be expired manually using the ``zone-purge``
+command of the :doc:`knotc<man_knotc>` utility. Manual expiration is applicable
+to any zone, including a catalog zone or a zone on a primary. Beware, a manually
+expired zone on a primary or a manually expired catalog zone becomes valid again
+after a server configuration is reloaded or the :doc:`knotd<man_knotd>` process
+is restarted, provided that the zone data hasn't been removed.
+
+.. _DNSSEC Key states:
+
+DNSSEC key states
+=================
+
+During its lifetime, a DNSSEC key finds itself in different states. Most of the time it
+is used for signing the zone and published in the zone. In order to exchange
+the key, one type of a key rollover is necessary, and during this rollover,
+the key goes through various states with respect to the rollover type and also the
+state of the other key being rolled-over.
+
+First, let's list the states of the key being rolled-in.
+
+Standard states:
+
+- ``active`` — The key is used for signing.
+- ``published`` — The key is published in the zone, but not used for signing. If the key is
+ a KSK or CSK, it is used for signing the DNSKEY RRSet.
+- ``ready`` (only for KSK) — The key is published in the zone and used for signing. The
+ old key is still active, since we are waiting for the DS records in the parent zone to be
+ updated (i.e. "KSK submission").
+
+Special states for algorithm rollover:
+
+- ``pre-active`` — The key is not yet published in the zone, but it's used for signing the zone.
+- ``published`` — The key is published in the zone, and it's still used for signing since the
+ pre-active state.
+
+Second, we list the states of the key being rolled-out.
+
+Standard states:
+
+- ``retire-active`` — The key is still used for signing, and is published in the zone, waiting for
+ the updated DS records in parent zone to be acked by resolvers (KSK case) or synchronizing
+ with KSK during algorithm rollover (ZSK case).
+- ``retired`` — The key is no longer used for signing. If ZSK, the key is still published in the zone.
+- ``removed`` — The key is not used in any way (in most cases such keys are deleted immediately).
+
+Special states for algorithm rollover:
+
+- ``post-active`` — The key is no longer published in the zone, but still used for signing.
+
+Special states for :rfc:`5011` trust anchor roll-over
+
+- ``revoke`` (only for KSK) — The key is published and used for signing, and the Revoked flag is set.
+
+.. NOTE::
+ Trust anchor roll-over is not implemented with automatic key management.
+
+ The ``revoke`` state can only be established using :doc:`keymgr<man_keymgr>` when using
+ :ref:`dnssec-manual-key-management`.
+
+The states listed above are relevant for :doc:`keymgr<man_keymgr>` operations like generating
+a key, setting its timers and listing KASP database.
+
+Note that the key "states" displayed in the server log lines while zone signing
+are not according to those listed above, but just a hint as to what the key is currently used for
+(e.g. "public, active" = key is published in the zone and used for signing).
+
+.. _DNSSEC Key rollovers:
+
+DNSSEC key rollovers
+====================
+
+This section describes the process of DNSSEC key rollover and its implementation
+in Knot DNS, and how the operator might watch and check that it's working correctly.
+The prerequisite is automatic zone signing with enabled
+:ref:`automatic key management<dnssec-automatic-ksk-management>`.
+
+The KSK and ZSK rollovers are triggered by the respective zone key getting old according
+to the settings (see :ref:`KSK<policy_ksk-lifetime>` and :ref:`ZSK<policy_zsk-lifetime>` lifetimes).
+
+The algorithm rollover starts when the policy :ref:`algorithm<policy_algorithm>`
+field is updated to a different value.
+
+The signing scheme rollover happens when the policy :ref:`signing scheme<policy_single-type-signing>`
+field is changed.
+
+It's also possible to change the algorithm and signing scheme in one rollover.
+
+The operator may check the next rollover phase time by watching the next zone signing time,
+either in the log or via ``knotc zone-status``. There is no special log for finishing a rollover.
+
+.. NOTE::
+ There are never two key rollovers running in parallel for one zone. If
+ a rollover is triggered while another is in progress, it waits until the
+ first one is finished. Note that a rollover might be considered finished
+ when the old key is retired or waiting to be deleted.
+
+The ZSK rollover is performed with Pre-publish method, KSK rollover uses Double-Signature
+scheme, as described in :rfc:`6781`.
+
+.. _Automatic KSK and ZSK rollovers example:
+
+Automatic KSK and ZSK rollovers example
+---------------------------------------
+
+Let's start with the following set of keys::
+
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, key, tag 50613, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, key, tag 62932, algorithm ECDSAP256SHA256, public, active
+
+The last fields hint the key state: ``public`` denotes a key that will be presented
+as the DNSKEY record, ``ready`` means that CDS/CDNSKEY records were created,
+``active`` tells us that the key is used for signing, while ``active+`` is an
+active key undergoing a roll-over or roll-in.
+
+For demonstration purposes, the following configuration is used::
+
+ submission:
+ - id: test_submission
+ check-interval: 2s
+ parent: dnssec_validating_resolver
+
+ policy:
+ - id: test_policy
+ ksk-lifetime: 5m
+ zsk-lifetime: 2m
+ propagation-delay: 2s
+ dnskey-ttl: 10s
+ zone-max-ttl: 15s
+ ksk-submission: test_submission
+
+Upon the zone's KSK lifetime expiration, a new KSK is generated and the rollover
+continues along the lines of :rfc:`6781#section-4.1.2`::
+
+ # KSK Rollover (50613 -> 9081)
+
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, KSK rollover started
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, key, tag 50613, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, key, tag 62932, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active+
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:50:00+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:50:12+0200
+
+ ... (propagation-delay + dnskey-ttl) ...
+
+ 2021-05-10T20:50:12+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:50:12+0200 notice: [example.com.] DNSSEC, KSK submission, waiting for confirmation
+ 2021-05-10T20:50:12+0200 info: [example.com.] DNSSEC, key, tag 50613, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:50:12+0200 info: [example.com.] DNSSEC, key, tag 62932, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:50:12+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, ready, active+
+ 2021-05-10T20:50:12+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:50:12+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:50:12+0200 info: [example.com.] DNSSEC, next signing at 2021-05-17T20:49:56+0200
+
+At this point the new KSK has to be submitted to the parent zone. Knot detects the updated parent's DS
+record automatically (and waits for additional period of the DS's TTL before retiring the old key)
+if :ref:`parent DS check<Submission section>` is configured, otherwise the
+operator must confirm it manually (using ``knotc zone-ksk-submitted``)::
+
+ 2021-05-10T20:50:12+0200 info: [example.com.] DS check, outgoing, remote 127.0.0.1@5300, KSK submission check: negative
+ 2021-05-10T20:50:14+0200 info: [example.com.] DS check, outgoing, remote 127.0.0.1@5300, KSK submission check: negative
+ 2021-05-10T20:50:16+0200 info: [example.com.] DS check, outgoing, remote 127.0.0.1@5300, KSK submission check: positive
+ 2021-05-10T20:50:16+0200 notice: [example.com.] DNSSEC, KSK submission, confirmed
+ 2021-05-10T20:50:16+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:50:16+0200 info: [example.com.] DNSSEC, key, tag 50613, algorithm ECDSAP256SHA256, KSK, public, active+
+ 2021-05-10T20:50:16+0200 info: [example.com.] DNSSEC, key, tag 62932, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:50:16+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:50:16+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:50:16+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:50:16+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:50:23+0200
+
+ ... (parent's DS TTL is 7 seconds) ...
+
+ 2021-05-10T20:50:23+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:50:23+0200 info: [example.com.] DNSSEC, key, tag 62932, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:50:23+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:50:23+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:50:23+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:50:23+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:51:56+0200
+
+Upon the zone's ZSK lifetime expiration, a new ZSK is generated and the rollover
+continues along the lines of :rfc:`6781#section-4.1.1`::
+
+ # ZSK Rollover (62932 -> 33255)
+
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, ZSK rollover started
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, key, tag 62932, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, key, tag 33255, algorithm ECDSAP256SHA256, public
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:51:56+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:52:08+0200
+
+ ... (propagation-delay + dnskey-ttl) ...
+
+ 2021-05-10T20:52:08+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:52:08+0200 info: [example.com.] DNSSEC, key, tag 62932, algorithm ECDSAP256SHA256, public
+ 2021-05-10T20:52:08+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:52:08+0200 info: [example.com.] DNSSEC, key, tag 33255, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:52:08+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:52:08+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:52:08+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:52:25+0200
+
+ ... (propagation-delay + zone-max-ttl) ...
+
+ 2021-05-10T20:52:25+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:52:25+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:52:25+0200 info: [example.com.] DNSSEC, key, tag 33255, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:52:25+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:52:25+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:52:25+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:54:08+0200
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, signing zone
+
+Further rollovers::
+
+ ... (zsk-lifetime - propagation-delay - zone-max-ttl) ...
+
+ # Another ZSK Rollover (33255 -> 49526)
+
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, ZSK rollover started
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, key, tag 33255, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, key, tag 49526, algorithm ECDSAP256SHA256, public
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:54:08+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:54:20+0200
+
+ ...
+
+ # Another KSK Rollover (9081 -> 9179)
+
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, signing zone
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, KSK rollover started
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, key, tag 9081, algorithm ECDSAP256SHA256, KSK, public, active
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, key, tag 49526, algorithm ECDSAP256SHA256, public, active
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, key, tag 9179, algorithm ECDSAP256SHA256, KSK, public, active+
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, signing started
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, successfully signed
+ 2021-05-10T20:55:00+0200 info: [example.com.] DNSSEC, next signing at 2021-05-10T20:55:12+0200
+
+ ...
+
+.. TIP::
+ If systemd is available, the KSK submission event is logged into journald
+ in a structured way. The intended use case is to trigger a user-created script.
+ Example::
+
+ journalctl -f -t knotd -o json | python3 -c '
+ import json, sys
+ for line in sys.stdin:
+ k = json.loads(line);
+ if "KEY_SUBMISSION" in k:
+ print("%s, zone=%s, keytag=%s" % (k["__REALTIME_TIMESTAMP"], k["ZONE"], k["KEY_SUBMISSION"]))
+ '
+
+ Alternatively, the :ref:`D-Bus signaling<server_dbus-event>` can be utilized for the same use.
+
+.. _DNSSEC Shared KSK:
+
+DNSSEC shared KSK
+=================
+
+Knot DNS allows, with automatic DNSSEC key management, to configure a shared KSK for multiple zones.
+By enabling :ref:`policy_ksk-shared`, we tell Knot to share all newly-created KSKs
+among all the zones with the same :ref:`DNSSEC signing policy<Policy section>` assigned.
+
+The feature works as follows. Each zone still manages its keys separately. If a new KSK shall be
+generated for the zone, it first checks if it can grab another zone's shared KSK instead -
+that is the last generated KSK in any of the zones with the same policy assigned.
+Anyway, only the cryptographic material is shared, the key may have different timers
+in each zone.
+
+.. rubric:: Consequences:
+
+If we have an initial setting with brand new zones without any DNSSEC keys,
+the initial keys for all zones are generated. With shared KSK, they will all have the same KSK,
+but different ZSKs. The KSK rollovers may take place at slightly different times for each of the zones,
+but the resulting new KSK will be shared again among all of them.
+
+If we have zones which already have their keys, turning on the shared KSK feature triggers no action.
+But when a KSK rollover takes place, they will use the same new key afterwards.
+
+.. WARNING::
+ Changing the policy :ref:`id<policy_id>` must be done carefully if shared
+ KSK is in use.
+
+.. _DNSSEC Delete algorithm:
+
+DNSSEC delete algorithm
+=======================
+
+This is how to "disconnect" a signed zone from a DNSSEC-aware parent zone.
+More precisely, we tell the parent zone to remove our zone's DS record by
+publishing a special formatted CDNSKEY and CDS record. This is mostly useful
+if we want to turn off DNSSEC on our zone so it becomes insecure, but not bogus.
+
+With automatic DNSSEC signing and key management by Knot, this is as easy as
+configuring :ref:`policy_cds-cdnskey-publish` option and reloading the configuration.
+We check if the special CDNSKEY and CDS records with the rdata "0 3 0 AA==" and "0 0 0 00",
+respectively, appeared in the zone.
+
+After the parent zone notices and reflects the change, we wait for TTL expire
+(so all resolvers' caches get updated), and finally we may do anything with the
+zone, e.g. turning off DNSSEC, removing all the keys and signatures as desired.
+
+.. _DNSSEC Offline KSK:
+
+DNSSEC Offline KSK
+==================
+
+Knot DNS allows a special mode of operation where the private part of the Key Signing Key is
+not available to the daemon, but it is rather stored securely in an offline storage. This requires
+that the KSK/ZSK signing scheme is used (i.e. :ref:`policy_single-type-signing` is off).
+The Zone Signing Key is always fully available to the daemon in order to sign common changes to the zone contents.
+
+The server (or the "ZSK side") only uses ZSK to sign zone contents and its changes. Before
+performing a ZSK rollover, the DNSKEY records will be pre-generated and signed by the
+signer (the "KSK side"). Both sides exchange keys in the form of human-readable messages with the help
+of the :doc:`keymgr<man_keymgr>` utility.
+
+Prerequisites
+-------------
+
+For the ZSK side (i.e. the operator of the DNS server), the zone has to be configured with:
+
+- Enabled :ref:`DNSSEC signing <zone_dnssec-signing>`
+- Properly configured and assigned :ref:`DNSSEC policy <Policy section>`:
+
+ - Enabled :ref:`policy_manual`
+ - Enabled :ref:`policy_offline-ksk`
+ - Explicit :ref:`policy_dnskey-ttl`
+ - Explicit :ref:`policy_zone-max-ttl`
+ - Other options are optional
+- KASP DB may contain a ZSK (the present or some previous one(s))
+
+For the KSK side (i.e. the operator of the KSK signer), the zone has to be configured with:
+
+- Properly configured and assigned :ref:`DNSSEC policy <Policy section>`:
+
+ - Enabled :ref:`policy_manual`
+ - Enabled :ref:`policy_offline-ksk`
+ - Explicit :ref:`policy_rrsig-refresh`
+ - Optional :ref:`policy_rrsig-lifetime`, :ref:`policy_rrsig-pre-refresh`,
+ :ref:`policy_algorithm`, :ref:`policy_reproducible-signing`,
+ and :ref:`policy_cds-cdnskey-publish`
+ - Other options are ignored
+- KASP DB contains a KSK (the present or a newly generated one)
+
+Generating and signing future ZSKs
+----------------------------------
+
+1. Use the ``keymgr pregenerate`` command on the ZSK side to prepare the ZSKs for a specified period of time in the future. The following example
+ generates ZSKs for the *example.com* zone for 6 months ahead starting from now::
+
+ $ keymgr -c /path/to/ZSK/side.conf example.com. pregenerate +6mo
+
+ If the time period is selected as e.g. *2 x* :ref:`policy_zsk-lifetime` *+ 4 x* :ref:`policy_propagation-delay`, it will
+ prepare roughly two complete future key rollovers. The newly-generated
+ ZSKs remain in non-published state until their rollover starts, i.e. the time
+ they would be generated in case of automatic key management.
+
+2. Use the ``keymgr generate-ksr`` command on the ZSK side to export the public parts of the future ZSKs in a form
+ similar to DNSKEY records. You might use the same time period as in the first step::
+
+ $ keymgr -c /path/to/ZSK/side.conf example.com. generate-ksr +0 +6mo > /path/to/ksr/file
+
+ Save the output of the command (called the Key Signing Request or KSR) to a file and transfer it to the KSK side e.g. via e-mail.
+
+3. Use the ``keymgr sign-ksr`` command on the KSK side with the KSR file from the previous step as a parameter::
+
+ $ keymgr -c /path/to/KSK/side.conf example.com. sign-ksr /path/to/ksr/file > /path/to/skr/file
+
+ This creates all the future forms of the DNSKEY, CDNSKEY and CSK records and all the respective RRSIGs and prints them on output. Save
+ the output of the command (called the Signed Key Response or SKR) to a file and transfer it back to the ZSK side.
+
+4. Use the ``keymgr import-skr`` command to import the records and signatures from the SKR file generated in the last step
+ into the KASP DB on the ZSK side::
+
+ $ keymgr -c /path/to/ZSK/side.conf example.com. import-skr /path/to/skr/file
+
+5. Use the ``knotc zone-keys-load`` command to trigger a zone re-sign on the ZSK-side and set up the future re-signing events correctly.::
+
+ $ knotc -c /path/to/ZSK/side.conf zone-keys-load example.com.
+
+6. Now the future ZSKs and DNSKEY records with signatures are ready in KASP DB for later usage.
+ Knot automatically uses them at the correct time intervals.
+ The entire procedure must be repeated before the time period selected at the beginning passes,
+ or whenever a configuration is changed significantly. Importing new SKR over some previously-imported
+ one leads to deleting the old offline records.
+
+Offline KSK and manual ZSK management
+-------------------------------------
+
+If the automatically preplanned ZSK roll-overs (first step) are not desired, just set the :ref:`policy_zsk-lifetime`
+to zero, and manually pregenerate ZSK keys and set their timers. Then follow the steps
+``generate-ksr — sign-ksr — import-skr — zone-keys-load`` and repeat the ceremony when necessary.
+
+Offline KSK roll-over
+---------------------
+
+The KSKs (on the KSK side) must be managed manually, but manual KSK roll-over is possible. Just plan the steps
+of the KSK roll-over in advance, and whenever the KSK set or timers are changed, re-perform the relevant rest of the ceremony
+``sign-ksr — import-skr — zone-keys-load``.
+
+Emergency SKR
+-------------
+
+A general recommendation for large deployments is to have some backup pre-published keys, so that if the current ones are
+compromised, they can be rolled-over to the backup ones without any delay. But in the case of Offline KSK, according to
+the procedures above, both ZSK and KSK immediate rollovers require the KSR-SKR ceremony.
+
+However, a trick can be done to achieve really immediate key substitution. This is no longer about Knot DNS functionality,
+just a hint for the operator.
+
+The idea is to perform every KSR-SKR ceremony twice: once with normal state of the keys (the backup key is only published),
+and once with the keys already exchanged (the backup key is temporarily marked as active and the standard key temporarily
+as public only). The second (backup) SKR should be saved for emergency key replacement.
+
+Summary of the steps:
+
+* Prepare KSK and ZSK side as usual, including public-only emergency key
+* Perform normal Offline KSK ceremony:
+
+ * Pre-generate ZSKs (only in the case of automatic ZSK management)
+ * Generate KSR
+ * Sign KSR on the KSK side
+ * Import SKR
+ * Re-sign the zone
+
+* Freeze the zone on the ZSK side
+* Temporarily set the backup key as active and the normal key as publish-only
+* Perform backup Offline KSK ceremony:
+
+ * Generate KSR (only if the backup key is a replacement for ZSK)
+ * Sign the KSR on the KSK side
+ * Save the SKR to a backup storage, don't import it yet
+
+* Return the keys to the previous state
+* Thaw the zone on the ZSK side
+
+Emergency key replacement:
+
+* Import the backup SKR
+* Align the keys with the new states (backup key as active, compromised key as public)
+* Re-sign the zone
+
+.. _DNSSEC multi-signer:
+
+DNSSEC multi-signer
+===================
+
+`Multi-signer` is a general term that refers to any mode of operation in which
+a DNS zone is signed by multiple servers (usually two) in parallel.
+Knot DNS offers various multi-signer modes, which are recommended for redundancy
+within an organization. For multi-signer operations involving multiple
+"DNSSEC providers" and the ability to switch between them, you can also refer to
+`MUSIC <https://github.com/DNSSEC-Provisioning/music>`_.
+
+
+Regardless of the chosen mode from the following options, any secondary that has multiple signers
+configured as primaries must prevent interchanged IXFR from them. This can be achieved
+either by setting :ref:`master pinning <zone_master-pin-tolerance>` on every secondary or
+by setting distinct :ref:`zone_serial-modulo` on each signer. It is recommended to combine
+both approaches. Alternatively, if any of the secondaries is not Knot DNS,
+:ref:`zone_provide-ixfr` can be disabled on the signers.
+
+Sharing private keys, manual policy
+-----------------------------------
+
+When DNSSEC keys are shared among zone signing servers (signers), one challenge
+is automatic key management (roll-overs) and synchronization among the signers.
+In this example mode of operation, it is expected that key management is maintained
+outside of Knot, and the generated keys, including private keys and metadata
+(timers), are available in Bind9 format.
+
+Every new key is then imported into each Knot using the :doc:`keymgr <man_keymgr>`
+``import-bind`` command, after which :doc:`knotc <man_knotc>` ``zone-keys-load``
+is invoked. With :ref:`policy_manual` policy configured, the signers simply
+follow prescribed key timers, maintaining the same key set at each signer.
+For more useful commands like ``list``, ``set``, and ``delete``, refer
+to :doc:`keymgr <man_keymgr>`.
+
+Sharing private keys, automatic policy
+--------------------------------------
+
+Knot handles automatic key management very well, but enabling it on multiple
+instances would lead to redundant key generation. However, it's possible to enable it on one signer
+and keep synchronizing the keys to all others. The managing signer shall be configured with
+:ref:`automatic ZSK/KSK management <dnssec-automatic-zsk-management>`, all others
+with :ref:`policy_manual` policy.
+
+The key set changes on the managing signer can be monitored by periodic queries
+with :doc:`keymgr <man_keymgr>` ``list``, or by listening to
+:ref:`D-Bus <server_dbus-event>` interface and watching for the ``keys_updated`` event.
+
+Whenever the key set is changed, key synchronization can be safely performed with
+:ref:`Data and metadata backup` feature. Dump the KASP
+database on the managing signer with :doc:`knotc <man_knotc>` ``zone-backup +kaspdb``,
+transfer the backup directory to each other signer, and import the keys by
+:doc:`knotc <man_knotc>` ``zone-restore +kaspdb``, followed by ``zone-keys-load``
+on them.
+
+This way, the full key set, including private keys and all metadata, is always
+synchronized between signers. The method of transporting the backup directory
+is beyond the scope of Knot and this documentation. An eventual loss of the managing
+signer results in the automatic key management being halted, but DNSSEC signing continues
+to function. The synchronization delay for keys between the managing signer and other
+signers must be accounted for in :ref:`policy_propagation-delay`.
+
+Distinct keys, DNSKEY record synchronization
+--------------------------------------------
+
+When the DNSSEC keys are not shared among signers, each server can manage its own keys separately.
+However, the DNSKEY (including CDNSKEY and CDS) records (with public keys) must be synchronized
+for full validity of the signed zone. :ref:`Dynamic updates` can be used to achieve this sharing.
+
+The following configuration options should be used:
+
+ - Set :ref:`policy_dnskey-management` to ``incremental`` on each signer to ensure
+ it retains the other's DNSKEY records in the zone during signing.
+ - Set :ref:`policy_delete-delay` to a reasonable time interval, which ensures that
+ all signers get synchronized during this period.
+ - Set :ref:`policy_cds-cdnskey-publish` to either ``none`` or ``always``, otherwise
+ the parent DS record might configure itself to point only to one signer's KSK.
+ - Configure :ref:`policy_dnskey-sync` to all other signers so that this signer's
+ public keys appear in each other's DNSKEY (also applies to CDNSKEY and CDS) RRSets.
+ - Configure :ref:`ACL` so that DDNS from all other signers is allowed.
+ - Set :ref:`zone_ddns-master` to empty value (`""`) so that DDNS from other signers
+ is not forwarded to the primary master if any.
+ - Additionally, the synchronization delay between all signers must be accounted
+ for in :ref:`policy_propagation-delay`.
+
+With careful configuration, all signers automatically synchronize their DNSKEY (and eventually
+CDNSKEY and CDS) RRSets, keeping them synchronized during roll-overs. Nevertheless,
+it is recommended to monitor their logs.
+
+.. NOTE::
+ It is highly recommended to use this mode with only two signers. With three or more signers,
+ it often happens that they continuously overwrite each other's DNSKEYs for a long time before
+ settling down. This can be mitigated by configuring :ref:`policy_dnskey-sync` in a cyclic maner,
+ such that they form a cycle (i.e. signer1 synchronizes only to signer2, signer2 to signer3 and so on).
+ However, this in turn leads to a breakage in DNSKEY synchronization whenever any signer goes offline.
+ A practical compromise is carefully configuring the order of each signer's :ref:`policy_dnskey-sync`
+ values in the way that the "cycling" signer is at the first position and the remaining signers follow.
+
+An illustrative example of the second of three signers::
+
+ remote:
+ - id: signer1
+ address: 10.20.30.1
+ - id: signer3
+ address: 10.20.30.3
+
+ acl:
+ - id: signers
+ remote: [ signer1, signer3 ]
+ action: [ query, update ]
+ # TODO configure TSIGs!
+
+ dnskey-sync:
+ - id: sync
+ remote: [ signer3, signer1 ] # the order matters here!
+
+ policy:
+ - id: multisigner
+ single-type-signing: on
+ ksk-lifetime: 60d
+ ksk-submission: ... # TODO see Automatic KSK management
+ propagation-delay: 14h
+ delete-delay: 2h
+ cds-cdnskey-publish: always
+ dnskey-management: incremental
+ dnskey-sync: sync
+
+ zone:
+ - domain: example.com.
+ # TODO configure zonefile and journal
+ # TODO configure transfers in/out: master, NOTIFY, ACLs...
+ dnssec-signing: on
+ dnssec-policy: multisigner
+ ddns-master: ""
+ serial-modulo: 1/3
+ acl: signers
+
+Distinct keys, DNSKEY at common unsigned primary
+------------------------------------------------
+
+The same approach and configuration can be used, with the difference that the signers
+do not send updated DNSKEYs (along with CDNSKEYs and CDSs) to each other. Instead, they
+send the updates to their common primary, which holds the unsigned version of zone.
+The only configuration change involves redirecting
+:ref:`policy_dnskey-sync` to the common primary and adjusting its ACL to allow DDNS
+from the signers.
+
+It is also necessary to configure :ref:`zone_ixfr-benevolent` on each signer so that
+they accept incremental zone transfers from the primary with additions (or removals)
+of their own's DNSKEYs.
+
+This setup should work nicely with any number of signers, however, due to the size
+of DNSKEY RRSet, at most three are advisable.
+
+.. _DNSSEC keys import to HSM:
+
+DNSSEC keys import to HSM
+=========================
+
+Knot DNS stores DNSSEC keys in textual PEM format (:rfc:`7468`),
+while many HSM management software require the keys for import to be in binary
+DER format (`Rec. ITU-T X.690 <https://www.itu.int/ITU-T/recommendations/rec.aspx?rec=x.690>`_).
+Keys can be converted from one format to another by software tools such as
+``certtool`` from `GnuTLS <https://www.gnutls.org/>`_ suite or
+``openssl`` from `OpenSSL <https://www.openssl.org/>`_ suite.
+
+In the examples below, ``c4eae5dea3ee8c15395680085c515f2ad41941b6`` is used as the key ID,
+``c4eae5dea3ee8c15395680085c515f2ad41941b6.pem`` represents the filename of the key in PEM format
+as copied from the Knot DNS zone's :ref:`KASP database directory <database_kasp-db>`,
+``c4eae5dea3ee8c15395680085c515f2ad41941b6.priv.der`` represents the file containing the private
+key in DER format as generated by the conversion tool, and
+``c4eae5dea3ee8c15395680085c515f2ad41941b6.pub.der`` represents the file containing the public
+key in DER format as generated by the conversion tool.
+
+.. code-block:: console
+
+ $ certtool -V -k --outder --infile c4eae5dea3ee8c15395680085c515f2ad41941b6.pem \
+ --outfile c4eae5dea3ee8c15395680085c515f2ad41941b6.priv.der
+
+ $ certtool -V --pubkey-info --outder --load-privkey c4eae5dea3ee8c15395680085c515f2ad41941b6.pem \
+ --outfile c4eae5dea3ee8c15395680085c515f2ad41941b6.pub.der
+
+As an alternative, ``openssl`` can be used instead. It is necessary to specify either ``rsa`` or ``ec``
+command according to the algorithm used by the key.
+
+.. code-block:: console
+
+ $ openssl rsa -outform DER -in c4eae5dea3ee8c15395680085c515f2ad41941b6.pem \
+ -out c4eae5dea3ee8c15395680085c515f2ad41941b6.priv.der
+
+ $ openssl rsa -outform DER -in c4eae5dea3ee8c15395680085c515f2ad41941b6.pem \
+ -out c4eae5dea3ee8c15395680085c515f2ad41941b6.pub.der -pubout
+
+Actual import of keys (both public and private keys from the same key pair) to an HSM can be done
+via PKCS #11 interface, by ``pkcs11-tool`` from `OpenSC <https://github.com/OpenSC/OpenSC/wiki>`_ toolkit
+for example. In the example below, ``/usr/local/lib/pkcs11.so`` is used as a name of the PKCS #11 library
+or module used for communication with the HSM.
+
+.. code-block:: console
+
+ $ pkcs11-tool --module /usr/local/lib/pkcs11.so --login \
+ --write-object c4eae5dea3ee8c15395680085c515f2ad41941b6.priv.der --type privkey \
+ --usage-sign --id c4eae5dea3ee8c15395680085c515f2ad41941b6
+
+ $ pkcs11-tool --module /usr/local/lib/pkcs11.so -login \
+ --write-object c4eae5dea3ee8c15395680085c515f2ad41941b6.pub.der --type pubkey \
+ --usage-sign --id c4eae5dea3ee8c15395680085c515f2ad41941b6
+
+.. _Controlling a running daemon:
+
+Daemon controls
+===============
+
+Knot DNS was designed to allow server reconfiguration on-the-fly
+without interrupting its operation. Thus it is possible to change
+both configuration and zone files and also add or remove zones without
+restarting the server. This can be done with::
+
+ $ knotc reload
+
+If you want to refresh the secondary zones, you can do this with::
+
+ $ knotc zone-refresh
+
+.. _Data and metadata backup:
+
+Data and metadata backup
+========================
+
+Some of the zone-related data, such as zone contents or DNSSEC signing keys,
+and metadata, like zone timers, might be worth backing up. For the sake of
+consistency, it's usually necessary to shut down the server, or at least freeze all
+the zones, before copying the data like zone files, KASP database, etc, to
+a backup location. To avoid this necessity, Knot DNS provides a feature to
+back up some or all of the zones seamlessly.
+
+Online backup
+-------------
+
+While the server is running and the zones normally loaded (even when they are
+constantly/frequently being updated), the user can manually trigger the
+backup by calling::
+
+ $ knotc zone-backup +backupdir /path/of/backup
+
+To back up just some of the zones (instead of all), the user might provide
+their list::
+
+ $ knotc zone-backup +backupdir /path/to/backup zone1.com. zone2.com. ...
+
+The backup directory should be empty or non-existing and it must be accessible
+and writable for the :ref:`server_user` account under which knotd is running.
+The backup procedure will begin soon and will happen zone-by-zone
+(partially in parallel if more :ref:`server_background-workers` are configured).
+**The user shall check the logs for the outcome of each zone's backup attempt.**
+The knotc's ``-b`` parameter might be used if the user desires to wait until
+the backup work is done and a simple result status is printed out.
+
+.. TIP::
+ There is a plain ASCII text file in the backup directory,
+ ``knot_backup.label``, that contains some useful information about the
+ backup, such as the backup creation date & time, the server identity, etc.
+ Care must always be taken **not to remove this file** from the backup nor to
+ damage it.
+
+If a backup fails, the backup directory containing incomplete backup is retained.
+For repeated backup attempts to the same directory, it must be removed or renamed
+manually first.
+
+.. NOTE::
+ When backing up or restoring a catalog zone, it's necessary to make sure that
+ the contents of the catalog doesn't change during the backup or restore.
+ An easy solution is to use ``knotc zone-freeze`` on the catalog zone for the
+ time of backup and restore.
+
+Offline restore
+---------------
+
+If the Online backup was performed for all zones, it's possible to
+restore the backed up data by simply copying them to their normal locations,
+since they're simply copies. For example, the user can copy (overwrite)
+the backed up KASP database files to their configured location.
+
+This restore of course must be done when the server is stopped. After starting up
+the server, it should run in the same state as at the time of backup.
+
+This method is recommended in the case of complete data loss, for example
+physical server failure.
+
+.. NOTE::
+ The online backup procedure stores all zone files in a single directory
+ using their default file names. If the original directory layout was
+ different, then the required directory structure must be created manually
+ for offline restore and zone files must be placed individually to their
+ respective directories. If the zone file names don't follow the default
+ pattern, they must be renamed manually to match the configuration. These
+ limitations don't apply to the online restore procedure.
+
+Online restore
+--------------
+
+This procedure is symmetrical to Online backup. By calling::
+
+ $ knotc zone-restore +backupdir /path/of/backup
+
+the user triggers a one-by-one zone restore from the backup on a running
+server. Again, a subset of zones might be specified. It must be specified
+if the backup was created for only a subset of zones.
+
+.. NOTE::
+ For restore of backups that have been created by Knot DNS releases prior
+ to 3.1, it's necessary to use the ``-f`` option. Since this option also
+ turns off some verification checks, it shouldn't be used in other cases.
+
+.. NOTE::
+ For QUIC, only the auto-generated key is restored. The ``zone-restore``
+ command doesn't restore a user-defined QUIC key and certificate so as to
+ avoid possible configuration management conflicts and they must be restored
+ from the backup (its subdirectory ``quic``) manually. In all cases,
+ restart of the Knot server after the restore is necessary for the restored
+ QUIC key/certificate to take effect.
+
+Limitations
+-----------
+
+Neither configuration file nor :ref:`Configuration database` is backed up
+by zone backup. The configuration has to be synchronized before zone restore
+is performed!
+
+If the private keys are stored in a HSM (anything using a PKCS#11 interface),
+they are not backed up. This includes internal metadata of the PKCS#11 provider
+software, such as key mappings, authentication information, and the configuration
+of the provider. Details are vendor-specific.
+
+The restore procedure does not care for keys deleted after taking the snapshot.
+Thus, after restore, there might remain some redundant ``.pem`` files
+of obsolete signing keys.
+
+.. TIP::
+ In order to seamlessly deploy a restored backup of KASP DB with respect to
+ a possibly ongoing DNSSEC key rollover, it's recommended to set
+ :ref:`propagation-delay <policy_propagation-delay>` to the sum of:
+
+ - The maximum delay between beginning of the zone signing and publishing
+ re-signed zone on all public secondary servers.
+ - How long it takes for the backup server to start up with the restored data.
+ - The period between taking backup snapshots of the live environment.
+
+.. _Statistics:
+
+Statistics
+==========
+
+The server provides some general statistics and optional query module statistics
+(see :ref:`mod-stats<mod-stats>`).
+
+Server statistics or global module statistics can be shown by::
+
+ $ knotc stats
+ $ knotc stats server # Show all server counters
+ $ knotc stats mod-stats # Show all mod-stats counters
+ $ knotc stats server.zone-count # Show specific server counter
+
+Per zone statistics can be shown by::
+
+ $ knotc zone-stats example.com. # Show all zone counters
+ $ knotc zone-stats example.com. mod-stats # Show all zone mod-stats counters
+ $ knotc zone-stats example.com. mod-stats.query-type # Show specific zone counter
+ $ knotc zone-stats -- # Show all zone counters for all zones
+ $ knotc zone-stats -- mod-stats.request-protocol # Show specific zone counter for all zones
+
+To show all supported counters even with 0 value, use the force option.
+
+A simple periodic statistic dump to a YAML file can also be enabled. See
+:ref:`stats section` for the configuration details.
+
+As the statistics data can be accessed over the server control socket,
+it is possible to create an arbitrary script (Python is supported at the moment)
+which could, for example, publish the data in JSON format via HTTP(S)
+or upload the data to a more efficient time series database. Take a look into
+the python folder of the project for these scripts.
+
+.. _Mode XDP:
+
+Mode XDP
+========
+
+Thanks to recent Linux kernel capabilities, namely eXpress Data Path and AF_XDP
+address family, Knot DNS offers a high-performance DNS over UDP packet processing
+mode. The basic idea is to filter DNS messages close to the network device and
+effectively forward them to the nameserver without touching the network stack
+of the operating system. Other messages (including DNS over TCP) are processed
+as usual.
+
+If :ref:`xdp_listen` is configured, the server creates
+additional XDP workers, listening on specified interface(s) and port(s) for DNS
+over UDP queries. Each XDP worker handles one RX and TX network queue pair.
+
+.. _Mode XDP_pre-requisites:
+
+Pre-requisites
+--------------
+
+* Linux kernel 4.18+ (5.x+ is recommended for optimal performance) compiled with
+ the `CONFIG_XDP_SOCKETS=y` option. The XDP mode isn't supported in other operating systems.
+* A multiqueue network card, which offers enough Combined RX/TX channels, with
+ native XDP support is highly recommended. Successfully tested cards:
+
+ * Intel series 700 (driver `i40e`), maximum number of channels per interface is 64.
+ * Intel series 500 (driver `ixgbe`), maximum number of channels per interface is 64.
+ The number of CPUs available has to be at most 64!
+
+* If the `knotd` service is not directly executed in the privileged mode, some
+ additional Linux capabilities have to be set:
+
+ Execute command::
+
+ systemctl edit knot
+
+ And insert these lines::
+
+ [Service]
+ CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN CAP_IPC_LOCK CAP_SYS_RESOURCE
+ AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN CAP_IPC_LOCK CAP_SYS_RESOURCE
+
+ The `CAP_SYS_RESOURCE` is needed on Linux < 5.11.
+
+ All the capabilities are dropped upon the service is started.
+
+* For proper processing of VLAN traffic, VLAN offloading should be disabled. E.g.::
+
+ ethtool -K <interface> tx-vlan-offload off rx-vlan-offload off
+
+
+Optimizations
+-------------
+
+Some helpful commands::
+
+ ethtool -N <interface> rx-flow-hash udp4 sdfn
+ ethtool -N <interface> rx-flow-hash udp6 sdfn
+ ethtool -L <interface> combined <?>
+ ethtool -G <interface> rx <?> tx <?>
+ renice -n 19 -p $(pgrep '^ksoftirqd/[0-9]*$')
+
+Limitations
+-----------
+
+* Request and its response must go through the same physical network device.
+* Dynamic DNS over XDP is not supported.
+* MTU higher than 1790 bytes is not supported.
+* Multiple BPF filters per one network device are not supported.
+* Systems with big-endian byte ordering require special recompilation of the nameserver.
+* IPv4 header and UDP checksums are not verified on received DNS messages.
+* DNS over XDP traffic is not visible to common system tools (e.g. firewall, tcpdump etc.).
+* BPF filter is not automatically unloaded from the network device. Manual filter unload::
+
+ ip link set dev <interface> xdp off
diff --git a/doc/reference.rst b/doc/reference.rst
new file mode 100644
index 0000000..ad4feb9
--- /dev/null
+++ b/doc/reference.rst
@@ -0,0 +1,3050 @@
+.. highlight:: none
+.. _Configuration Reference:
+
+***********************
+Configuration Reference
+***********************
+
+.. _Description:
+
+Description
+===========
+
+Configuration files for Knot DNS use simplified YAML format. Simplified means
+that not all of the features are supported.
+
+For the description of configuration items, we have to declare a meaning of
+the following symbols:
+
+- ``INT`` – Integer
+- ``STR`` – Textual string
+- ``HEXSTR`` – Hexadecimal string (with ``0x`` prefix)
+- ``BOOL`` – Boolean value (``on``/``off`` or ``true``/``false``)
+- ``TIME`` – Number of seconds, an integer with possible time multiplier suffix
+ (``s`` ~ 1, ``m`` ~ 60, ``h`` ~ 3600 or ``d`` ~ 24 * 3600)
+- ``SIZE`` – Number of bytes, an integer with possible size multiplier suffix
+ (``B`` ~ 1, ``K`` ~ 1024, ``M`` ~ 1024^2 or ``G`` ~ 1024^3)
+- ``BASE64`` – Base64 encoded string
+- ``ADDR`` – IPv4 or IPv6 address
+- ``DNAME`` – Domain name
+- ``...`` – Multi-valued item, order of the values is preserved
+- ``[`` ``]`` – Optional value
+- ``|`` – Choice
+
+The configuration consists of several fixed sections and optional module
+sections. There are 16 fixed sections (``module``, ``server``, ``xdp``, ``control``,
+``log``, ``statistics``, ``database``, ``keystore``, ``key``, ``remote``,
+``remotes``, ``acl``, ``submission``, ``policy``, ``template``, ``zone``).
+Module sections are prefixed with the ``mod-`` prefix (e.g. ``mod-stats``).
+
+Most of the sections (e.g. ``zone``) are sequences of settings blocks. Each
+settings block begins with a unique identifier, which can be used as a reference
+from other sections (such an identifier must be defined in advance).
+
+A multi-valued item can be specified either as a YAML sequence::
+
+ address: [10.0.0.1, 10.0.0.2]
+
+or as more single-valued items each on an extra line::
+
+ address: 10.0.0.1
+ address: 10.0.0.2
+
+If an item value contains spaces or other special characters, it is necessary
+to enclose such a value within double quotes ``"`` ``"``.
+
+.. _default_paths:
+
+If not specified otherwise, an item representing a file or a directory path may
+be defined either as an absolute path (starting with ``/``), or a path relative
+to the same directory as the default value of the item.
+
+.. _Comments:
+
+Comments
+========
+
+A comment begins with a ``#`` character and is ignored during processing.
+Also each configuration section or sequence block allows a permanent
+comment using the ``comment`` item which is stored in the server beside the
+configuration.
+
+.. _including configuration:
+
+Including configuration
+=======================
+
+Another configuration file or files, matching a pattern, can be included at
+the top level in the current file.
+
+::
+
+ include: STR
+
+.. _include:
+
+include
+-------
+
+A path or a matching pattern specifying one or more files that are included
+at the place of the include option position in the configuration.
+If the path is not absolute, then it is considered to be relative to the
+current file. The pattern can be an arbitrary string meeting POSIX *glob*
+requirements, e.g. dir/\*.conf. Matching files are processed in sorted order.
+
+*Default:* not set
+
+.. _clearing configuration sections:
+
+Clearing configuration sections
+===============================
+
+It's possible to clear specified configuration sections at given phases
+of the configuration parsing.
+
+::
+
+ clear: STR
+
+.. _clear:
+
+clear
+-----
+
+A matching pattern specifying configuration sections that are cleared when
+this item is parsed. This allows overriding of existing configuration
+in the configuration database when including a configuration file or
+ensures that some configuration wasn't specified in previous includes.
+
+.. NOTE::
+ For the pattern matching the POSIX function
+ `fnmatch() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html>`_
+ is used. On Linux, the GNU extension
+ `FNM_EXTMATCH <https://www.gnu.org/software/libc/manual/html_node/Wildcard-Matching.html#index-FNM_005fEXTMATCH>`_
+ is enabled, which allows extended pattern matching.
+ Examples:
+
+ - ``clear: zone`` – Clears the ``zone`` section.
+ - ``clear: mod-*`` – Clears all module sections.
+ - ``clear: "[!z]*"`` – Clears all sections not beginning with letter ``z``.
+ - ``clear: !(zone)`` – (GNU only) Clears all sections except the ``zone`` one.
+ - ``clear: @(zone|template)`` – (GNU only) Clears the ``zone`` and ``template`` sections.
+
+*Default:* not set
+
+.. _module section:
+
+``module`` section
+==================
+
+Dynamic modules loading configuration.
+
+.. NOTE::
+ If configured with non-empty ``--with-moduledir=path`` parameter, all
+ shared modules in this directory will be automatically loaded.
+
+::
+
+ module:
+ - id: STR
+ file: STR
+
+.. _module_id:
+
+id
+--
+
+A module identifier in the form of the ``mod-`` prefix and module name suffix.
+
+.. _module_file:
+
+file
+----
+
+A path to a shared library file with the module implementation.
+
+.. WARNING::
+ If the path is not absolute, the library is searched in the set of
+ system directories. See ``man dlopen`` for more details.
+
+*Default:* ``${libdir}/knot/modules-${version}``/module_name.so
+(or ``${path}``/module_name.so if configured with ``--with-moduledir=path``)
+
+.. _server section:
+
+``server`` section
+==================
+
+General options related to the server.
+
+::
+
+ server:
+ identity: [STR]
+ version: [STR]
+ nsid: [STR|HEXSTR]
+ rundir: STR
+ user: STR[:STR]
+ pidfile: STR
+ udp-workers: INT
+ tcp-workers: INT
+ background-workers: INT
+ async-start: BOOL
+ tcp-idle-timeout: TIME
+ tcp-io-timeout: INT
+ tcp-remote-io-timeout: INT
+ tcp-max-clients: INT
+ tcp-reuseport: BOOL
+ tcp-fastopen: BOOL
+ quic-max-clients: INT
+ quic-outbuf-max-size: SIZE
+ quic-idle-close-timeout: TIME
+ remote-pool-limit: INT
+ remote-pool-timeout: TIME
+ remote-retry-delay: TIME
+ socket-affinity: BOOL
+ udp-max-payload: SIZE
+ udp-max-payload-ipv4: SIZE
+ udp-max-payload-ipv6: SIZE
+ key-file: STR
+ cert-file: STR
+ edns-client-subnet: BOOL
+ answer-rotation: BOOL
+ automatic-acl: BOOL
+ proxy-allowlist: ADDR[/INT] | ADDR-ADDR ...
+ dbus-event: none | running | zone-updated | ksk-submission | dnssec-invalid ...
+ dbus-init-delay: TIME
+ listen: ADDR[@INT] | STR ...
+ listen-quic: ADDR[@INT] ...
+
+.. CAUTION::
+ When you change configuration parameters dynamically or via configuration file
+ reload, some parameters in the Server section require restarting the Knot server
+ so that the changes take effect. See below for the details.
+
+.. _server_identity:
+
+identity
+--------
+
+An identity of the server returned in the response to the query for TXT
+record ``id.server.`` or ``hostname.bind.`` in the CHAOS class (:rfc:`4892`).
+Set to an empty value to disable.
+
+*Default:* FQDN hostname
+
+.. _server_version:
+
+version
+-------
+
+A version of the server software returned in the response to the query
+for TXT record ``version.server.`` or ``version.bind.`` in the CHAOS
+class (:rfc:`4892`). Set to an empty value to disable.
+
+*Default:* server version
+
+.. _server_nsid:
+
+nsid
+----
+
+A DNS name server identifier (:rfc:`5001`). Set to an empty value to disable.
+
+*Default:* FQDN hostname at the moment of the daemon start
+
+.. _server_rundir:
+
+rundir
+------
+
+A path for storing run-time data (PID file, unix sockets, etc.). A non-absolute
+path is relative to the :doc:`knotd<man_knotd>` startup directory.
+
+Depending on the usage of this parameter, its change may require restart of the Knot
+server to take effect.
+
+*Default:* ``${localstatedir}/run/knot`` (configured with ``--with-rundir=path``)
+
+.. _server_user:
+
+user
+----
+
+A system user with an optional system group (``user:group``) under which the
+server is run after starting and binding to interfaces. Linux capabilities
+are employed if supported.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``root:root``
+
+.. _server_pidfile:
+
+pidfile
+-------
+
+A PID file :ref:`location<default_paths>`.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* :ref:`rundir<server_rundir>`\ ``/knot.pid``
+
+.. _server_udp-workers:
+
+udp-workers
+-----------
+
+A number of UDP workers (threads) used to process incoming queries
+over UDP.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* equal to the number of online CPUs
+
+.. _server_tcp-workers:
+
+tcp-workers
+-----------
+
+A number of TCP workers (threads) used to process incoming queries
+over TCP.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* equal to the number of online CPUs, default value is at least 10
+
+.. _server_background-workers:
+
+background-workers
+------------------
+
+A number of workers (threads) used to execute background operations (zone
+loading, zone updates, etc.).
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* equal to the number of online CPUs, default value is at most 10
+
+.. _server_async-start:
+
+async-start
+-----------
+
+If enabled, server doesn't wait for the zones to be loaded and starts
+responding immediately with SERVFAIL answers until the zone loads.
+
+*Default:* ``off``
+
+.. _server_tcp-idle-timeout:
+
+tcp-idle-timeout
+----------------
+
+Maximum idle time (in seconds) between requests on an inbound TCP connection.
+It means if there is no activity on an inbound TCP connection during this limit,
+the connection is closed by the server.
+
+*Minimum:* ``1``
+
+*Default:* ``10``
+
+.. _server_tcp-io-timeout:
+
+tcp-io-timeout
+--------------
+
+Maximum time (in milliseconds) to receive or send one DNS message over an inbound
+TCP connection. It means this limit applies to normal DNS queries and replies,
+incoming DDNS, and **outgoing zone transfers**. The timeout is measured since some
+data is already available for processing.
+Set to 0 for infinity.
+
+*Default:* ``500`` (milliseconds)
+
+.. CAUTION::
+ In order to reduce the risk of Slow Loris attacks, it's recommended setting
+ this limit as low as possible on public servers.
+
+.. _server_tcp-remote-io-timeout:
+
+tcp-remote-io-timeout
+---------------------
+
+Maximum time (in milliseconds) to receive or send one DNS message over an outbound
+TCP connection which has already been established to a configured remote server.
+It means this limit applies to incoming zone transfers, sending NOTIFY,
+DDNS forwarding, and DS check or push. This timeout includes the time needed
+for a network round-trip and for a query processing by the remote.
+Set to 0 for infinity.
+
+*Default:* ``5000`` (milliseconds)
+
+.. _server_tcp-reuseport:
+
+tcp-reuseport
+-------------
+
+If enabled, each TCP worker listens on its own socket and the OS kernel
+socket load balancing is employed using SO_REUSEPORT (or SO_REUSEPORT_LB
+on FreeBSD). Due to the lack of one shared socket, the server can offer
+higher response rate processing over TCP. However, in the case of
+time-consuming requests (e.g. zone transfers of a TLD zone), enabled reuseport
+may result in delayed or not being responded client requests. So it is
+advisable to use this option on secondary servers.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``off``
+
+.. _server_tcp-fastopen:
+
+tcp-fastopen
+------------
+
+If enabled, use TCP Fast Open for outbound TCP communication (client side):
+incoming zone transfers, sending NOTIFY, and DDNS forwarding. This mode simplifies
+TCP handshake and can result in better networking performance. TCP Fast Open
+for inbound TCP communication (server side) isn't affected by this
+configuration as it's enabled automatically if supported by OS.
+
+.. NOTE::
+ The TCP Fast Open support must also be enabled on the OS level:
+
+ * Linux/macOS: ensure kernel parameter ``net.ipv4.tcp_fastopen`` is ``2`` or
+ ``3`` for server side, and ``1`` or ``3`` for client side.
+ * FreeBSD: ensure kernel parameter ``net.inet.tcp.fastopen.server_enable``
+ is ``1`` for server side, and ``net.inet.tcp.fastopen.client_enable`` is
+ ``1`` for client side.
+
+*Default:* ``off``
+
+.. _server_quic-max-clients:
+
+quic-max-clients
+----------------
+
+A maximum number of QUIC clients connected in parallel.
+
+See also :ref:`xdp_quic`.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Minimum:* ``128``
+
+*Default:* ``10000`` (ten thousand)
+
+.. _server_quic-outbuf-max-size:
+
+quic-outbuf-max-size
+--------------------
+
+Maximum cumulative size of memory used for buffers of unACKed
+sent messages. This limit is per one UDP worker.
+
+.. NOTE::
+ Set low if little memory is available (together with :ref:`server_quic-max-clients`
+ since QUIC connections are memory-heavy). Set to high value if outgoing zone
+ transfers of big zone over QUIC are expected.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Minimum:* ``1M`` (1 MiB)
+
+*Default:* ``100M`` (100 MiB)
+
+.. _server_quic-idle-close-timeout:
+
+quic-idle-close-timeout
+-----------------------
+
+Time in seconds, after which any idle QUIC connection is gracefully closed.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Minimum:* ``1``
+
+*Default:* ``4``
+
+.. _server_remote-pool-limit:
+
+remote-pool-limit
+-----------------
+
+If nonzero, the server will keep up to this number of outgoing TCP connections
+open for later use. This is an optimization to avoid frequent opening of
+TCP connections to the same remote.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``0``
+
+.. _server_remote-pool-timeout:
+
+remote-pool-timeout
+-------------------
+
+The timeout in seconds after which the unused kept-open outgoing TCP connections
+to remote servers are closed.
+
+*Default:* ``5``
+
+.. _server_remote-retry-delay:
+
+remote-retry-delay
+------------------
+
+When a connection attempt times out to some remote address, this information will be
+kept for this specified time (in milliseconds) and other connections to the same address won't
+be attempted. This prevents repetitive waiting for timeout on an unreachable remote.
+
+*Default:* ``0``
+
+.. _server_socket-affinity:
+
+socket-affinity
+---------------
+
+If enabled and if SO_REUSEPORT is available on Linux, all configured network
+sockets are bound to UDP and TCP workers in order to increase the networking performance.
+This mode isn't recommended for setups where the number of network card queues
+is lower than the number of UDP or TCP workers.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``off``
+
+.. _server_tcp-max-clients:
+
+tcp-max-clients
+---------------
+
+A maximum number of TCP clients connected in parallel, set this below the file
+descriptor limit to avoid resource exhaustion.
+
+.. NOTE::
+ It is advisable to adjust the maximum number of open files per process in your
+ operating system configuration.
+
+*Default:* one half of the file descriptor limit for the server process
+
+.. _server_udp-max-payload:
+
+udp-max-payload
+---------------
+
+Maximum EDNS0 UDP payload size default for both IPv4 and IPv6.
+
+*Default:* ``1232``
+
+.. _server_udp-max-payload-ipv4:
+
+udp-max-payload-ipv4
+--------------------
+
+Maximum EDNS0 UDP payload size for IPv4.
+
+*Default:* ``1232``
+
+.. _server_udp-max-payload-ipv6:
+
+udp-max-payload-ipv6
+--------------------
+
+Maximum EDNS0 UDP payload size for IPv6.
+
+*Default:* ``1232``
+
+.. _server_key-file:
+
+key-file
+--------
+
+Path to a server key PEM file which is used for DNS over QUIC communication.
+A non-absolute path of a user specified key file is relative to the
+:file:`@config_dir@` directory.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* auto-generated key
+
+.. _server_cert-file:
+
+cert-file
+---------
+
+Path to a server certificate PEM file which is used for DNS over QUIC communication.
+A non-absolute path is relative to the :file:`@config_dir@` directory.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* one-time in-memory certificate
+
+.. _server_edns-client-subnet:
+
+edns-client-subnet
+------------------
+
+Enable or disable EDNS Client Subnet support. If enabled, responses to queries
+containing the EDNS Client Subnet option
+always contain a valid EDNS Client Subnet option according to :rfc:`7871`.
+
+*Default:* ``off``
+
+.. _server_answer-rotation:
+
+answer-rotation
+---------------
+
+Enable or disable sorted-rrset rotation in the answer section of normal replies.
+The rotation shift is simply determined by a query ID.
+
+*Default:* ``off``
+
+.. _server_automatic-acl:
+
+automatic-acl
+-------------
+
+If enabled, :ref:`automatic ACL<remote_automatic-acl>` setting of
+configured remotes is considered when evaluating authorized operations.
+
+*Default:* ``off``
+
+.. _server_proxy-allowlist:
+
+proxy-allowlist
+---------------
+
+An ordered list of IP addresses, network subnets, or network ranges
+which are allowed as a source address of proxied DNS traffic over UDP.
+The supported proxy protocol is
+`haproxy PROXY v2 <https://www.haproxy.org/download/2.5/doc/proxy-protocol.txt>`_.
+
+.. NOTE::
+ TCP is not supported.
+
+*Default:* not set
+
+.. _server_dbus-event:
+
+dbus-event
+----------
+
+Specification of server or zone states which emit a D-Bus signal on the system
+bus. The bus name is ``cz.nic.knotd``, the object path is ``/cz/nic/knotd``, and
+the interface name is ``cz.nic.knotd.events``.
+
+Possible values:
+
+- ``none`` – No signal is emitted.
+- ``running`` – There are two possible signals emitted:
+
+ - ``started`` when the server is started and all configured zones (including
+ catalog zones and their members) are loaded or successfully bootstrapped.
+ - ``stopped`` when the server shutdown sequence is initiated.
+- ``zone-updated`` – The signal ``zone_updated`` is emitted when a zone has been updated;
+ the signal parameters are `zone name` and `zone SOA serial`.
+- ``keys-updated`` - The signal ``keys_updated`` is emitted when a DNSSEC key set
+ of this zone is updated.
+- ``ksk-submission`` – The signal ``zone_ksk_submission`` is emitted if there is
+ a ready KSK present when the zone is signed; the signal parameters are
+ `zone name`, `KSK keytag`, and `KSK KASP id`.
+- ``dnssec-invalid`` – The signal ``zone_dnssec_invalid`` is emitted when DNSSEC
+ validation fails; the signal parameter is `zone name`.
+
+.. NOTE::
+ This function requires systemd version at least 221.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``none``
+
+.. _server_dbus-init-delay:
+
+dbus-init-delay
+---------------
+
+Time in seconds which the server waits upon D-Bus initialization to ensure
+the D-Bus client is ready to receive signals.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Minimum:* ``0``
+
+*Default:* ``1``
+
+.. _server_listen:
+
+listen
+------
+
+One or more IP addresses where the server listens for incoming queries.
+Optional port specification (default is 53) can be appended to each address
+using ``@`` separator. Use ``0.0.0.0`` for all configured IPv4 addresses or
+``::`` for all configured IPv6 addresses. Filesystem path can be specified
+for listening on local unix SOCK_STREAM socket. Non-absolute path
+(i.e. not starting with ``/``) is relative to :ref:`server_rundir`.
+Non-local address binding is automatically enabled if supported by the operating system.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* not set
+
+.. _server_listen-quic:
+
+listen-quic
+-----------
+
+One or more IP addresses (and optionally ports) where the server listens
+for incoming queries over QUIC protocol.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* not set
+
+.. NOTE::
+ Incoming :ref:`DDNS<dynamic updates>` over QUIC isn't supported.
+ The server always responds with SERVFAIL.
+
+.. _xdp section:
+
+``xdp`` section
+===============
+
+Various options related to XDP listening, especially TCP.
+
+::
+
+ xdp:
+ listen: STR[@INT] | ADDR[@INT] ...
+ udp: BOOL
+ tcp: BOOL
+ quic: BOOL
+ quic-port: INT
+ tcp-max-clients: INT
+ tcp-inbuf-max-size: SIZE
+ tcp-outbuf-max-size: SIZE
+ tcp-idle-close-timeout: TIME
+ tcp-idle-reset-timeout: TIME
+ tcp-resend-timeout: TIME
+ route-check: BOOL
+
+.. CAUTION::
+ When you change configuration parameters dynamically or via configuration file
+ reload, some parameters in the XDP section require restarting the Knot server
+ so that the changes take effect.
+
+.. _xdp_listen:
+
+listen
+------
+
+One or more network device names (e.g. ``ens786f0``) on which the :ref:`Mode XDP`
+is enabled. Alternatively, an IP address can be used instead of a device name,
+but the server will still listen on all addresses belonging to the same interface!
+Optional port specification (default is 53) can be appended to each device name
+or address using ``@`` separator.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+.. CAUTION::
+ If XDP workers only process regular DNS traffic over UDP, it is strongly
+ recommended to also :ref:`listen <server_listen>` on the addresses which are
+ intended to offer the DNS service, at least to fulfil the DNS requirement for
+ working TCP.
+
+.. NOTE::
+ Incoming :ref:`DDNS<dynamic updates>` over XDP isn't supported.
+ The server always responds with SERVFAIL.
+
+*Default:* not set
+
+.. _xdp_udp:
+
+udp
+---
+
+If enabled, DNS over UDP is processed with XDP workers.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``on``
+
+.. _xdp_tcp:
+
+tcp
+---
+
+If enabled, DNS over TCP traffic is processed with XDP workers.
+
+The TCP stack limitations:
+
+ - Congestion control is not implemented.
+ - Lost packets that do not contain TCP payload may not be resend.
+ - Not optimized for transfers of non-trivial zones.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``off``
+
+.. _xdp_quic:
+
+quic
+----
+
+If enabled, DNS over QUIC is processed with XDP workers.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``off``
+
+.. _xdp_quic-port:
+
+quic-port
+---------
+
+DNS over QUIC will listen on the interfaces configured by :ref:`xdp_listen`,
+but on different port, configured by this option.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+*Default:* ``853``
+
+.. _xdp_tcp-max-clients:
+
+tcp-max-clients
+---------------
+
+A maximum number of TCP clients connected in parallel.
+
+*Minimum:* ``1024``
+
+*Default:* ``1000000`` (one million)
+
+.. _xdp_tcp-inbuf-max-size:
+
+tcp-inbuf-max-size
+------------------
+
+Maximum cumulative size of memory used for buffers of incompletely
+received messages.
+
+*Minimum:* ``1M`` (1 MiB)
+
+*Default:* ``100M`` (100 MiB)
+
+.. _xdp_tcp-outbuf-max-size:
+
+tcp-outbuf-max-size
+-------------------
+
+Maximum cumulative size of memory used for buffers of unACKed
+sent messages.
+
+*Minimum:* ``1M`` (1 MiB)
+
+*Default:* ``100M`` (100 MiB)
+
+.. _xdp_tcp-idle-close-timeout:
+
+tcp-idle-close-timeout
+----------------------
+
+Time in seconds, after which any idle connection is gracefully closed.
+
+*Minimum:* ``1``
+
+*Default:* ``10``
+
+.. _xdp_tcp-idle-reset-timeout:
+
+tcp-idle-reset-timeout
+----------------------
+
+Time in seconds, after which any idle connection is forcibly closed.
+
+*Minimum:* ``1``
+
+*Default:* ``20``
+
+.. _xdp_tcp-resend-timeout:
+
+tcp-resend-timeout
+------------------
+
+Resend outgoing data packets (with DNS response payload) if not ACKed
+before this timeout.
+
+*Minimum:* ``1``
+
+*Default:* ``5``
+
+.. _xdp_route-check:
+
+route-check
+-----------
+
+If enabled, routing information from the operating system is considered
+when processing every incoming DNS packet received over the XDP interface:
+
+- If the outgoing interface of the corresponding DNS response differs from
+ the incoming one, the packet is processed normally by UDP/TCP workers
+ (XDP isn't used).
+- If the destination address is blackholed, unreachable, or prohibited,
+ the DNS packet is dropped without any response.
+- The destination MAC address and possible VLAN tag for the response are taken
+ from the routing system.
+
+If disabled, symmetrical routing is applied. It means that the query source
+MAC address is used as a response destination MAC address. Possible VLAN tag
+is preserved.
+
+Change of this parameter requires restart of the Knot server to take effect.
+
+.. NOTE::
+ This mode requires forwarding enabled on the loopback interface
+ (``sysctl -w net.ipv4.conf.lo.forwarding=1`` and ``sysctl -w net.ipv6.conf.lo.forwarding=1``).
+ If forwarding is disabled, all incoming DNS packets are dropped!
+
+ Only VLAN 802.1Q is supported.
+
+*Default:* ``off``
+
+.. _control section:
+
+``control`` section
+===================
+
+Configuration of the server control interface.
+
+::
+
+ control:
+ listen: STR
+ timeout: TIME
+
+.. _control_listen:
+
+listen
+------
+
+A UNIX socket :ref:`path<default_paths>` where the server listens for
+control commands.
+
+*Default:* :ref:`rundir<server_rundir>`\ ``/knot.sock``
+
+.. _control_timeout:
+
+timeout
+-------
+
+Maximum time (in seconds) the control socket operations can take.
+Set to 0 for infinity.
+
+*Default:* ``5``
+
+.. _log section:
+
+``log`` section
+===============
+
+Server can be configured to log to the standard output, standard error
+output, syslog (or systemd journal if systemd is enabled) or into an arbitrary
+file.
+
+There are 6 logging severity levels:
+
+- ``critical`` – Non-recoverable error resulting in server shutdown.
+- ``error`` – Recoverable error, action should be taken.
+- ``warning`` – Warning that might require user action.
+- ``notice`` – Server notice or hint.
+- ``info`` – Informational message.
+- ``debug`` – Debug or detailed message.
+
+In the case of a missing log section, ``warning`` or more serious messages
+will be logged to both standard error output and syslog. The ``info`` and
+``notice`` messages will be logged to standard output.
+
+::
+
+ log:
+ - target: stdout | stderr | syslog | STR
+ server: critical | error | warning | notice | info | debug
+ control: critical | error | warning | notice | info | debug
+ zone: critical | error | warning | notice | info | debug
+ quic: critical | error | warning | notice | info | debug
+ any: critical | error | warning | notice | info | debug
+
+.. _log_target:
+
+target
+------
+
+A logging output.
+
+Possible values:
+
+- ``stdout`` – Standard output.
+- ``stderr`` – Standard error output.
+- ``syslog`` – Syslog or systemd journal.
+- *file\_name* – A specific file.
+
+With ``syslog`` target, syslog service is used. However, if Knot DNS has been compiled
+with systemd support and operating system has been booted with systemd, systemd journal
+is used for logging instead of syslog.
+
+A *file_name* may be specified as an absolute path or a path relative to the
+:doc:`knotd<man_knotd>` startup directory.
+
+.. _log_server:
+
+server
+------
+
+Minimum severity level for messages related to general operation of the server to be
+logged.
+
+*Default:* not set
+
+.. _log_control:
+
+control
+-------
+
+Minimum severity level for messages related to server control to be logged.
+
+*Default:* not set
+
+.. _log_zone:
+
+zone
+----
+
+Minimum severity level for messages related to zones to be logged.
+
+*Default:* not set
+
+.. _log_quic:
+
+quic
+----
+
+Minimum severity level for messages related to QUIC to be logged.
+
+*Default:* not set
+
+.. _log_any:
+
+any
+---
+
+Minimum severity level for all message types, except ``quic``, to be logged.
+
+*Default:* not set
+
+.. _stats section:
+
+``stats`` section
+=================
+
+Periodic server statistics dumping.
+
+::
+
+ statistics:
+ timer: TIME
+ file: STR
+ append: BOOL
+
+.. _statistics_timer:
+
+timer
+-----
+
+A period (in seconds) after which all available statistics metrics will by written to the
+:ref:`file<statistics_file>`.
+
+*Default:* not set
+
+.. _statistics_file:
+
+file
+----
+
+A file :ref:`path<default_paths>` of statistics output in the YAML format.
+
+*Default:* :ref:`rundir<server_rundir>`\ ``/stats.yaml``
+
+.. _statistics_append:
+
+append
+------
+
+If enabled, the output will be appended to the :ref:`file<statistics_file>`
+instead of file replacement.
+
+*Default:* ``off``
+
+.. _database section:
+
+``database`` section
+====================
+
+Configuration of databases for zone contents, DNSSEC metadata, or event timers.
+
+::
+
+ database:
+ storage: STR
+ journal-db: STR
+ journal-db-mode: robust | asynchronous
+ journal-db-max-size: SIZE
+ kasp-db: STR
+ kasp-db-max-size: SIZE
+ timer-db: STR
+ timer-db-max-size: SIZE
+ catalog-db: str
+ catalog-db-max-size: SIZE
+
+.. _database_storage:
+
+storage
+-------
+
+A data directory for storing journal, KASP, and timer databases. A non-absolute
+path is relative to the :doc:`knotd<man_knotd>` startup directory.
+
+*Default:* ``${localstatedir}/lib/knot`` (configured with ``--with-storage=path``)
+
+.. _database_journal-db:
+
+journal-db
+----------
+
+An explicit :ref:`specification<default_paths>` of the persistent journal database
+directory.
+
+*Default:* :ref:`storage<database_storage>`\ ``/journal``
+
+.. _database_journal-db-mode:
+
+journal-db-mode
+---------------
+
+Specifies journal LMDB backend configuration, which influences performance
+and durability.
+
+Possible values:
+
+- ``robust`` – The journal database disk synchronization ensures database
+ durability but is generally slower.
+- ``asynchronous`` – The journal database disk synchronization is optimized for
+ better performance at the expense of lower database durability in the case of
+ a crash. This mode is recommended on secondary servers with many zones.
+
+*Default:* ``robust``
+
+.. _database_journal-db-max-size:
+
+journal-db-max-size
+-------------------
+
+The hard limit for the journal database maximum size. There is no cleanup logic
+in journal to recover from reaching this limit. Journal simply starts refusing
+changes across all zones. Decreasing this value has no effect if it is lower
+than the actual database file size.
+
+It is recommended to limit :ref:`journal-max-usage<zone_journal-max-usage>`
+per-zone instead of :ref:`journal-db-max-size<database_journal-db-max-size>`
+in most cases. Please keep this value larger than the sum of all zones'
+journal usage limits. See more details regarding
+:ref:`journal behaviour<Journal behaviour>`.
+
+.. NOTE::
+ This value also influences server's usage of virtual memory.
+
+*Default:* ``20G`` (20 GiB), or ``512M`` (512 MiB) for 32-bit
+
+.. _database_kasp-db:
+
+kasp-db
+-------
+
+An explicit :ref:`specification<default_paths>` of the KASP database directory.
+
+*Default:* :ref:`storage<database_storage>`\ ``/keys``
+
+.. _database_kasp-db-max-size:
+
+kasp-db-max-size
+----------------
+
+The hard limit for the KASP database maximum size.
+
+.. NOTE::
+ This value also influences server's usage of virtual memory.
+
+*Default:* ``500M`` (500 MiB)
+
+.. _database_timer-db:
+
+timer-db
+--------
+
+An explicit :ref:`specification<default_paths>` of the persistent timer
+database directory.
+
+*Default:* :ref:`storage<database_storage>`\ ``/timers``
+
+.. _database_timer-db-max-size:
+
+timer-db-max-size
+-----------------
+
+The hard limit for the timer database maximum size.
+
+.. NOTE::
+ This value also influences server's usage of virtual memory.
+
+*Default:* ``100M`` (100 MiB)
+
+.. _database_catalog-db:
+
+catalog-db
+----------
+
+An explicit :ref:`specification<default_paths>` of the zone catalog
+database directory. Only useful if :ref:`catalog-zones` are enabled.
+
+*Default:* :ref:`storage<database_storage>`\ ``/catalog``
+
+.. _database_catalog-db-max-size:
+
+catalog-db-max-size
+-------------------
+
+The hard limit for the catalog database maximum size.
+
+.. NOTE::
+ This value also influences server's usage of virtual memory.
+
+*Default:* ``20G`` (20 GiB), or ``512M`` (512 MiB) for 32-bit
+
+.. _keystore section:
+
+``keystore`` section
+====================
+
+DNSSEC keystore configuration.
+
+::
+
+ keystore:
+ - id: STR
+ backend: pem | pkcs11
+ config: STR
+ key-label: BOOL
+
+.. _keystore_id:
+
+id
+--
+
+A keystore identifier.
+
+
+.. _keystore_backend:
+
+backend
+-------
+
+A key storage backend type.
+
+Possible values:
+
+- ``pem`` – PEM files.
+- ``pkcs11`` – PKCS #11 storage.
+
+*Default:* ``pem``
+
+.. _keystore_config:
+
+config
+------
+
+A backend specific configuration. A directory with PEM files (the path can
+be specified as a relative path to :ref:`kasp-db<database_kasp-db>`) or
+a configuration string for PKCS #11 storage (`<pkcs11-uri> <module-path>`).
+The PKCS #11 URI Scheme is defined in :rfc:`7512`.
+
+.. NOTE::
+ Example configuration string for PKCS #11::
+
+ "pkcs11:token=knot;pin-value=1234 /usr/lib64/pkcs11/libsofthsm2.so"
+
+*Default:* :ref:`kasp-db<database_kasp-db>`\ ``/keys``
+
+.. _keystore_key-label:
+
+key-label
+---------
+
+If enabled in combination with the PKCS #11 :ref:`keystore_backend`, generated keys
+are labeled in the form ``<zone_name> KSK|ZSK``.
+
+*Default:* ``off``
+
+.. _key section:
+
+``key`` section
+===============
+
+Shared TSIG keys used to authenticate communication with the server.
+
+::
+
+ key:
+ - id: DNAME
+ algorithm: hmac-md5 | hmac-sha1 | hmac-sha224 | hmac-sha256 | hmac-sha384 | hmac-sha512
+ secret: BASE64
+
+.. _key_id:
+
+id
+--
+
+A key name identifier.
+
+.. NOTE::
+ This value MUST be exactly the same as the name of the TSIG key on the
+ opposite primary/secondary server(s).
+
+.. _key_algorithm:
+
+algorithm
+---------
+
+A TSIG key algorithm. See
+`TSIG Algorithm Numbers <https://www.iana.org/assignments/tsig-algorithm-names/tsig-algorithm-names.xhtml>`_.
+
+Possible values:
+
+- ``hmac-md5``
+- ``hmac-sha1``
+- ``hmac-sha224``
+- ``hmac-sha256``
+- ``hmac-sha384``
+- ``hmac-sha512``
+
+*Default:* not set
+
+.. _key_secret:
+
+secret
+------
+
+Shared key secret.
+
+*Default:* not set
+
+.. _remote section:
+
+``remote`` section
+==================
+
+Definitions of remote servers for outgoing connections (source of a zone
+transfer, target for a notification, etc.).
+
+::
+
+ remote:
+ - id: STR
+ address: ADDR[@INT] | STR ...
+ via: ADDR[@INT] ...
+ quic: BOOL
+ key: key_id
+ cert-key: BASE64 ...
+ block-notify-after-transfer: BOOL
+ no-edns: BOOL
+ automatic-acl: BOOL
+
+.. _remote_id:
+
+id
+--
+
+A remote identifier.
+
+.. _remote_address:
+
+address
+-------
+
+An ordered list of destination IP addresses or UNIX socket paths which are
+used for communication with the remote server. Non-absolute path
+(i.e. not starting with ``/``) is relative to :ref:`server_rundir`.
+Optional destination port (default is 53 for UDP/TCP and 853 for QUIC)
+can be appended to the address using ``@`` separator.
+The addresses are tried in sequence until the
+remote is reached.
+
+*Default:* not set
+
+.. NOTE::
+ If the remote is contacted and it refuses to perform requested action,
+ no more addresses will be tried for this remote.
+
+.. _remote_via:
+
+via
+---
+
+An ordered list of source IP addresses which are used as source addresses
+for communication with the remote. For the N-th :ref:`remote address <remote_address>`,
+the last, but at most N-th, specified :ref:`via address<remote_via>`
+of the same family is used.
+This option can help if the server listens on more addresses.
+Optional source port (default is random) can be appended
+to the address using ``@`` separator.
+
+*Default:* not set
+
+.. NOTE::
+
+ For the following configuration:
+
+ ::
+
+ remote:
+ - id: example
+ address: [198.51.100.10, 2001:db8::10, 198.51.100.20, 2001:db8::20]
+ via: [198.51.100.1, 198.51.100.2, 2001:db8::1]
+
+ the (``via`` -> ``address``) mapping is:
+
+ - ``198.51.100.1`` -> ``198.51.100.10``
+ - ``2001:db8::1`` -> ``2001:db8::10``
+ - ``198.51.100.2`` -> ``198.51.100.20``
+ - ``2001:db8::1`` -> ``2001:db8::20``
+
+.. _remote_quic:
+
+quic
+----
+
+If this option is set, the QUIC protocol will be used for outgoing communication
+with this remote.
+
+.. NOTE::
+ One connection per each remote is opened; :ref:`server_remote-pool-limit`
+ does not take effect for QUIC. However, fast QUIC handshakes utilizing obtained
+ session tickets are used for reopening connections to recently (up to 1 day)
+ queried remotes.
+
+*Default:* ``off``
+
+.. _remote_key:
+
+key
+---
+
+A :ref:`reference<key_id>` to the TSIG key which is used to authenticate
+the communication with the remote server.
+
+*Default:* not set
+
+.. _remote_cert-key:
+
+cert-key
+--------
+
+An ordered list of remote certificate public key PINs. If the list is non-empty,
+communication with the remote is possible only via QUIC protocol and
+a peer certificate is required. The peer certificate key must match one of the
+specified PINs.
+
+A PIN is a unique identifier that represents the public key of the peer certificate.
+It's a base64-encoded SHA-256 hash of the public key. This identifier
+remains the same on a certificate renewal.
+
+*Default:* not set
+
+.. _remote_block-notify-after-transfer:
+
+block-notify-after-transfer
+---------------------------
+
+When incoming AXFR/IXFR from this remote (as a primary server), suppress
+sending NOTIFY messages to all configured secondary servers.
+
+*Default:* ``off``
+
+.. _remote_no-edns:
+
+no-edns
+-------
+
+If enabled, no OPT record (EDNS) is inserted to outgoing requests to this
+remote server. This mode is necessary for communication with some broken
+implementations (e.g. Windows Server 2016).
+
+.. NOTE::
+ This option effectively disables :ref:`zone expire<Zone expiration>` timer
+ updates via EDNS EXPIRE option specified in :rfc:`7314`.
+
+*Default:* ``off``
+
+.. _remote_automatic-acl:
+
+automatic-acl
+-------------
+
+If enabled, some authorized operations for the remote are automatically allowed
+based on the context:
+
+- Incoming NOTIFY is allowed from the remote if it's configured as a
+ :ref:`primary server <zone_master>` for the zone.
+- Outgoing zone transfer is allowed to the remote if it's configured as a
+ :ref:`NOTIFY target <zone_notify>` for the zone.
+
+Automatic ACL rules are evaluated before explicit :ref:`zone ACL <zone_acl>` configuration.
+
+.. NOTE::
+ This functionality requires global activation via
+ :ref:`server_automatic-acl` in the server section.
+
+*Default:* ``on``
+
+.. _remotes section:
+
+``remotes`` section
+===================
+
+Definitions of groups of remote servers. Remote grouping can simplify the
+configuration.
+
+::
+
+ remotes:
+ - id: STR
+ remote: remote_id ...
+
+.. _remotes_id:
+
+id
+--
+
+A remote group identifier.
+
+.. _remotes_remote:
+
+remote
+------
+
+An ordered list of :ref:`references<remote_id>` to remote server definitions.
+
+*Default:* not set
+
+.. _acl section:
+
+``acl`` section
+===============
+
+Access control list rule definitions. An ACL rule is a description of one
+or more authorized operations (zone transfer request, zone change notification,
+and dynamic DNS update) which are allowed to be processed or denied.
+
+::
+
+ acl:
+ - id: STR
+ address: ADDR[/INT] | ADDR-ADDR | STR ...
+ key: key_id ...
+ cert-key: BASE64 ...
+ remote: remote_id | remotes_id ...
+ action: query | notify | transfer | update ...
+ deny: BOOL
+ update-type: STR ...
+ update-owner: key | zone | name
+ update-owner-match: sub-or-equal | equal | sub | pattern
+ update-owner-name: STR ...
+
+.. _acl_id:
+
+id
+--
+
+An ACL rule identifier.
+
+.. _acl_address:
+
+address
+-------
+
+An ordered list of IP addresses, absolute UNIX socket paths, network subnets,
+or network ranges. The query's
+source address must match one of them. If this item is not set, address match is not
+required.
+
+*Default:* not set
+
+.. _acl_key:
+
+key
+---
+
+An ordered list of :ref:`reference<key_id>`\ s to TSIG keys. The query must
+match one of them. If this item is not set, transaction authentication is not used.
+
+*Default:* not set
+
+.. _acl_cert-key:
+
+cert-key
+--------
+
+An ordered list of remote certificate public key PINs. If the list is non-empty,
+communication with the remote is possible only via QUIC protocol and
+a peer certificate is required. The peer certificate key must match one of the
+specified PINs.
+
+A PIN is a unique identifier that represents the public key of the peer certificate.
+It's a base64-encoded SHA-256 hash of the public key. This identifier
+remains the same on a certificate renewal.
+
+*Default:* not set
+
+.. _acl_remote:
+
+remote
+------
+
+An ordered list of references :ref:`remote<remote_id>` and
+:ref:`remotes<remotes_id>`. The query must
+match one of the remotes. Specifically, one of the remote's addresses and remote's
+TSIG key if configured must match.
+
+.. NOTE::
+ This option cannot be specified along with the :ref:`acl_address` or
+ :ref:`acl_key` option at one ACL item.
+
+*Default:* not set
+
+.. _acl_action:
+
+action
+------
+
+An ordered list of allowed (or denied) actions.
+
+Possible values:
+
+- ``query`` – Allow regular DNS query. As normal queries are always allowed,
+ this action is only useful in combination with :ref:`TSIG key<acl_key>`.
+- ``notify`` – Allow incoming notify (NOTIFY).
+- ``transfer`` – Allow zone transfer (AXFR, IXFR).
+- ``update`` – Allow zone updates (DDNS).
+
+*Default:* ``query``
+
+.. _acl_deny:
+
+deny
+----
+
+If enabled, instead of allowing, deny the specified :ref:`action<acl_action>`,
+:ref:`address<acl_address>`, :ref:`key<acl_key>`, or combination if these
+items. If no action is specified, deny all actions.
+
+*Default:* ``off``
+
+.. _acl_update-type:
+
+update-type
+-----------
+
+A list of allowed types of Resource Records in a zone update. Every record in an update
+must match one of the specified types.
+
+*Default:* not set
+
+.. _acl_update-owner:
+
+update-owner
+------------
+
+This option restricts possible owners of Resource Records in a zone update by comparing
+them to either the :ref:`TSIG key<acl_key>` identity, the current zone name, or to a list of
+domain names given by the :ref:`acl_update-owner-name` option.
+The comparison method is given by the :ref:`acl_update-owner-match` option.
+
+Possible values:
+
+- ``key`` — The owner of each updated RR must match the identity of the TSIG key if used.
+- ``name`` — The owner of each updated RR must match at least one name in the
+ :ref:`acl_update-owner-name` list.
+- ``zone`` — The owner of each updated RR must match the current zone name.
+
+*Default:* not set
+
+.. _acl_update-owner-match:
+
+update-owner-match
+------------------
+
+This option defines how the owners of Resource Records in an update are matched to the domain name(s)
+set by the :ref:`acl_update-owner` option.
+
+Possible values:
+
+- ``sub-or-equal`` — The owner of each RR in an update must either be equal to
+ or be a subdomain of at least one domain name set by :ref:`acl_update-owner`.
+- ``equal`` — The owner of each updated RR must be equal to at least one domain
+ name set by :ref:`acl_update-owner`.
+- ``sub`` — The owner of each updated RR must be a subdomain of, but MUST NOT
+ be equal to at least one domain name set by :ref:`acl_update-owner`.
+- ``pattern`` — The owner of each updated RR must match a pattern specified by
+ :ref:`acl_update-owner`. The pattern can be an arbitrary FQDN or non-FQDN
+ domain name. If a label consists of one ``*`` (asterisk) character, it
+ matches any label. More asterisk labels can be specified.
+
+*Default:* ``sub-or-equal``
+
+.. _acl_update-owner-name:
+
+update-owner-name
+-----------------
+
+A list of allowed owners of RRs in a zone update used with :ref:`acl_update-owner`
+set to ``name``. Every listed owner name which is not FQDN (i.e. it doesn't end
+in a dot) is considered as if it was appended with the target zone name.
+Such a relative owner name specification allows better ACL rule reusability across
+multiple zones.
+
+*Default:* not set
+
+.. _submission section:
+
+``submission`` section
+======================
+
+Parameters of KSK submission checks.
+
+::
+
+ submission:
+ - id: STR
+ parent: remote_id | remotes_id ...
+ check-interval: TIME
+ timeout: TIME
+ parent-delay: TIME
+
+.. _submission_id:
+
+id
+--
+
+A submission identifier.
+
+.. _submission_parent:
+
+parent
+------
+
+A list of references :ref:`remote<remote_id>` and :ref:`remotes<remotes_id>`
+to parent's DNS servers to be checked for
+presence of corresponding DS records in the case of KSK submission. All of them must
+have a corresponding DS for the rollover to continue. If none is specified, the
+rollover must be pushed forward manually.
+
+*Default:* not set
+
+.. TIP::
+ A DNSSEC-validating resolver can be set as a parent.
+
+.. _submission_check-interval:
+
+check-interval
+--------------
+
+Interval for periodic checks of DS presence on parent's DNS servers, in the
+case of the KSK submission.
+
+*Default:* ``1h`` (1 hour)
+
+.. _submission_timeout:
+
+timeout
+-------
+
+After this time period (in seconds) the KSK submission is automatically considered
+successful, even if all the checks were negative or no parents are configured.
+Set to 0 for infinity.
+
+*Default:* ``0``
+
+.. _submission_parent-delay:
+
+parent-delay
+------------
+
+After successful parent DS check, wait for this period before continuing the next
+key roll-over step. This delay shall cover the propagation delay of update in the
+parent zone.
+
+*Default:* ``0``
+
+.. _dnskey-sync section:
+
+``dnskey-sync`` section
+=======================
+
+Parameters of DNSKEY dynamic-update synchrnization.
+
+::
+
+ dnskey-sync:
+ - id: STR
+ remote: remote_id | remotes_id ...
+ check-interval: TIME
+
+.. _dnskey-sync_id:
+
+id
+--
+
+A dnskey-sync identifier.
+
+.. _dnskey-sync_remote:
+
+remote
+------
+
+A list of references :ref:`remote<remote_id>` and :ref:`remotes<remotes_id>`
+to other signers or common master, which the DDNS updates with
+DNSKEY/CDNSKEY/CDS records shall be sent to.
+
+*Default:* not set
+
+.. _dnskey-sync_check-interval:
+
+check-interval
+--------------
+
+If the last DNSKEY sync failed or resulted in any change, re-check
+the consistence after this interval and re-try if needed.
+
+*Default:* ``60`` (1 minute)
+
+.. _policy section:
+
+``policy`` section
+==================
+
+DNSSEC policy configuration.
+
+::
+
+ policy:
+ - id: STR
+ keystore: keystore_id
+ manual: BOOL
+ single-type-signing: BOOL
+ algorithm: rsasha1 | rsasha1-nsec3-sha1 | rsasha256 | rsasha512 | ecdsap256sha256 | ecdsap384sha384 | ed25519 | ed448
+ ksk-size: SIZE
+ zsk-size: SIZE
+ ksk-shared: BOOL
+ dnskey-ttl: TIME
+ zone-max-ttl: TIME
+ ksk-lifetime: TIME
+ zsk-lifetime: TIME
+ delete-delay: TIME
+ propagation-delay: TIME
+ rrsig-lifetime: TIME
+ rrsig-refresh: TIME
+ rrsig-pre-refresh: TIME
+ reproducible-signing: BOOL
+ nsec3: BOOL
+ nsec3-iterations: INT
+ nsec3-opt-out: BOOL
+ nsec3-salt-length: INT
+ nsec3-salt-lifetime: TIME
+ signing-threads: INT
+ ksk-submission: submission_id
+ ds-push: remote_id | remotes_id ...
+ cds-cdnskey-publish: none | delete-dnssec | rollover | always | double-ds
+ cds-digest-type: sha256 | sha384
+ dnskey-management: full | incremental
+ offline-ksk: BOOL
+ unsafe-operation: none | no-check-keyset | no-update-dnskey | no-update-nsec | no-update-expired ...
+
+.. _policy_id:
+
+id
+--
+
+A policy identifier.
+
+.. _policy_keystore:
+
+keystore
+--------
+
+A :ref:`reference<keystore_id>` to a keystore holding private key material
+for zones.
+
+*Default:* an imaginary keystore with all default values
+
+.. NOTE::
+ A configured keystore called "default" won't be used unless explicitly referenced.
+
+.. _policy_manual:
+
+manual
+------
+
+If enabled, automatic key management is not used.
+
+*Default:* ``off``
+
+.. _policy_single-type-signing:
+
+single-type-signing
+-------------------
+
+If enabled, Single-Type Signing Scheme is used in the automatic key management
+mode.
+
+*Default:* ``off`` (:ref:`module onlinesign<mod-onlinesign>` has default ``on``)
+
+.. _policy_algorithm:
+
+algorithm
+---------
+
+An algorithm of signing keys and issued signatures. See
+`DNSSEC Algorithm Numbers <https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1>`_.
+
+Possible values:
+
+- ``rsasha1``
+- ``rsasha1-nsec3-sha1``
+- ``rsasha256``
+- ``rsasha512``
+- ``ecdsap256sha256``
+- ``ecdsap384sha384``
+- ``ed25519``
+- ``ed448``
+
+.. NOTE::
+ Ed25519 algorithm is only available if compiled with GnuTLS 3.6.0+.
+
+ Ed448 algorithm is only available if compiled with GnuTLS 3.6.12+ and Nettle 3.6+.
+
+*Default:* ``ecdsap256sha256``
+
+.. _policy_ksk-size:
+
+ksk-size
+--------
+
+A length of newly generated :abbr:`KSK (Key Signing Key)` or
+:abbr:`CSK (Combined Signing Key)` keys.
+
+*Default:* ``2048`` (rsa*), ``256`` (ecdsap256), ``384`` (ecdsap384), ``256`` (ed25519),
+``456`` (ed448)
+
+.. _policy_zsk-size:
+
+zsk-size
+--------
+
+A length of newly generated :abbr:`ZSK (Zone Signing Key)` keys.
+
+*Default:* see default for :ref:`ksk-size<policy_ksk-size>`
+
+.. _policy_ksk-shared:
+
+ksk-shared
+----------
+
+If enabled, all zones with this policy assigned will share one or more KSKs.
+More KSKs can be shared during a KSK rollover.
+
+.. WARNING::
+ As the shared KSK set is bound to the policy :ref:`id<policy_id>`, renaming the
+ policy breaks this connection and new shared KSK set is initiated when
+ a new KSK is needed.
+
+*Default:* ``off``
+
+.. _policy_dnskey-ttl:
+
+dnskey-ttl
+----------
+
+A TTL value for DNSKEY records added into zone apex.
+
+.. NOTE::
+ Has influence over ZSK key lifetime.
+
+.. WARNING::
+ Ensure all DNSKEYs with updated TTL are propagated before any subsequent
+ DNSKEY rollover starts.
+
+*Default:* zone SOA TTL
+
+.. _policy_zone-max-ttl:
+
+zone-max-ttl
+------------
+
+Declare (override) maximal TTL value among all the records in zone.
+
+.. NOTE::
+ It's generally recommended to override the maximal TTL computation by setting this
+ explicitly whenever possible. It's required for :ref:`DNSSEC Offline KSK` and
+ really reasonable when records are generated dynamically
+ (e.g. by a :ref:`module<mod-synthrecord>`).
+
+*Default:* computed after zone is loaded
+
+.. _policy_ksk-lifetime:
+
+ksk-lifetime
+------------
+
+A period between KSK generation and the next rollover initiation.
+
+.. NOTE::
+ KSK key lifetime is also influenced by propagation-delay, dnskey-ttl,
+ and KSK submission delay.
+
+ Zero (aka infinity) value causes no KSK rollover as a result.
+
+ This applies for CSK lifetime if single-type-signing is enabled.
+
+*Default:* ``0``
+
+.. _policy_zsk-lifetime:
+
+zsk-lifetime
+------------
+
+A period between ZSK activation and the next rollover initiation.
+
+.. NOTE::
+ More exactly, this period is measured since a ZSK is activated,
+ and after this, a new ZSK is generated to replace it within
+ following roll-over.
+
+ ZSK key lifetime is also influenced by propagation-delay and dnskey-ttl
+
+ Zero (aka infinity) value causes no ZSK rollover as a result.
+
+*Default:* ``30d`` (30 days)
+
+.. _policy_delete-delay:
+
+delete-delay
+------------
+
+Once a key (KSK or ZSK) is rolled-over and removed from the zone,
+keep it in the KASP database for at least this period before deleting it completely.
+This might be useful in some troubleshooting cases when resurrection
+is needed.
+
+*Default:* ``0``
+
+.. _policy_propagation-delay:
+
+propagation-delay
+-----------------
+
+An extra delay added for each key rollover step. This value should be high
+enough to cover propagation of data from the primary server to all
+secondary servers, as well as the duration of signing routine itself and
+possible outages in signing and propagation infrastructure. In other words,
+this delay should ensure that within this period of time after planned
+change of the key set, all public-facing secondaries will already serve
+new DNSKEY RRSet for sure.
+
+.. NOTE::
+ Has influence over ZSK key lifetime.
+
+*Default:* ``1h`` (1 hour)
+
+.. _policy_rrsig-lifetime:
+
+rrsig-lifetime
+--------------
+
+A validity period of newly issued signatures.
+
+.. NOTE::
+ The RRSIG's signature inception time is set to 90 minutes in the past. This
+ time period is not counted to the signature lifetime.
+
+*Default:* ``14d`` (14 days)
+
+.. _policy_rrsig-refresh:
+
+rrsig-refresh
+-------------
+
+A period how long at least before a signature expiration the signature will be refreshed,
+in order to prevent expired RRSIGs on secondary servers or resolvers' caches.
+
+*Default:* 0.1 * :ref:`policy_rrsig-lifetime` + :ref:`policy_propagation-delay` + :ref:`policy_zone-max-ttl`
+
+.. _policy_rrsig-pre-refresh:
+
+rrsig-pre-refresh
+-----------------
+
+A period how long at most before a signature refresh time the signature might be refreshed,
+in order to refresh RRSIGs in bigger batches on a frequently updated zone
+(avoid re-sign event too often).
+
+*Default:* ``1h`` (1 hour)
+
+.. _policy_reproducible-signing:
+
+reproducible-signing
+--------------------
+
+For ECDSA algorithms, generate RRSIG signatures deterministically (:rfc:`6979`).
+Besides better theoretical cryptographic security, this mode allows significant
+speed-up of loading signed (by the same method) zones. However, the zone signing
+is a bit slower.
+
+*Default:* ``off``
+
+.. _policy_nsec3:
+
+nsec3
+-----
+
+Specifies if NSEC3 will be used instead of NSEC.
+
+*Default:* ``off``
+
+.. _policy_nsec3-iterations:
+
+nsec3-iterations
+----------------
+
+A number of additional times the hashing is performed.
+
+*Default:* ``0``
+
+.. _policy_nsec3-opt-out:
+
+nsec3-opt-out
+-------------
+
+If set, NSEC3 records won't be created for insecure delegations.
+This speeds up the zone signing and reduces overall zone size.
+
+.. WARNING::
+ NSEC3 with the Opt-Out bit set no longer works as a proof of non-existence
+ in this zone.
+
+*Default:* ``off``
+
+.. _policy_nsec3-salt-length:
+
+nsec3-salt-length
+-----------------
+
+A length of a salt field in octets, which is appended to the original owner
+name before hashing.
+
+*Default:* ``8``
+
+.. _policy_nsec3-salt-lifetime:
+
+nsec3-salt-lifetime
+-------------------
+
+A validity period of newly issued salt field.
+
+Zero value means infinity.
+
+Special value *-1* triggers re-salt every time when active ZSK changes.
+This optimizes the number of big changes to the zone.
+
+*Default:* ``30d`` (30 days)
+
+.. _policy_signing-threads:
+
+signing-threads
+---------------
+
+When signing zone or update, use this number of threads for parallel signing.
+
+Those are extra threads independent of :ref:`Background workers<server_background-workers>`.
+
+.. NOTE::
+ Some steps of the DNSSEC signing operation are not parallelized.
+
+*Default:* ``1`` (no extra threads)
+
+.. _policy_ksk-submission-check:
+
+ksk-submission
+--------------
+
+A reference to :ref:`submission<submission_id>` section holding parameters of
+KSK submission checks.
+
+*Default:* not set
+
+.. _policy_ds-push:
+
+ds-push
+-------
+
+Optional references :ref:`remote<remote_id>` and :ref:`remotes<remotes_id>`
+to authoritative DNS server of the
+parent's zone. The remote server must be configured to accept DS record
+updates via DDNS. Whenever a CDS record in the local zone is changed, the
+corresponding DS record is sent as a dynamic update (DDNS) to the parent
+DNS server. All previous DS records are deleted within the DDNS message.
+It's possible to manage both child and parent zones by the same Knot DNS server.
+
+.. NOTE::
+ This feature requires :ref:`cds-cdnskey-publish<policy_cds-cdnskey-publish>`
+ not to be set to ``none``.
+
+.. NOTE::
+ The mentioned change to CDS record usually means that a KSK roll-over is running
+ and the new key being rolled-in is in "ready" state already for the period of
+ :ref:`propagation-delay<policy_propagation-delay>`.
+
+.. NOTE::
+ Module :ref:`Onlinesign<mod-onlinesign>` doesn't support DS push.
+
+*Default:* not set
+
+.. _policy_dnskey-sync:
+
+dnskey-sync
+-----------
+
+A reference to :ref:`dnskey-sync<dnskey-sync_id>` section holding parameters
+of DNSKEY synchronization.
+
+*Default:* not set
+
+.. _policy_cds-cdnskey-publish:
+
+cds-cdnskey-publish
+-------------------
+
+Controls if and how shall the CDS and CDNSKEY be published in the zone.
+
+Possible values:
+
+- ``none`` – Never publish any CDS or CDNSKEY records in the zone.
+- ``delete-dnssec`` – Publish special CDS and CDNSKEY records indicating turning off DNSSEC.
+- ``rollover`` – Publish CDS and CDNSKEY records for ready and not yet active KSK (submission phase of KSK rollover).
+- ``always`` – Always publish one CDS and one CDNSKEY records for the current KSK.
+- ``double-ds`` – Always publish up to two CDS and two CDNSKEY records for ready and/or active KSKs.
+
+.. NOTE::
+ If the zone keys are managed manually, the CDS and CDNSKEY rrsets may contain
+ more records depending on the keys available.
+
+.. WARNING::
+ The ``double-ds`` value does not trigger double-DS roll-over method. That method is
+ only supported when performed manually, with unset :ref:`policy_ksk-submission-check`.
+
+*Default:* ``rollover``
+
+.. _policy_cds-digest-type:
+
+cds-digest-type
+---------------
+
+Specify digest type for published CDS records.
+
+*Default:* ``sha256``
+
+.. _policy_dnskey-management:
+
+dnskey-management
+-----------------
+
+Specify how the DNSKEY, CDNSKEY, and CDS RRSets at the zone apex are handled
+when (re-)signing the zone.
+
+Possible values:
+
+- ``full`` – Upon every zone (re-)sign, delete all unknown DNSKEY, CDNSKEY, and CDS
+ records and keep just those that are related to the zone keys stored in the KASP database.
+- ``incremental`` – Keep unknown DNSKEY, CDNSKEY, and CDS records in the zone, and
+ modify server-managed records incrementally by employing changes in the KASP database.
+
+.. NOTE::
+ Prerequisites for *incremental*:
+
+ - The :ref:`Offline KSK <DNSSEC Offline KSK>` isn't supported.
+ - The :ref:`policy_delete-delay` is long enough to cover possible daemon
+ shutdown (e.g. due to server maintenance).
+ - Avoided manual deletion of keys with :doc:`keymgr<man_keymgr>`.
+
+ Otherwise there might remain some DNSKEY records in the zone, belonging to
+ deleted keys.
+
+*Default:* ``full``
+
+.. _policy_offline-ksk:
+
+offline-ksk
+-----------
+
+Specifies if :ref:`Offline KSK <DNSSEC Offline KSK>` feature is enabled.
+
+*Default:* ``off``
+
+.. _policy_unsafe-operation:
+
+unsafe-operation
+----------------
+
+Turn off some DNSSEC safety features.
+
+Possible values:
+
+- ``none`` – Nothing disabled.
+- ``no-check-keyset`` – Don't check active keys in present algorithms. This may
+ lead to violation of :rfc:`4035#section-2.2`.
+- ``no-update-dnskey`` – Don't maintain/update DNSKEY, CDNSKEY, and CDS records
+ in the zone apex according to KASP database. Juste leave them as they are in the zone.
+- ``no-update-nsec`` – Don't maintain/update NSEC/NSEC3 chain. Leave all the records
+ as they are in the zone.
+- ``no-update-expired`` – Don't update expired RRSIGs.
+
+Multiple values may be specified.
+
+.. WARNING::
+ This mode is intended for DNSSEC experts who understand the corresponding consequences.
+
+*Default:* ``none``
+
+.. _template section:
+
+``template`` section
+====================
+
+A template is shareable zone settings, which can simplify configuration by
+reducing duplicates. A special default template (with the *default* identifier)
+can be used for global zone configuration or as an implicit configuration
+if a zone doesn't have another template specified.
+
+::
+
+ template:
+ - id: STR
+ global-module: STR/STR ...
+ # All zone options (excluding 'template' item)
+
+.. NOTE::
+ If an item is explicitly specified both in the referenced template and
+ the zone, the template item value is overridden by the zone item value.
+
+.. _template_id:
+
+id
+--
+
+A template identifier.
+
+.. _template_global-module:
+
+global-module
+-------------
+
+An ordered list of references to query modules in the form of *module_name* or
+*module_name/module_id*. These modules apply to all queries.
+
+.. NOTE::
+ This option is only available in the *default* template.
+
+*Default:* not set
+
+.. _zone section:
+
+``zone`` section
+================
+
+Definition of zones served by the server.
+
+::
+
+ zone:
+ - domain: DNAME
+ template: template_id
+ storage: STR
+ file: STR
+ master: remote_id | remotes_id ...
+ ddns-master: remote_id
+ notify: remote_id | remotes_id ...
+ acl: acl_id ...
+ master-pin-tolerance: TIME
+ provide-ixfr: BOOL
+ semantic-checks: BOOL | soft
+ zonefile-sync: TIME
+ zonefile-load: none | difference | difference-no-serial | whole
+ journal-content: none | changes | all
+ journal-max-usage: SIZE
+ journal-max-depth: INT
+ ixfr-benevolent: BOOL
+ ixfr-by-one: BOOL
+ ixfr-from-axfr: BOOL
+ zone-max-size : SIZE
+ adjust-threads: INT
+ dnssec-signing: BOOL
+ dnssec-validation: BOOL
+ dnssec-policy: policy_id
+ ds-push: remote_id | remotes_id ...
+ zonemd-verify: BOOL
+ zonemd-generate: none | zonemd-sha384 | zonemd-sha512 | remove
+ serial-policy: increment | unixtime | dateserial
+ serial-modulo: INT/INT
+ reverse-generate: DNAME
+ refresh-min-interval: TIME
+ refresh-max-interval: TIME
+ retry-min-interval: TIME
+ retry-max-interval: TIME
+ expire-min-interval: TIME
+ expire-max-interval: TIME
+ catalog-role: none | interpret | generate | member
+ catalog-template: template_id ...
+ catalog-zone: DNAME
+ catalog-group: STR
+ module: STR/STR ...
+
+.. _zone_domain:
+
+domain
+------
+
+A zone name identifier.
+
+.. _zone_template:
+
+template
+--------
+
+A :ref:`reference<template_id>` to a configuration template.
+
+*Default:* not set or ``default`` (if the template exists)
+
+.. _zone_storage:
+
+storage
+-------
+
+A data directory for storing zone files. A non-absolute path is relative to
+the :doc:`knotd<man_knotd>` startup directory.
+
+*Default:* ``${localstatedir}/lib/knot`` (configured with ``--with-storage=path``)
+
+.. _zone_file:
+
+file
+----
+
+A :ref:`path<default_paths>` to the zone file. It is also possible to use
+the following formatters:
+
+- ``%c[``\ *N*\ ``]`` or ``%c[``\ *N*\ ``-``\ *M*\ ``]`` – Means the *N*\ th
+ character or a sequence of characters beginning from the *N*\ th and ending
+ with the *M*\ th character of the textual zone name (see ``%s``). The
+ indexes are counted from 0 from the left. All dots (including the terminal
+ one) are considered. If the character is not available, the formatter has no effect.
+- ``%l[``\ *N*\ ``]`` – Means the *N*\ th label of the textual zone name
+ (see ``%s``). The index is counted from 0 from the right (0 ~ TLD).
+ If the label is not available, the formatter has no effect.
+- ``%s`` – Means the current zone name in the textual representation.
+ The zone name doesn't include the terminating dot (the result for the root
+ zone is the empty string!).
+- ``%%`` – Means the ``%`` character.
+
+.. WARNING::
+ Beware of special characters which are escaped or encoded in the \\DDD form
+ where DDD is corresponding decimal ASCII code.
+
+*Default:* :ref:`storage<zone_storage>`\ ``/%s.zone``
+
+.. _zone_master:
+
+master
+------
+
+An ordered list of references :ref:`remote<remote_id>` and
+:ref:`remotes<remotes_id>` to zone primary servers
+(formerly known as master servers).
+
+*Default:* not set
+
+.. _zone_ddns-master:
+
+ddns-master
+-----------
+
+A :ref:`reference<remote_id>` to a zone primary master where DDNS messages
+should be forwarded to. If not specified, the first :ref:`master<zone_master>`
+server is used.
+
+If set to the empty value (""), incoming DDNS messages aren't forwarded but are applied
+to the local zone instead, no matter if it is a secondary server. This is only allowed in
+combination with :ref:`zone_dnssec-signing` enabled.
+
+*Default:* not set
+
+.. _zone_notify:
+
+notify
+------
+
+An ordered list of references :ref:`remote<remote_id>` and
+:ref:`remotes<remotes_id>` to secondary servers to which notify
+message is sent if the zone changes.
+
+*Default:* not set
+
+.. _zone_acl:
+
+acl
+---
+
+An ordered list of :ref:`references<acl_id>` to ACL rules which can allow
+or disallow zone transfers, updates or incoming notifies.
+
+*Default:* not set
+
+.. _zone_master-pin-tolerance:
+
+master-pin-tolerance
+--------------------
+
+If set to a nonzero value on a secondary, always request AXFR/IXFR from the same
+primary as the last time, effectively pinning one primary. Only when another
+primary is updated and the current one lags behind for the specified amount of time
+(defined by this option), change to the updated primary and force AXFR.
+
+This option is useful when multiple primaries may have different zone history
+in their journals, making it unsafe to combine interchanged IXFR
+from different primaries.
+
+*Default:* 0
+
+.. _zone_provide-ixfr:
+
+provide-ixfr
+------------
+
+If disabled, the server is forced to respond with AXFR to IXFR queries.
+If enabled, IXFR requests are responded normally.
+
+*Default:* ``on``
+
+.. _zone_semantic-checks:
+
+semantic-checks
+---------------
+
+Selects if extra zone semantic checks are used or impacts of the mandatory checks.
+
+There are several mandatory checks which are always enabled and cannot be turned
+off. An error in a mandatory check causes the zone not to be loaded. Most of
+the mandatory checks can be weakened by setting ``soft``, which allows the zone to
+be loaded even if the check fails.
+
+If enabled, extra checks are used. These checks don't prevent the zone from loading.
+
+The mandatory checks are applied to zone files, zone transfers, and updates via
+control interface. The extra checks are applied to zone files only!
+
+Mandatory checks:
+
+- Missing SOA record at the zone apex (:rfc:`1034`) (*)
+- An extra record exists together with a CNAME record except for RRSIG and NSEC (:rfc:`1034`)
+- Multiple CNAME records with the same owner exist (:rfc:`1034`)
+- DNAME record having a record under it (:rfc:`6672`)
+- Multiple DNAME records with the same owner exist (:rfc:`6672`)
+- NS record exists together with a DNAME record (:rfc:`6672`)
+- DS record exists at the zone apex (:rfc:`3658`)
+
+(*) The marked check can't be weakened by the soft mode. All other mandatory checks
+are subject to the optional soft mode.
+
+Extra checks:
+
+- Missing NS record at the zone apex
+- Missing glue A or AAAA record
+- Invalid DS or NSEC3PARAM record
+- CDS or CDNSKEY inconsistency
+- All other DNSSEC checks executed during :ref:`zone_dnssec-validation`
+
+.. NOTE::
+ The soft mode allows the refresh event to ignore a CNAME response to a SOA
+ query (malformed message) and triggers a zone bootstrap instead.
+
+*Default:* ``off``
+
+.. _zone_zonefile-sync:
+
+zonefile-sync
+-------------
+
+The time after which the current zone in memory will be synced with a zone file
+on the disk (see :ref:`file<zone_file>`). The server will serve the latest
+zone even after a restart using zone journal, but the zone file on the disk will
+only be synced after ``zonefile-sync`` time has expired (or after manual zone
+flush). This is applicable when the zone is updated via IXFR, DDNS or automatic
+DNSSEC signing. In order to completely disable automatic zone file synchronization,
+set the value to -1. In that case, it is still possible to force a manual zone flush
+using the ``-f`` option.
+
+.. NOTE::
+ If you are serving large zones with frequent updates where
+ the immediate sync with a zone file is not desirable, increase the value.
+
+*Default:* ``0`` (immediate)
+
+.. _zone_zonefile-load:
+
+zonefile-load
+-------------
+
+Selects how the zone file contents are applied during zone load.
+
+Possible values:
+
+- ``none`` – The zone file is not used at all.
+- ``difference`` – If the zone contents are already available during server start or reload,
+ the difference is computed between them and the contents of the zone file. This difference
+ is then checked for semantic errors and applied to the current zone contents.
+- ``difference-no-serial`` – Same as ``difference``, but the SOA serial in the zone file is
+ ignored, the server takes care of incrementing the serial automatically.
+- ``whole`` – Zone contents are loaded from the zone file.
+
+When ``difference`` is configured and there are no zone contents yet (cold start
+and no zone contents in the journal), it behaves the same way as ``whole``.
+
+*Default:* ``whole``
+
+.. NOTE::
+ See :ref:`Handling, zone file, journal, changes, serials` for guidance on
+ configuring these and related options to ensure reliable operation.
+
+.. _zone_journal-content:
+
+journal-content
+---------------
+
+Selects how the journal shall be used to store zone and its changes.
+
+Possible values:
+
+- ``none`` – The journal is not used at all.
+- ``changes`` – Zone changes history is stored in journal.
+- ``all`` – Zone contents and history is stored in journal.
+
+*Default:* ``changes``
+
+.. WARNING::
+ When this option is changed, the journal still contains data respective to
+ the previous setting. For example, changing it to ``none`` does not purge
+ the journal. Also, changing it from ``all`` to ``changes``
+ does not cause the deletion of the zone-in-journal and the behaviour of the
+ zone loading procedure might be different than expected. It is recommended
+ to consider purging the journal when this option is changed.
+
+.. _zone_journal-max-usage:
+
+journal-max-usage
+-----------------
+
+Policy how much space in journal DB will the zone's journal occupy.
+
+.. NOTE::
+ Journal DB may grow far above the sum of journal-max-usage across
+ all zones, because of DB free space fragmentation.
+
+*Default:* ``100M`` (100 MiB)
+
+.. _zone_journal-max-depth:
+
+journal-max-depth
+-----------------
+
+Maximum history length of the journal.
+
+.. NOTE::
+ Zone-in-journal changeset isn't counted to the limit.
+
+*Minimum:* ``2``
+
+*Default:* ``20``
+
+.. _zone_ixfr-benevolent:
+
+ixfr-benevolent
+---------------
+
+If enabled, incoming IXFR is applied even when it contains removals of non-existing
+or additions of existing records.
+
+*Default:* off
+
+.. _zone_ixfr-by-one:
+
+ixfr-by-one
+-----------
+
+Within incoming IXFR, process only one changeset at a time, not multiple together.
+This preserves the complete history in the journal and prevents the merging of
+changesets when multiple changesets are IXFRed simultaneously. However, this does not
+prevent the merging (or deletion) of old changesets in the journal to save space,
+as described in :ref:`journal behaviour <Journal behaviour>`.
+
+This option leads to increased server load when processing IXFR, including
+network traffic.
+
+*Default:* ``off``
+
+.. _zone_ixfr-from-axfr:
+
+ixfr-from-axfr
+--------------
+
+If a primary sends AXFR-style-IXFR upon an IXFR request, compute the difference
+and process it as an incremental zone update (e.g. by storing the changeset in
+the journal).
+
+*Default:* ``off``
+
+.. _zone_zone-max-size:
+
+zone-max-size
+-------------
+
+Maximum size of the zone. The size is measured as size of the zone records
+in wire format without compression. The limit is enforced for incoming zone
+transfers and dynamic updates.
+
+For incremental transfers (IXFR), the effective limit for the total size of
+the records in the transfer is twice the configured value. However the final
+size of the zone must satisfy the configured value.
+
+*Default:* unlimited
+
+.. _zone_adjust-threads:
+
+adjust-threads
+--------------
+
+Parallelize internal zone adjusting procedures by using specified number of
+threads. This is useful with huge zones with NSEC3. Speedup observable at
+server startup and while processing NSEC3 re-salt.
+
+*Default:* ``1`` (no extra threads)
+
+.. _zone_dnssec-signing:
+
+dnssec-signing
+--------------
+
+If enabled, automatic DNSSEC signing for the zone is turned on.
+
+*Default:* ``off``
+
+.. _zone_dnssec-validation:
+
+dnssec-validation
+-----------------
+
+If enabled, the zone contents are validated for being correctly signed
+(including NSEC/NSEC3 chain) with DNSSEC signatures every time the zone
+is loaded or changed (including AXFR/IXFR).
+
+When the validation fails, the zone being loaded or update being applied
+is cancelled with an error, and either none or previous zone state is published.
+
+List of DNSSEC checks:
+
+- Every zone RRSet is correctly signed by at least one present DNSKEY.
+- DNSKEY RRSet is signed by KSK.
+- NSEC(3) RR exists for each name (unless opt-out) with correct bitmap.
+- Every NSEC(3) RR is linked to the lexicographically next one.
+
+The validation is not affected by :ref:`zone_dnssec-policy` configuration,
+except for :ref:`policy_signing-threads` option, which specifies the number
+of threads for parallel validation.
+
+.. NOTE::
+
+ Redundant or garbage NSEC3 records are ignored.
+
+ This mode is not compatible with :ref:`zone_dnssec-signing`.
+
+*Default:* not set
+
+.. _zone_dnssec-policy:
+
+dnssec-policy
+-------------
+
+A :ref:`reference<policy_id>` to DNSSEC signing policy.
+
+.. NOTE::
+ A configured policy called "default" won't be used unless explicitly referenced.
+
+*Default:* an imaginary policy with all default values
+
+.. _zone_ds-push:
+
+ds-push
+-------
+
+Per zone configuration of :ref:`policy_ds-push`. This option overrides possible
+per policy option.
+
+*Default:* not set
+
+.. _zone_zonemd-verify:
+
+zonemd-verify
+-------------
+
+On each zone load/update, verify that ZONEMD is present in the zone and valid.
+
+.. NOTE::
+ Zone digest calculation may take much time and CPU on large zones.
+
+*Default:* ``off``
+
+.. _zone_zonemd-generate:
+
+zonemd-generate
+---------------
+
+On each zone update, calculate ZONEMD and put it into the zone.
+
+Possible values:
+
+- ``none`` – No action regarding ZONEMD.
+- ``zonemd-sha384`` – Generate ZONEMD using SHA384 algorithm.
+- ``zonemd-sha512`` – Generate ZONEMD using SHA512 algorithm.
+- ``remove`` – Remove any ZONEMD from the zone apex.
+
+*Default:* ``none``
+
+.. _zone_serial-policy:
+
+serial-policy
+-------------
+
+Specifies how the zone serial is updated after a dynamic update or
+automatic DNSSEC signing. If the serial is changed by the dynamic update,
+no change is made.
+
+Possible values:
+
+- ``increment`` – The serial is incremented according to serial number arithmetic.
+- ``unixtime`` – The serial is set to the current unix time.
+- ``dateserial`` – The 10-digit serial (YYYYMMDDnn) is incremented, the first
+ 8 digits match the current iso-date.
+
+.. NOTE::
+ If the resulting serial for ``unixtime`` or ``dateserial`` is lower than or
+ equal to the current serial (this happens e.g. when migrating from other policy or
+ frequent updates), the serial is incremented instead.
+
+ To avoid user confusion, use ``dateserial`` only if you expect at most
+ 100 updates per day per zone and ``unixtime`` only if you expect at most
+ one update per second per zone.
+
+ Generated catalog zones use ``unixtime`` only.
+
+*Default:* ``increment`` (``unixtime`` for generated catalog zones)
+
+.. _zone_serial-modulo:
+
+serial-modulo
+-------------
+
+Specifies that the zone serials shall be congruent by specified modulo.
+The option value must be a string in the format ``R/M``, where ``R < M <= 256`` are
+positive integers. Whenever the zone serial is incremented, it is ensured
+that ``serial % M == R``. This can be useful in the case of multiple inconsistent
+primaries, where distinct zone serial sequences prevent cross-master-IXFR
+by any secondary.
+
+.. NOTE::
+ In order to ensure the congruent policy, this option is only allowed
+ with :ref:`DNSSEC signing enabled<zone_dnssec-signing>` and
+ :ref:`zone_zonefile-load` to be either ``difference-no-serial`` or ``none``.
+
+ Because the zone serial effectively always increments by ``M`` instead of
+ ``1``, it is not recommended to use ``dateserial`` :ref:`zone_serial-policy`
+ or even ``unixtime`` in case of rapidly updated zone.
+
+*Default:* ``0/1``
+
+.. _zone_reverse-generate:
+
+reverse-generate
+----------------
+
+This option triggers the automatic generation of reverse PTR records based on
+A/AAAA records in the specified zone. The entire generated zone is automatically
+stored in the journal.
+
+Current limitations:
+
+- Only one zone to be reversed can be specified.
+- Is slow for large zones (even when changing a little).
+
+*Default:* none
+
+.. _zone_refresh-min-interval:
+
+refresh-min-interval
+--------------------
+
+Forced minimum zone refresh interval (in seconds) to avoid flooding primary server.
+
+*Minimum:* ``2``
+
+*Default:* ``2``
+
+.. _zone_refresh-max-interval:
+
+refresh-max-interval
+--------------------
+
+Forced maximum zone refresh interval (in seconds).
+
+*Default:* not set
+
+.. _zone_retry-min-interval:
+
+retry-min-interval
+------------------
+
+Forced minimum zone retry interval (in seconds) to avoid flooding primary server.
+
+*Minimum:* ``1``
+
+*Default:* ``1``
+
+.. _zone_retry-max-interval:
+
+retry-max-interval
+------------------
+
+Forced maximum zone retry interval (in seconds).
+
+*Default:* not set
+
+.. _zone_expire-min-interval:
+
+expire-min-interval
+-------------------
+
+Forced minimum zone expire interval (in seconds) to avoid flooding primary server.
+
+*Minimum:* ``3``
+
+*Default:* ``3``
+
+.. _zone_expire-max-interval:
+
+expire-max-interval
+-------------------
+
+Forced maximum zone expire interval (in seconds).
+
+*Default:* not set
+
+.. _zone_catalog-role:
+
+catalog-role
+------------
+
+Trigger zone catalog feature. Possible values:
+
+- ``none`` – Not a catalog zone.
+- ``interpret`` – A catalog zone which is loaded from a zone file or XFR,
+ and member zones shall be configured based on its contents.
+- ``generate`` – A catalog zone whose contents are generated according to
+ assigned member zones.
+- ``member`` – A member zone that is assigned to one generated catalog zone.
+
+.. NOTE::
+ If set to ``generate``, the :ref:`zone_zonefile-load` option has no effect
+ since a zone file is never loaded.
+
+*Default:* ``none``
+
+.. _zone_catalog-template:
+
+catalog-template
+----------------
+
+For the catalog member zones, the specified configuration template will be applied.
+
+Multiple catalog templates may be defined. The first one is used unless the member zone
+has the *group* property defined, matching another catalog template.
+
+.. NOTE::
+ This option must be set if and only if :ref:`zone_catalog-role` is *interpret*.
+
+ Nested catalog zones aren't supported. Therefore catalog templates can't use
+ :ref:`zone_catalog-template`, :ref:`zone_catalog-role`, :ref:`zone_catalog-zone`,
+ and :ref:`zone_catalog-group` options.
+
+*Default:* not set
+
+.. _zone_catalog-zone:
+
+catalog-zone
+------------
+
+Assign this member zone to specified generated catalog zone.
+
+.. NOTE::
+ This option must be set if and only if :ref:`zone_catalog-role` is *member*.
+
+ The referenced catalog zone must exist and have :ref:`zone_catalog-role` set to *generate*.
+
+*Default:* not set
+
+.. _zone_catalog-group:
+
+catalog-group
+-------------
+
+Assign this member zone to specified catalog group (configuration template).
+
+.. NOTE::
+ This option has effect if and only if :ref:`zone_catalog-role` is *member*.
+
+*Default:* not set
+
+.. _zone_module:
+
+module
+------
+
+An ordered list of references to query modules in the form of *module_name* or
+*module_name/module_id*. These modules apply only to the current zone queries.
+
+*Default:* not set
diff --git a/doc/requirements.rst b/doc/requirements.rst
new file mode 100644
index 0000000..584afa2
--- /dev/null
+++ b/doc/requirements.rst
@@ -0,0 +1,115 @@
+.. highlight:: none
+.. _Requirements:
+
+************
+Requirements
+************
+
+Hardware
+========
+
+Knot DNS requirements are not very demanding for typical
+installations, and a commodity server or a virtual solution will be
+sufficient in most cases.
+
+However, please note that there are some scenarios that will require
+administrator's attention and some testing of exact requirements before
+deploying Knot DNS to a production environment. These cases include
+deployment for a large number of zones (DNS hosting), large number
+of records in one or more zones (TLD), or large number of requests.
+
+CPU requirements
+----------------
+
+The server scales with processing power and also with the number of
+available cores/CPUs. Enabling Hyper-threading is convenient if supported.
+
+There is no lower bound on the CPU requirements, but it should support
+memory barriers and atomic instructions (i586 and newer).
+
+Network card
+------------
+
+The best results have been achieved with multi-queue network cards. The
+number of multi-queues should equal the total number of CPU cores (with
+Hyper-threading enabled).
+
+Memory requirements
+-------------------
+
+The server implementation focuses on performance and thus can be quite
+memory demanding. The rough estimate for memory requirements is
+3 times the size of the zone in the plain-text format. Again this is only
+an estimate and you are advised to do your own measurements before
+deploying Knot DNS to production.
+
+.. NOTE::
+ To ensure uninterrupted serving of the zone, Knot DNS
+ employs the Read-Copy-Update mechanism instead of locking and thus
+ requires twice the amount of memory for the duration of incoming
+ transfers.
+
+Operating system
+================
+
+Knot DNS itself is written in a portable way and can be compiled
+and run on most UNIX-like systems, such as Linux, \*BSD, and macOS.
+
+Required libraries
+==================
+
+Knot DNS requires a few libraries to be available:
+
+* libedit
+* gnutls >= 3.3
+* liburcu >= 0.5.4
+* lmdb >= 0.9.15
+
+.. NOTE::
+ The LMDB library is included with Knot DNS source code. However, linking
+ with the system library is preferred.
+
+Optional libraries
+==================
+
+International Domain Names support (IDNA2008 or IDNA2003) in :doc:`kdig<man_kdig>`:
+
+* libidn2 (or libidn)
+
+Systemd's startup notification mechanism and journald logging:
+
+* libsystemd
+
+Dnstap support in :doc:`kdig<man_kdig>` or module :ref:`dnstap<mod-dnstap>`:
+
+* fstrm (and protobuf-c if building from source code)
+
+Linux :manpage:`capabilities(7)` support, which allows the server to be started
+as a non-root user/group, binding to privileged ports (53), and giving up all
+its capabilities, resulting in a completely unprivileged process:
+
+* libcap-ng >= 0.6.4
+
+MaxMind database for **geodb** support in module :ref:`geoip<mod-geoip>`:
+
+* libmaxminddb0
+
+DNS-over-HTTPS (DoH) support in :doc:`kdig<man_kdig>`:
+
+* libnghttp2
+
+The :ref:`XDP functionality <Mode XDP>` and :doc:`kxdpgun <man_kxdpgun>`
+tool. These are only supported on Linux operating systems. See the chapter
+:ref:`Mode XDP <Mode XDP_pre-requisites>` for software and hardware
+recommendations.
+
+* libbpf
+* libxdp (if libbpf >= 1.0)
+* libmnl (for kxdpgun)
+
+DNS-over-QUIC (DoQ) support in :doc:`knotd<man_knotd>`, :doc:`kxdpgun<man_kxdpgun>`,
+and :doc:`kdig<man_kdig>`:
+
+* libngtcp2 >= 0.17.0 (or embedded one via `--enable-quic`)
+* gnutls >= 3.7.3
+* :ref:`Mode XDP` (for knotd and kxdpgun)
diff --git a/doc/theme_html/static/admon_caution_48.png b/doc/theme_html/static/admon_caution_48.png
new file mode 100644
index 0000000..9016ec0
--- /dev/null
+++ b/doc/theme_html/static/admon_caution_48.png
Binary files differ
diff --git a/doc/theme_html/static/admon_important_48.png b/doc/theme_html/static/admon_important_48.png
new file mode 100644
index 0000000..7021f4c
--- /dev/null
+++ b/doc/theme_html/static/admon_important_48.png
Binary files differ
diff --git a/doc/theme_html/static/admon_note_48.png b/doc/theme_html/static/admon_note_48.png
new file mode 100644
index 0000000..e72e336
--- /dev/null
+++ b/doc/theme_html/static/admon_note_48.png
Binary files differ
diff --git a/doc/theme_html/static/admon_tip_48.png b/doc/theme_html/static/admon_tip_48.png
new file mode 100644
index 0000000..f679193
--- /dev/null
+++ b/doc/theme_html/static/admon_tip_48.png
Binary files differ
diff --git a/doc/theme_html/static/admon_warning_48.png b/doc/theme_html/static/admon_warning_48.png
new file mode 100644
index 0000000..2c338d5
--- /dev/null
+++ b/doc/theme_html/static/admon_warning_48.png
Binary files differ
diff --git a/doc/theme_html/static/admons.css b/doc/theme_html/static/admons.css
new file mode 100644
index 0000000..d9f3406
--- /dev/null
+++ b/doc/theme_html/static/admons.css
@@ -0,0 +1,69 @@
+/* === Style for admonitions === */
+
+/* Settings from 'basic' theme (modified only) */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+ padding-left: 54px;/* based on icon size */
+ padding-right: 24px;/* based on icon size */
+}
+
+/* Settings from 'classic' theme (modified only) */
+
+div.admonition p {
+ display: block;
+}
+
+p.admonition-title {
+ padding-bottom: 11px;/* based on icon size */
+ padding-top: 11px;/* based on icon size */
+}
+
+p.admonition-title:after {
+ content: none; /* do not add colon */
+}
+
+/* Icon settings for all admonitions */
+div.admonition {
+ /* background-image: url('abstract_admon_48.png'); */
+ background-repeat: no-repeat;
+ background-position: 2px 2px;
+}
+
+/* Specific admonitions */
+div.admonition-todo {
+ background-color: #CAE2B6;
+ border: solid 1px #439427;
+}
+
+div.warning {
+ background-image: url('admon_warning_48.png');
+ background-color: #FFE4E4;
+ border: solid 3px #990D1C;
+}
+
+div.caution {
+ background-image: url('admon_caution_48.png');
+ background-color: #FFE4E4;
+ border: solid 1px #990D1C;
+}
+
+div.important {
+ background-image: url('admon_important_48.png');
+ background-color: #FBECC8;
+ border: solid 1px #D68612;
+}
+
+div.note {
+ background-image: url('admon_note_48.png');
+ background-color: white;
+ border: solid 1px #D1D3D4;
+}
+
+div.tip {
+ background-image: url('admon_tip_48.png');
+ background-color: #F2E4FD;
+ border: solid 1px #D1C2E6;
+}
diff --git a/doc/theme_html/static/main.css b/doc/theme_html/static/main.css
new file mode 100644
index 0000000..d7eb5d1
--- /dev/null
+++ b/doc/theme_html/static/main.css
@@ -0,0 +1,6 @@
+@import url("nature.css");
+
+/* Addendum for admonitions */
+@import url("admons.css");
+
+/* Other overrides here */
diff --git a/doc/theme_html/theme.conf b/doc/theme_html/theme.conf
new file mode 100644
index 0000000..eb8c607
--- /dev/null
+++ b/doc/theme_html/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = nature
+stylesheet = main.css
+pygments_style = sphinx
diff --git a/doc/troubleshooting.rst b/doc/troubleshooting.rst
new file mode 100644
index 0000000..3d7c359
--- /dev/null
+++ b/doc/troubleshooting.rst
@@ -0,0 +1,110 @@
+.. highlight:: none
+.. _Troubleshooting:
+
+***************
+Troubleshooting
+***************
+
+First of all, check the logs. Enabling at least the ``warning`` message
+severity may help you to identify some problems. See the :ref:`log section`
+for details.
+
+.. _Submitting a bugreport:
+
+Reporting bugs
+==============
+
+If you are unable to solve the problem by yourself, you can submit a
+bugreport to the Knot DNS developers. For security or sensitive issues
+contact the developers directly on
+`knot-dns@labs.nic.cz <mailto:knot-dns@labs.nic.cz>`_.
+All other bugs and questions may be directed to the public Knot DNS users
+mailing list
+(`knot-dns-users@lists.nic.cz <mailto:knot-dns-users@lists.nic.cz>`_) or
+may be entered into the
+`issue tracking system <https://gitlab.nic.cz/knot/knot-dns/issues>`_.
+
+Before anything else, please try to answer the following questions:
+
+* Has it been working?
+* What has changed? System configuration, software updates, network
+ configuration, firewall rules modification, hardware replacement, etc.
+
+The bugreport should contain the answers for the previous questions and in
+addition at least the following information:
+
+* Knot DNS version and type of installation (distribution package, from source,
+ etc.)
+* Operating system, platform, kernel version
+* Relevant basic hardware information (processor, amount of memory, available
+ network devices, etc.)
+* Description of the bug
+* Log output with the highest verbosity (category ``any``, severity ``debug``)
+* Steps to reproduce the bug (if known)
+* Backtrace (if the bug caused a crash or a hang; see the next section)
+
+If possible, please provide a minimal configuration file and zone files which
+can be used to reproduce the bug.
+
+.. _Generating backtrace:
+
+Generating backtrace
+====================
+
+Backtrace carries basic information about the state of the program and how
+the program got where it is. It helps determining the location of the bug in
+the source code.
+
+If you run Knot DNS from distribution packages, make sure the debugging
+symbols for the package are installed. The symbols are usually distributed
+in a separate package.
+
+There are several ways to get the backtrace. One possible way is to extract
+the backtrace from a core dump file. Core dump is a memory snapshot generated
+by the operating system when a process crashes. The generating of core dumps
+must be usually enabled::
+
+ $ ulimit -c unlimited # Enable unlimited core dump size
+ $ knotd ... # Reproduce the crash
+ ...
+ $ gdb knotd <core-dump-file> # Start gdb on the core dump
+ (gdb) info threads # Get a summary of all threads
+ (gdb) thread apply all bt full # Extract backtrace from all threads
+ (gdb) quit
+
+To save the backtrace into a file, the following GDB commands can be used::
+
+ (gdb) set pagination off
+ (gdb) set logging file backtrace.txt
+ (gdb) set logging on
+ (gdb) info threads
+ (gdb) thread apply all bt full
+ (gdb) set logging off
+
+To generate a core dump of a running process, the `gcore` utility can be used::
+
+ $ gcore -o <output-file> $(pidof knotd)
+
+Please note that core dumps can be intercepted by an error-collecting system
+service (systemd-coredump, ABRT, Apport, etc.). If you are using such a service,
+consult its documentation about core dump retrieval.
+
+If the error is reproducible, it is also possible to start and inspect the
+server directly in the debugger::
+
+ $ gdb --args knotd -c /etc/knot.conf
+ (gdb) run
+ ...
+
+Alternatively, the debugger can be attached to a running server
+process. This is generally useful when troubleshooting a stuck process::
+
+ $ knotd ...
+ $ gdb --pid $(pidof knotd)
+ (gdb) continue
+ ...
+
+If you fail to get a backtrace of a running process using the previous method,
+you may try the single-purpose ``pstack`` utility::
+
+ $ pstack $(pidof knotd) > backtrace.txt
diff --git a/doc/utilities.rst b/doc/utilities.rst
new file mode 100644
index 0000000..392115d
--- /dev/null
+++ b/doc/utilities.rst
@@ -0,0 +1,24 @@
+.. highlight:: none
+.. _Utilities:
+
+Utilities
+=========
+
+Knot DNS comes with a few DNS client utilities and a few utilities to control
+the server. This section collects manual pages for all provided binaries:
+
+.. toctree::
+ :titlesonly:
+
+ man_knotd
+ man_knotc
+ man_keymgr
+ man_kjournalprint
+ man_kcatalogprint
+ man_kzonecheck
+ man_kzonesign
+ man_kdig
+ man_khost
+ man_knsec3hash
+ man_knsupdate
+ man_kxdpgun