Settings reference
Every key of kudurru.yaml with its type, default, scope and environment variable.
Every settings key of kudurru.yaml, generated from the metadata table in
internal/config/schema.go, the same table kudurru config schema prints and
GET /api/v1/settings/_schema serves.
Where a value comes from. Each layer overrides the one before it:
- the built-in default (the Default column);
- the config file (
--config,KUDURRU_CONFIG, default/etc/kudurru/kudurru.yaml); - the settings file (
settingsFileorKUDURRU_SETTINGS_FILE) for cluster-scope keys, which is where changes made in the UI, withkudurru settings setor withPATCH /api/v1/settingsare written; it is watched and hot keys apply at once; - the environment:
KUDURRU_<SECTION>__<KEY>, with__for every dot of the path (KUDURRU_LOG__LEVEL=debug), orKUDURRU_<SECTION>__<KEY>_FILEnaming a file that holds the value.string[]values are comma-separated;listandmapkeys can only be set in a file. A key set from the environment is read-only in the UI, and a variable that names no key stops the server at start.
Scope. node keys belong to one host. cluster keys are shared by every
node of a deployment.
Allowed values. The bold label is the name the UI shows. The Allowed
line lists what a key accepts: a closed set, a range, a format (ip,
cidr for a CIDR or a single address, hostport, url, domain,
upstream for a server in dnsproxy syntax), the object a value names (ref)
and the members of list and map values. The config file, the environment and
the API reject anything else with an error naming the key.
Flags. host-only keys can only be set in the file or the environment on the host, never through the API or the UI (they name listeners, files and privileged behaviour). restart keys take effect after a restart (in Kubernetes the chart rolls the pods); every other key is applied while the server runs. write-only keys are never returned by the API.
node
listeners
| Key | Type | Default | Scope | Description |
|---|---|---|---|---|
listeners.dns | list | [{address: "0.0.0.0:53", protocols: [udp, tcp]}] | node | DNS listeners. Addresses where devices send plain DNS queries. Port 53 is what devices expect; the default 0.0.0.0:53 answers on every address over UDP and TCP. Bind one address, e.g. 192.168.1.10:53, when another service on the machine already uses port 53. Allowed: items: {address (required): string (format hostport); protocols: list of string (one of udp | tcp) (default ["udp","tcp"])}. host-only, restart Environment: file only. |
listeners.dot | list | [] | node | DNS-over-TLS listeners. Encrypted DNS-over-TLS (DoT), usually on port 853, for devices that support it such as Android's Private DNS. Each entry needs an address, e.g. 0.0.0.0:853, and a certificate and key valid for the name devices use. Empty serves none. RFC 7858, ALPN dot. Allowed: items: {address (required): string (format hostport); tls (required): {certFile (required): string; keyFile (required): string}}. host-only, restart Environment: file only. |
listeners.doh | list | [] | node | DNS-over-HTTPS listeners. Encrypted DNS-over-HTTPS (DoH), usually on port 443, for browsers and devices that support it. Each entry needs an address, e.g. 0.0.0.0:443, a certificate and key, and optionally a path (default /dns-query). Empty serves none. RFC 8484, HTTP/2 and HTTP/1.1. Allowed: items: {address (required): string (format hostport); path: string (default /dns-query); tls (required): {certFile (required): string; keyFile (required): string}}. host-only, restart Environment: file only. |
listeners.doq | list | [] | node | DNS-over-QUIC listeners. Encrypted DNS-over-QUIC (DoQ), usually on UDP port 853, for clients that support it. Each entry needs an address, e.g. 0.0.0.0:853, and a certificate and key. Empty serves none. RFC 9250, ALPN doq. Allowed: items: {address (required): string (format hostport); tls (required): {certFile (required): string; keyFile (required): string}}. host-only, restart Environment: file only. |
listeners.doh3 | list | [] | node | DNS-over-HTTP/3 listeners. Encrypted DNS-over-HTTPS over HTTP/3 (QUIC), usually on UDP port 443, for browsers that support it. Each entry needs an address, e.g. 0.0.0.0:443, a certificate and key, and optionally a path (default /dns-query). Empty serves none. ALPN h3. Allowed: items: {address (required): string (format hostport); path: string (default /dns-query); tls (required): {certFile (required): string; keyFile (required): string}}. host-only, restart Environment: file only. |
listeners.api.address | string | 0.0.0.0:8080 | node | API and UI address. Address and port of the dashboard and the HTTP API, e.g. 0.0.0.0:8080 for every address or 127.0.0.1:8080 for this machine only; browse to https://<server address>:8080. Allowed: format hostport. host-only, restart Environment: KUDURRU_LISTENERS__API__ADDRESS |
listeners.api.tls.auto | string | selfsigned | node | API automatic TLS. Whether the dashboard uses HTTPS with a certificate kudurru makes itself when no certificate file is set. selfsigned (default) encrypts the connection, though browsers warn because no public authority signed the certificate; off serves plain HTTP, for use behind a reverse proxy that handles TLS. The certificate is generated once into <node.dataDir>/keys/. Allowed: one of selfsigned | off. host-only, restart Environment: KUDURRU_LISTENERS__API__TLS__AUTO |
listeners.api.tls.certFile | string | (empty) | node | API certificate file. Path of your own certificate for the dashboard (PEM, full chain), e.g. /etc/kudurru/tls/tls.crt; set it with the key file to replace the self-signed certificate. Takes precedence over listeners.api.tls.auto. host-only, restart Environment: KUDURRU_LISTENERS__API__TLS__CERTFILE |
listeners.api.tls.keyFile | string | (empty) | node | API key file. Path of the private key (PEM) of listeners.api.tls.certFile, e.g. /etc/kudurru/tls/tls.key. host-only, restart Environment: KUDURRU_LISTENERS__API__TLS__KEYFILE |
listeners.api.pathPrefix | string | (empty) | node | API path prefix. URL path the dashboard and API are served under when a reverse proxy mounts kudurru below the root of a site, e.g. /kudurru for https://home.example/kudurru/. Empty serves them at /. host-only, restart Environment: KUDURRU_LISTENERS__API__PATHPREFIX |
listeners.api.trustedProxies | string[] | [] | node | Trusted reverse proxies. Reverse proxies in front of the dashboard, as addresses or CIDRs, e.g. 192.168.1.5 or 10.0.0.0/8. Only requests from them may report the real client address and scheme in X-Forwarded-For and X-Forwarded-Proto; empty trusts no proxy. Allowed: items: string (format cidr). host-only, restart Environment: KUDURRU_LISTENERS__API__TRUSTEDPROXIES |
listeners.ops.address | string | 0.0.0.0:8081 | node | Health listener address. Address and port of the health checks Docker, Kubernetes and load balancers poll, e.g. 0.0.0.0:8081 (/healthz/live, /healthz/ready). They need no login. Allowed: format hostport. host-only, restart Environment: KUDURRU_LISTENERS__OPS__ADDRESS |
listeners.metrics.address | string | 0.0.0.0:9153 | node | Metrics listener address. Address and port Prometheus scrapes metrics from (/metrics), e.g. 0.0.0.0:9153, or 127.0.0.1:9153 to keep them on this machine. Allowed: format hostport. host-only, restart Environment: KUDURRU_LISTENERS__METRICS__ADDRESS |
listeners.proxyProtocolFrom | string[] | [] | node | PROXYv2 peers. Only with a dnsdist front end: the exact addresses allowed to tell kudurru the real client address in a PROXY protocol v2 header, as CIDRs, normally one /32 per front end, e.g. 192.168.1.2/32. Leave empty when devices query kudurru directly. Use loopback only when dnsdist shares kudurru's network namespace. Allowed: items: string (format cidr). host-only, restart Environment: KUDURRU_LISTENERS__PROXYPROTOCOLFROM |
listeners.proxyProtocolSecretFile | string | (empty) | node | PROXYv2 secret file. Path of a file holding the secret shared with the dnsdist front end, at least 32 bytes, e.g. made with openssl rand -hex 32. Required when proxyProtocolFrom names a peer that is not loopback, so another host cannot forge client addresses. Carried in PROXYv2 TLV 0xE0. host-only, restart Environment: KUDURRU_LISTENERS__PROXYPROTOCOLSECRETFILE |
listeners.internal.address | string | 0.0.0.0:8082 | node | Node-to-node listener address. Address and port the other nodes of a cluster use to reach this one, e.g. 0.0.0.0:8082; a single server does not need it reachable. Always TLS with a bearer token; it serves list bodies by digest and /internal/status. Allowed: format hostport. host-only, restart Environment: KUDURRU_LISTENERS__INTERNAL__ADDRESS |
listeners.internal.tokenFile | string | (empty) | node | Internal token file. Path of a file holding the token nodes present to each other. Empty (the usual choice) derives it from the encryption key, so every node with the same KUDURRU_ENCRYPTION_KEY agrees on it (HKDF). host-only, restart Environment: KUDURRU_LISTENERS__INTERNAL__TOKENFILE |
listeners.internal.tls.certFile | string | (empty) | node | Internal certificate file. Path of the certificate (PEM) of the node-to-node listener, for your own PKI. Empty (the usual choice) issues one from a CA derived from the encryption key, which every node with the same key trusts. host-only, restart Environment: KUDURRU_LISTENERS__INTERNAL__TLS__CERTFILE |
listeners.internal.tls.keyFile | string | (empty) | node | Internal key file. Path of the private key (PEM) of listeners.internal.tls.certFile. host-only, restart Environment: KUDURRU_LISTENERS__INTERNAL__TLS__KEYFILE |
listeners.internal.tls.caFile | string | (empty) | node | Internal CA bundle. Path of the CA bundle (PEM) trusted when this node connects to other nodes; set it together with your own certificates. Empty trusts the CA derived from the encryption key. host-only, restart Environment: KUDURRU_LISTENERS__INTERNAL__TLS__CAFILE |
listeners.internal.tls.serverName | string | (empty) | node | Internal TLS server name. Name checked in other nodes' certificates, e.g. kudurru-internal.home.example; it must be a SAN of listeners.internal.tls.certFile. Empty uses the fixed name of the derived certificates. Allowed: format domain. host-only, restart Environment: KUDURRU_LISTENERS__INTERNAL__TLS__SERVERNAME |
listeners.blockPage.http | string | :80 | node | Block page HTTP address. Address and port where the block page answers browsers over plain HTTP, e.g. :80; empty turns it off. Under the blockPage block response, blocked names point at this server, so a browser that opens one lands here. Needs blockPage.enabled. Allowed: format hostport. host-only, restart Environment: KUDURRU_LISTENERS__BLOCKPAGE__HTTP |
listeners.blockPage.https | string | (empty) | node | Block page HTTPS address. Optional address and port of the block page over HTTPS, e.g. :443; empty (the default) leaves it off. No certificate can be valid for the blocked names, so browsers show a certificate warning before the page, and sites that use HSTS show no page at all (docs/deploy/blocking-page.md). Allowed: format hostport. host-only, restart Environment: KUDURRU_LISTENERS__BLOCKPAGE__HTTPS |
listeners.blockPage.tls.certFile | string | (empty) | node | Block page certificate file. Path of the certificate (PEM) of the HTTPS block page. Empty generates a self-signed one into <node.dataDir>/keys/blockpage.crt; a certificate of your own cannot match the blocked names either. host-only, restart Environment: KUDURRU_LISTENERS__BLOCKPAGE__TLS__CERTFILE |
listeners.blockPage.tls.keyFile | string | (empty) | node | Block page key file. Path of the private key (PEM) of listeners.blockPage.tls.certFile. host-only, restart Environment: KUDURRU_LISTENERS__BLOCKPAGE__TLS__KEYFILE |
listeners.sockets | int | 0 | node | Sockets per DNS listener. How many sockets each UDP and TCP DNS listener opens, so several CPU cores read queries in parallel. 0 (default) opens one per CPU (GOMAXPROCS), 1 a single socket. Uses SO_REUSEPORT on Linux, each socket with its own read loop; other systems always use one. Allowed: at least 0. host-only, restart Environment: KUDURRU_LISTENERS__SOCKETS |
store
upstreams
cache
blocking
| Key | Type | Default | Scope | Description |
|---|---|---|---|---|
blocking.enabled | bool | true | cluster | Blocking enabled. Block ads, trackers and other listed names for the whole network; off answers every query unfiltered. To pause blocking for a while, use the temporary disable on the dashboard instead (a runtime toggle, not this key). Applies to forwarded queries, not to your own zones. Environment: KUDURRU_BLOCKING__ENABLED |
blocking.defaultResponse | string | zeroIP | cluster | Default block response. What a blocked query is answered with, unless the client's Policy (blockMode) or the BlockList (response) chooses otherwise. zeroIP (default) makes the connection fail at once and suits most networks; blockPage shows browsers a page that explains the block; refused is discouraged, because devices then ask another DNS server. Allowed: one of zeroIP | nxdomain | customIP | refused | blockPage. Environment: KUDURRU_BLOCKING__DEFAULTRESPONSE |
blocking.blockTTL | duration | 10m | cluster | Block response TTL. How long devices may remember a block answer, e.g. 10m, unless the Policy sets blockTTL. Keep it short: after you allow a name, devices keep the cached block until it expires. Environment: KUDURRU_BLOCKING__BLOCKTTL |
blocking.allowDegraded | bool | true | cluster | Serve while lists load. Answer queries and report ready while blocklists are still loading, e.g. right after a restart; queries are filtered by the lists already loaded. Off, the node reports not ready until every referenced list is loaded, so load balancers keep traffic away. restart Environment: KUDURRU_BLOCKING__ALLOWDEGRADED |
blocking.customIP.v4 | string | (empty) | cluster | Custom block IPv4. IPv4 address blocked A queries are answered with when the block response is customIP, e.g. 192.168.1.10 for a server of yours that shows a notice. Empty answers NODATA. Allowed: format ipv4. Environment: KUDURRU_BLOCKING__CUSTOMIP__V4 |
blocking.customIP.v6 | string | (empty) | cluster | Custom block IPv6. IPv6 address blocked AAAA queries are answered with when the block response is customIP, e.g. fd00::10. Empty answers NODATA. Allowed: format ipv6. Environment: KUDURRU_BLOCKING__CUSTOMIP__V6 |
blocking.refreshInterval | duration | 24h | cluster | List refresh interval. How often blocklists are downloaded again when a list sets no refreshInterval of its own, e.g. 24h; at least 1m. In a cluster the leader downloads and the other nodes copy its result by digest. restart Environment: KUDURRU_BLOCKING__REFRESHINTERVAL |
blocking.initStrategy | string | fast | cluster | List loading at start. What happens at start while blocklists load: fast (default) serves at once using the copies saved on disk; blocking waits until every list is loaded; failOnError also exits when a list cannot be loaded. Allowed: one of fast | blocking | failOnError. restart Environment: KUDURRU_BLOCKING__INITSTRATEGY |
blocking.listsDir | string | (empty) | node | List cache directory. Directory where downloaded blocklists are saved so the next start can use them at once. Empty uses <node.dataDir>/lists. Files are named by the sha256 of the list URL. host-only, restart Environment: KUDURRU_BLOCKING__LISTSDIR |
blocking.allowLocalListURLs | bool | false | node | Allow local list URLs. Allow blocklist URLs that point at this machine or at special addresses: loopback, link-local (169.254.0.0/16, fe80::/10, where cloud metadata services live), unspecified and multicast. Off by default so whoever can add a BlockList cannot make the node fetch internal services (SSRF). Lists on private LAN addresses such as 192.168.1.5 are always allowed. host-only, restart Environment: KUDURRU_BLOCKING__ALLOWLOCALLISTURLS |
blocking.catalogue.url | string | (empty) | cluster | Catalogue URL. Leave empty to use the blocked-services and safe-search catalogue built into kudurru. A URL, e.g. https://example.com/kudurru-catalogue.json, replaces it with your own document (schema version 2, or 1, docs/deploy/blocked-services.md). The leader downloads it and the other nodes copy the leader's; a document that fails validation leaves the current catalogue in service. Allowed: format url. restart Environment: KUDURRU_BLOCKING__CATALOGUE__URL |
blocking.catalogue.adguardServicesURL | string | (empty) | cluster | AdGuard services URL (GPL-3.0, opt-in). Off when empty. Opt-in: a URL of AdGuard's HostlistsRegistry blocked-services file, e.g. https://raw.githubusercontent.com/AdguardTeam/HostlistsRegistry/main/assets/services.json, adds its services (about 140) to the catalogue next to kudurru's own; kudurru's entries win when both have an ID. That data is GPL-3.0 licensed: kudurru does not ship it, your instance downloads it (the leader, on the catalogue refresh interval; the other nodes copy the leader's), and the dashboard marks those services as from AdGuard (GPL-3.0). Check that the licence suits how you use and share the data. docs/deploy/blocked-services.md. Allowed: format url. restart Environment: KUDURRU_BLOCKING__CATALOGUE__ADGUARDSERVICESURL |
blocking.catalogue.refreshInterval | duration | 24h | cluster | Catalogue refresh interval. How often the catalogue at blocking.catalogue.url and the AdGuard services at blocking.catalogue.adguardServicesURL are checked for a new version, e.g. 24h; at least 1m. A conditional GET, so an unchanged document is not downloaded again. restart Environment: KUDURRU_BLOCKING__CATALOGUE__REFRESHINTERVAL |
blockPage
| Key | Type | Default | Scope | Description |
|---|---|---|---|---|
blockPage.enabled | bool | false | cluster | Block page enabled. Show browsers a page that explains why a site was blocked, instead of a connection error. Turning it on starts the block page listener (listeners.blockPage) and allows the blockPage block response; choose that response in blocking.defaultResponse or a Policy. Blocked A and AAAA queries then point at blockPage.ipv4 and blockPage.ipv6; other types get NODATA. restart Environment: KUDURRU_BLOCKPAGE__ENABLED |
blockPage.ipv4 | string | (empty) | cluster | Block page IPv4 address. Address browsers are sent to for the block page, e.g. 192.168.1.10: this server's LAN address, or a VIP or load balancer in front of the block page. Blocked A queries are answered with it under the blockPage response. Empty picks the first specific address of listeners.blockPage, else of listeners.dns; when every listener binds all addresses (0.0.0.0, ::) there is none, and blockPage.enabled is refused. Allowed: format ipv4. Environment: KUDURRU_BLOCKPAGE__IPV4 |
blockPage.ipv6 | string | (empty) | cluster | Block page IPv6 address. IPv6 address browsers are sent to for the block page, e.g. fd00::10; blocked AAAA queries are answered with it under the blockPage response. When blockPage.ipv4 is empty too, one is picked from the listeners as for IPv4; without an IPv6 address, AAAA queries get NODATA and browsers use IPv4. Allowed: format ipv6. Environment: KUDURRU_BLOCKPAGE__IPV6 |
blockPage.title | string | This site is blocked | cluster | Page title. Heading of the block page, e.g. This site is blocked (plain text, at most 200 characters). Environment: KUDURRU_BLOCKPAGE__TITLE |
blockPage.message | string | The administrator of this network has blocked access to this domain. | cluster | Page message. Text under the heading that tells people why the site is blocked and what they can do (plain text, at most 2000 characters; HTML is shown as text). Environment: KUDURRU_BLOCKPAGE__MESSAGE |
blockPage.contact | string | (empty) | cluster | Administrator contact. How people reach you, shown as "Ask your administrator": an email address, e.g. admin@home.example, or a link, e.g. https://wiki.home.example/dns. Empty leaves the line out. Environment: KUDURRU_BLOCKPAGE__CONTACT |
blockPage.showDetails | bool | true | cluster | Show block details. Show what blocked the name (the list, rule, blocked service, safe search or policy), looked up in the recent query log. Off shows only the domain, the client, the node and the time, which keeps your list choices private. Environment: KUDURRU_BLOCKPAGE__SHOWDETAILS |
blockPage.dashboardURL | string | (empty) | cluster | Dashboard URL. Address of the dashboard the block page links administrators to, e.g. https://192.168.1.10:8080; the link opens /queries?domain=... there. Empty builds it from the block page address and listeners.api; set it when the dashboard is reached under another name or through a reverse proxy. Allowed: format url. Environment: KUDURRU_BLOCKPAGE__DASHBOARDURL |
blockPage.rateLimit | int | 120 | cluster | Requests per minute per client. Most block page requests one client address may make per minute, e.g. 120, with bursts up to the same number; beyond it the page answers 429 Too Many Requests. 0 removes the limit. Allowed: range 0-100000. Environment: KUDURRU_BLOCKPAGE__RATELIMIT |