# pdns-recursor-compose-gotchas > Use when PowerDNS Recursor dnstap framestream produces 0 events or a rec_control reloader sidecar keeps restarting under Docker Compose. Trigger symptoms: (1) dnstap collector shows recv_total=0 while the unix socket exists, (2) recursor has no obvious dnstap error logs, (3) a sidecar meant to run `rec_control reload-*` restarts with “Fatal: non-options (sh, while true; do ...)” or shell syntax errors. Fixes unix socket permissions (chmod 0666) and correct Compose entrypoint scripting. - Author: derp - Repository: Zerostate-IO/PowerBlockade - Version: 20260128125327 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/Zerostate-IO/PowerBlockade - Web: https://mule.run/skillshub/@@Zerostate-IO/PowerBlockade~pdns-recursor-compose-gotchas:20260128125327 --- --- name: pdns-recursor-compose-gotchas description: | Use when PowerDNS Recursor dnstap framestream produces 0 events or a rec_control reloader sidecar keeps restarting under Docker Compose. Trigger symptoms: (1) dnstap collector shows recv_total=0 while the unix socket exists, (2) recursor has no obvious dnstap error logs, (3) a sidecar meant to run `rec_control reload-*` restarts with “Fatal: non-options (sh, while true; do ...)” or shell syntax errors. Fixes unix socket permissions (chmod 0666) and correct Compose entrypoint scripting. --- # PowerDNS Recursor Compose Gotchas ## Problem 1) **dnstap framestream over unix socket yields 0 events** even though the socket path exists. 2) **recursor-reloader sidecar** (a loop running `rec_control reload-zones` / `reload-lua-config`) **keeps restarting** because the image’s default entrypoint is still `pdns_recursor` and your shell loop is being passed as CLI args. ## Context / Trigger Conditions ### A. dnstap no events - Recursor configured with Lua `dnstapFrameStreamServer("/var/run/dnstap/dnstap.sock", {logQueries=true, logResponses=true})` - Collector uses `github.com/dnstap/golang-dnstap` `NewFrameStreamSockInputFromPath("/var/run/dnstap/dnstap.sock")` - Collector logs show `recv_total=0` over time. - `ls -l /var/run/dnstap/dnstap.sock` shows it exists, often owned by `root:root` and mode like `srwxr-xr-x`. ### B. recursor-reloader restart loop - Container logs show errors like: - `Fatal: non-options (sh, while true; do ...) on the command line...` - or repeated `Syntax error: end of file unexpected (expecting "do")`. ## Solution ### A. Fix unix socket permissions for dnstap **Root cause:** the collector (server) creates the unix socket file with restrictive perms (often `0755` owned by root). Recursor may not run as root, so it cannot `connect()` to the socket. Recursor may also not log a clear error. **Fix:** 1. Ensure the socket directory is permissive (in recursor container entrypoint is fine): ```sh mkdir -p /var/run/dnstap chmod 0777 /var/run/dnstap || true ``` 2. After the collector binds the socket, `chmod` the socket to allow connects: ```go input, err := dnstap.NewFrameStreamSockInputFromPath(cfg.DnstapSocket) if err != nil { /* ... */ } _ = os.Chmod(cfg.DnstapSocket, 0o666) ``` ### B. Compose shell loop for rec_control: override entrypoint correctly **Root cause:** `powerdns/pdns-recursor-*` images use an entrypoint that starts `pdns_recursor` (often via `tini`). If you only set `command: sh -c ...`, Docker will pass `sh -c ...` as args to `pdns_recursor`. **Fix:** override the **entrypoint** to `sh -c