==========
== 0x2f ==
==========

Update pihole's blocklist more often with cron

I’m using pihole in docker and an anti-phishing website blocking list from cert.pl. They recommend re-download the list every 5 minutes. Pi-hole by default updates the database only once a week. We need to increase the frequency.

I don’t really know why, but every Pi-hole forum thread says “just mount a file in the pihole docker container at etc/cron.d”, but that just doesn’t work. The job just never runs.

Here’s what I did instead: Instead of creating a /etc/pihole.d/somefile inside the contaier, I created a cron file on the host (the computer running docker, not inside the container).

So I created /etc/cron.d/pihole with the following contents:

*/5 * * * * root docker exec pihole pihole updateGravity > /tmp/gravity.log

Note that the /etc/cron.d/pihole file doesn’t contain any dashes, dots or underscores. Underscores are probably fine but I was just so pissed from the trial and error that I picked the simplst name. Just remember that it matters. Also note that the file contents end with a newline. I’m redirecting the stdout to /tmp/gravity.log so I can easily tell if the job ran or not.

The difference is that my host machine runs Debian which uses the cron (the Vixie Cron implementation) rather than the busybox crond that the pihole docker container uses.

Alternatively, you could probably create a separate container within your docker compose whose job it is to run “pihole -g” every 5 minutes.

Trobuleshooting of etc/cron.d inside the container not working

Before I created the host cron file, I troubleshooted inside the container a lot. Here’s what I did in case you wanna tinker more.

Here’s an example cron file:


* * * * * root echo hello > /tmp/test.log

Create a docker compose file that runs a pihole container and mounts the above file, named e.g. just “test” at /etc/pihole.d/test and make sure that the file is owned by root:root and has mode 644

docker exec -it pihole /bin/bash
# from now on below commands are run inside the container exec
$ ps aux | grep crond # find cron daemon pid
$ kill [cron daemon pid] # kill cron daemon so you can start it yourself from terminal
$ crond -f -l 0 -L /tmp/crond.log # start crond in foreground, with verbose loglevel, and log to /tmp/crond.log
# here open another terminal and also run docker exec -it pihole /bin/bash
# then in the new window run "tail -f /tmp/crond.log"

“test” just never runs. I guess it has to do with the “crond” implementation, which is the busybox crond. It may be missing some features. You could theoretically just append to /etc/crontabs/root inside the container and add a new job, but I didn’t want to screw with a file provided by the container as it can change in the future.

The crond manpage even explicitly says it looks for files in /etc/cron.d/ which makes it even more weird that it doesn’t work:

Cron searches /var/spool/cron for crontab files which are named after accounts in /etc/passwd; The found crontabs are loaded into the memory. Cron also searches for /etc/anacrontab and any files in the /etc/cron.d directory, which have a different format (see crontab(5))