I struggled with the strange behavior of dhcpcd on my Raspberry Pi powered by Raspbian. The RPi does many things on my local network, including ad-blocking thanks to the pihole service.

I run pihole1 as a docker container, and it does its job perfectly well. Thanks to the port binding, I could bind port 53 (DNS) directly to the host and use its address as a DNS server.

Network configuration

I use a tool called dhcpcd to configure the static IP address for my Raspberry Pi. Also, in the configuration file dhcpcd.conf, I can also change DNS. Here’s what I did.

interface wlan0
static ip_address=192.168.1.102/24
static routers=192.168.1.1
static domain_name_servers=127.0.0.1 1.1.1.1 8.8.8.8

interface eth0
static ip_address=192.168.1.2/24
static routers=192.168.1.1
static domain_name_servers=127.0.0.1 1.1.1.1 8.8.8.8

For both interfaces (wlan0 and eth0), I configured static IP addresses and DNS, using my local pihole service as a primary DNS. I didn’t want to rely only on my local instance because in case of any error or even docker image update, I’d end up without DNS. Unfortunately, despite the configuration, the system saw only one DNS – 127.0.0.1.

Here’s what I found in resolv.conf:

# Generated by resolvconf
nameserver 127.0.0.1

The same happened even if I reorder DNS in the configuration. Below change generated the same resolv.conf.

# ...
static domain_name_servers=1.1.1.1 127.0.0.1 8.8.8.8
# ...

I removed the 127.0.0.1 entirely from the configuration to test if it made any difference. After reboot, resolv.conf presented a proper set of name servers.

# Generated by resolvconf
nameserver 1.1.1.1
nameserver 8.8.8.8

Let’s form the problem: using localhost (127.0.0.1) address in the domain_name_servers option in dhcpcd causes the rest of DNS to be ignored.

The resolv.conf.head file as a solution

After some research and reading docs, I stumbled upon a resolv.conf.head file, which is a way to prepend an additional name server to the resolv.conf file.

I changed the configuration of dhcpcd to use public DNS only.

# ...
static domain_name_servers=1.1.1.1 8.8.8.8
# ...

Subsequently, I created a /etc/resolv.conf.head with the localhost address as a nameserver.

# resolv.conf.head
nameserver 127.0.0.1

After reboot, it turned out that my localhost address defined in the additional header file was successfully added as the first nameserver in the resolv.conf. Ultimately, it looks as follows:

# Generated by resolvconf
nameserver 127.0.0.1
nameserver 1.1.1.1
nameserver 8.8.8.8

If you ever struggle with this crazy behavior, treat it like a potential solution. If you know the actual reason or have a better solution – please let me know.

Featured photo by Erwan Hesry on Unsplash.


  1. pihole is a self-hosted adblocker that works as a proxy for DNS queries, blocking requests related to tracking, advertisements, and other untrustworthy resources. ↩︎