pdns_recursor uses unix domain sockets to communicate with the command-line utility rec_control. When the chroot= configuration parameter is set (the default setting is /var/empty), the rec_control program no longer works. The reason for the breakage is that a new unix domain socket is created for each rec_control request. The powerdns recursor looks for these files in LOCALSTATEDIR (defined in config.h) unless --socket-dir is specified on the command line or socket-dir is changed in /etc/powerdns/recursor.conf. When pdns_recursor is chrooted, it cannot access these files and therefore cannot respond to rec_control commands. An unfortunate side-effect of the socket-dir option is that it also changes where pdns_recusor puts its PID file. Therefore if the sysadmin changes it, the init.d script breaks and can no longer stop the daemon. I advocate changing the default LOCALSTATEDIR in config.h to /var/run/powerdns . This allows the following workaround to the chroot problem: mkdir -p /var/empty/var/run mv /var/run/powerdns /var/empty/var/run ln -s /var/empty/var/run/powerdns /var/run At this point, rec_control will create its sockets within the chroot-accessable portion of the filesystem. pdns_recursor will be able to respond to rec_control commands. Reproducible: Always Steps to Reproduce: 1. Set "chroot=/var/empty" in /etc/powerdns/recursor.conf (this is the ebuild default!) 2. /etc/init.d/precursor start 3. rec_control ping Actual Results: rec_control hangs Expected Results: rec_control gives "pong" response SuSE's solution is to use /var/run/pdns ... but conffiles on SuSE are also stored in /etc/pdns. I suggest, since gentoo uses /etc/powerdns, that /var/run/powerdns is used for consistency. It is also necessary to change the initscript to use the pid file in /var/run/powerdns. Aside from the PID file problem associated with changing the socket-dir entry in the config file (as noted above), it is also worth mentioning that rec_control does not parse the config file, so if LOCALSTATEDIR is not changed in the code and the socket directory is changed in the config file, it's always necessary to pass --socket-dir= to rec_control... Which is somewhat cumbersome. Is /var/empty really a good name for the chroot dir? It's not very descriptive.
I know that rec_control is broken. The main problem is that the recursor uses datagram sockets. When using stream sockets the recursor could pass the answer back the same way the request came in. I initially wrote the init script stop action with "rec_control quit" until I noticed that the chroot support breaks it. IMHO a chroot'ed daemon shouldn't need to open back a connection to the outside of the chroot. In an ideal world the recursor would only need an empty directory for chroot, hence the current uhm "historic" default is /var/empty.
I updated the package. The chroot directory is now /var/lib/powerdns, statedir is /var/run/powerdns, being a symlink to /var/lib/powerdns/var/run/powerdns. Init script now uses rec_control quit to stop the recursor and also has a ping command. Thanks!
I updated it once more. Our bootmisc init script will remove the symlink in /var/run during boot. I now made the state and chroot directory /var/lib/powerdns and /var/lib/powerdns/var/lib/powerdns a symlink to ../.. Not really clean, but that's the way it is. :(