Example of a setup with two Recursors using systemd

In this example we set up two Recursor instances running under systemd supervision. Each instance will offer its record cache content to other instances.

The first instance will start without a hot cache, but the second instance will retrieve hot cache contents from the already running instance. If an instance is restarted it will retrieve cache content from the instance that was not restarted.

Setup the first Recursor with no instance name

  1. Make sure your environment has a NATS server running and note the IP and port it is listening on. Check its configuration, it should allow at least 8MB for its maximum payload size. Consult https://nats.io for more detail on available options.

  2. Copy the example configuration to the Recursor’s configuration directory and edit the natsServer.host and natsServer.port values to match the values noted in the previous step:

# cp examples/recursornatsconf.yml /etc/powerdns
# edit /etc/powerdns/recursornatsconf.yml
  1. Add the script to start the Plexus functionality to the Recursor configuration:

dnssec:
  # validation: process # default
  trustanchorfile: /usr/share/dns/root.key
recursor:
  hint_file: /usr/share/dns/root.hints
  include_dir: /etc/powerdns/recursor.d
  security_poll_suffix: ''
  lua_start_stop_script: /usr/share/lua/5.1/pdns-recursor/natsspawn.lua # <- add this line
incoming:
  # listen:
  # - 127.0.0.1 # default
outgoing:
  # source_address:
  # - 0.0.0.0 # default
  1. Create and enable the default first Recursor instance (as this is the first instance started in the queue group this instance wil not start up with a hot cache):

# systemctl enable pdns-recursor
# systemctl start pdns-recursor
# jourtnalctl -u pdns-recursor | tail # to validate correct startup

Apr 15 11:38:41 pepper pdns-recursor[155643]: msg="Reading Nats config from file" subsystem="lua" level="0" prio="Info" tid="0" ts="1744709921.652" path="/etc/powerdns/recursornatsconf.yml"
Apr 15 11:38:41 pepper pdns-recursor[155643]: msg="Nats Lua code loading" subsystem="lua" level="0" prio="Info" tid="0" ts="1744709921.652" host="127.0.0.1" port="4222" queue="pdns_recursor.pu  blisher" subject="pdns_recursor.recordCache"
Apr 15 11:38:41 pepper pdns-recursor[155643]: msg="Nats connected" subsystem="lua" level="0" prio="Info" tid="0" ts="1744709921.652" host="127.0.0.1" port="4222"
Apr 15 11:38:41 pepper pdns-recursor[155643]: msg="Nats requesting cache data from other recursor" subsystem="lua" level="0" prio="Info" tid="0" ts="1744709921.652" subject="pdns_recursor.recordCache"
Apr 15 11:38:41 pepper pdns-recursor[155643]: msg="Nats waiting for requests" subsystem="lua" level="0" prio="Info" tid="0" ts="1744709921.653" queue="pdns_recursor.publisher" subject="pdns_recursor.recordCache"
  1. Do a query to get records into the record cache:

# dig @127.0.0.1 powerdns.com

Setup the second Recursor with instance name “1”

  1. Copy the first Recursor instance’s configuration file to the second:

# cp /etc/powerdns/recursor.conf /etc/powerdns/recursor-1.conf
  1. Edit the incoming section in the newly created file:

dnssec:
  # validation: process # default
  trustanchorfile: /usr/share/dns/root.key
recursor:
  hint_file: /usr/share/dns/root.hints
  include_dir: /etc/powerdns/recursor.d
  security_poll_suffix: ''
  lua_start_stop_script: /usr/share/lua/5.1/pdns-recursor/natsspawn.lua
incoming: # <- edit this section to make the recursor instance 1 listen on a non-default port
  listen:
  - 127.0.0.1:5353
outgoing:
  # source_address:
  # - 0.0.0.0 # default
  1. Copy the nats config file to be used by the Recursor -1 instance. This file does not need to be edited. Then create and start this instance:

# cp /etc/recursornatsconf.yml /etc/recursornatsconf-1.yml
# systemctl enable pdns-recursor@1
# systemctl start pdns-recursor@1
# journalctl -u pdns-recursor | tail # to validate correct startup

Apr 15 11:42:47 pepper pdns-recursor-1[157690]: msg="Reading Nats config from file" subsystem="lua" level="0" prio="Info" tid="0" ts="1744710167.669" path="/etc/powerdns/recursornatsconf-1.yml"
Apr 15 11:42:47 pepper pdns-recursor-1[157690]: msg="Nats Lua code loading" subsystem="lua" level="0" prio="Info" tid="0" ts="1744710167.669" host="127.0.0.1" port="4222" queue="pdns_recursor.publisher" subject="pdns_recursor.recordCache"
Apr 15 11:42:47 pepper pdns-recursor-1[157690]: msg="Nats connected" subsystem="lua" level="0" prio="Info" tid="0" ts="1744710167.669" host="127.0.0.1" port="4222"
Apr 15 11:42:47 pepper pdns-recursor-1[157690]: msg="Nats requesting cache data from other recursor" subsystem="lua" level="0" prio="Info" tid="0" ts="1744710167.669" subject="pdns_recursor.recordCache"
Apr 15 11:42:47 pepper pdns-recursor-1[157690]: msg="Nats waiting for requests" subsystem="lua" level="0" prio="Info" tid="0" ts="1744710167.669" queue="pdns_recursor.publisher" subject="pdns_recursor.recordCache"
Apr 15 11:42:47 pepper pdns-recursor-1[157690]: msg="Nats received pdns_recursor.getRecordCacheRecords data" subsystem="lua" level="0" prio="Info" tid="0" ts="1744710167.670" length="13194"
Apr 15 11:42:47 pepper pdns-recursor-1[157690]: msg="Processed cache dump" subsystem="recordcache" level="0" prio="Info" tid="0" ts="1744710167.670" identity="pepper" inserted="66" processed="93" protocolVersion="1" size="13194" time="1744710167" version="5.2.3"

The log lines above show the second instance retrieving record cache content from the first instance. In this example we have shown two instances, but there can be more. The instances do not have to run on the same system as long as they are part of the same NATS service.

Running the same query on the second instance will provide a result from the cache.

# dig @127.0.0.1 -p 5353 powerdns.com