Skip to content

Public repository describing the setup and deployment of Pi-hole and Cloudflare Proxy DNS (Tunnel Client) using Docker Compose.

Notifications You must be signed in to change notification settings

dynamic-stall/pihole-docker

Repository files navigation

Pi-hole Ad Blocker with Cloudflare Proxy DNS


BLUF: This project will allow you to use Docker Compose to run Pi-hole and Cloudflare Tunnel Client in tandem to achieve DNS-Over-HTTPS. Not to mention network-level ad blocking!


NOTE: If your use case is to block YouTube or Hulu ads... find another use case 😜.


DISCLAIMER: This is an educational experience aimed at deepening one's understanding of networking and containerization. Pi-hole is open-source software licensed under the European Union Public License (EUPL), which allows for its free use and modification. Please refer to this link for trademark rules and brand guidelines. As always, use your best judgement and/or the Internet for guidelines on things you should and should not be doing with this software.


Requirements

  • Docker Compose or Docker Desktop (Docker install scripts for RHEL/CentOS Stream 8-9, Pi OS, and macOS included in this repo)

  • Your pick of operating system, generally... (Windows installs will require WSL v1.2 or later) (macOS version 10.13 -- High Sierra -- and newer is what ChatGPT and Google Gemini reccommend) (Most flavors of Linux are supported, but Google is always your friend; I'm using CentOS Stream 9)

  • Preferably at least 4GB of RAM (2GB might work, but you likely won't be happy with it)

  • (OPTIONAL) Cloudflare Zero Trust account for enhanced DNS capabilities


Build Instructions

i. (OPTIONAL) Create/log into your Cloudflare account and Navigate to Zero Trust from the lefthand menu. Expand Gateway and select DNS Locations.


ii. (OPTIONAL) Click the blue Add a location button. Choose whichever name you'd like (this matters to no one but you), then click the Add IP button; this should auto-populate with your current public address.


iii. (OPTIONAL) Check the Set as Default DNS Location box and click Add location in the bottom-right.


iv. (OPTIONAL) Click on your newly created location under the Location name menu. Under Location details, record the DoH endpoint URL. Save that value for later.

cloudflare-gateway-dns-locations


  1. Clone this repository:
git clone https://github.com/dynamic-stall/pihole-docker
cd pihole-docker

  1. Create a .env from the example file (be sure to add your personalized variables):
cp .env.example .env

  1. You can change the configuration values of Pi-hole and Cloudflare Tunnel Client in the docker-compose.yml file. Port configs should generally be left as is, unless you have specific requirements based on your environment. IP address ranges can be left as is, as Docker will create the bridge network for you (check notes at the end of that file as well as the troubleshooting steps in one of the install-docker_* scripts for details on how to specify existing external networks). I advise you leave the CONTAINER names as is; another script relies on them being named, "pihole" and "cloudflared." HOSTNAME changes will affect nothing but the joy in your heart.


  1. To create the directories for the Docker volumes, set your Pi-hole password, and build the Docker containers, run build-pihole.sh:
./build-pihole.sh

This bash script will:

  • Create your local directories -- and set permissions -- for the Pi-hole container (if not already set up)

  • Establish a Docker group for the current user (if one hasn't been created already)

  • Start Docker Compose (in daemon mode)

  • Build your containers to spec (successfully, one would hope)

  • Set your Pi-hole password (no password file needed... who wants a plaintext file with sensitive info lying around?)

  • Display the containers created and their current status via docker ps command


If you see either container stuck in a Restarting state, something went wrong during the build; chances are, it's related to your volume directories (permissions or their very existence). You can also try restarting either stuck container (or re-composing) as a troubleshooting step:

docker restart <container-name>

<OR>

docker compose up -d

If the restarting status persists, check your volume directories (default: /srv/docker/pihole/). Ensure that the directories are owned by root:docker with proper permissions. The script sets permissions to 770 (rwxrwx---) by default, which allows the container to function but is more permissive than necessary. For improved security, you could reduce permissions to 750 (rwxr-x---) for directories and 640 (rw-r-----) for files while still maintaining functionality. Additionally, confirm that your user account is a member of the docker group (which the build-pihole.sh script handles automatically).

Note: Newly created files in these directories will inherit permissions based on the container's umask, not manually set permissions.


Pi-hole Web Admin UI

Once the Pi-hole Docker container has started, you can access Pi-hole's Web Admin UI at http://localhost:8061/admin.

pi-hole-web-admin-home


Enter the Web Admin password you set earlier.


If the password needs to be reset, run the following command:

docker exec -it <pihole-container-name> pihole setpassword
  • (Entering a blank password will remove the password requirement altogether.)

You can check the Upstream DNS Servers by navigating to Settings from the lefthand menu and selecting the DNS tab. You should see the IP address set for your Cloudflare Tunnel Client under Custom DNS Servers.

pihole-dash-dns-settings


Updating Blocklists and Allowlists

Completely optional, but you can further bolster the blocklists and/or allowlists your Pi-hole instance uses (the default Steven Black list is great on its own, but you may have a more stringent use case). If you'd like, you may make use of the additional blocklist and allowlist text files I've included in this repo. The easiest way to accomplish this is to navigate to the Subscribed lists group management page in your Pi-hole dashboard, which you can find by clicking Lists from the left-hand menu. Then, open up the text files and copy/paste each into URL field under Add a new subscribed list. Enter an optional comment to better organize each list item, then click either the red Add blocklist or the green Add allowlist button on the right depending on which URL type you're pasting.

pihole-lists-add


Next, navigate to Tools --> Update Gravity from the left-hand menu. Click the blue Update button and wait for the update to complete before navigating to any different pages (there should be a "[✓] Done." at the very end of the output that displays).

pihole-update-gravity


NOTE: Pi-hole auto-updates Gravity each Sunday as long as your container is up, running, and connected to the Internet (I don't know at what time, but I'm sure Google knows... LOL).

Note II: You can also update your lists at the CLI via pihole deny or pihole allow commands; then run pihole -g to update the database. Sample commands below:

Update blocklist via CLI:

# Add one (or more) URL(s) to your blocklist:
docker exec -it <pihole-container-name> pihole deny site.com [site2.com site3.com ...]

# Update database:
docker exec -it <pihole-container-name> pihole gravity -g

Update allowlist via CLI:

# Add one (or more) URL(s) to your allowlist:
docker exec -it <pihole-container-name> pihole allow site.com [site2.com site3.com ...]

# Update database:
docker exec -it <pihole-container-name> pihole gravity -g

Network Configuration

This last and most important step depends on your network setup and deployment strategy.


  • NOTE: If you have your Pi-hole container up and running, but Cloudflared is still misbehaving, you can deploy the Pi-hole container on its own: simply change the DNS servers Pi-hole is using under Settings (see: Pi-hole Web Admin UI section). Set the two custom IPv4 addresses to the Cloudflare DNS addresses you recorded earlier <OR> use one of the preset DNS locations (I'd still recommend choosing Cloudflare's 1.1.1.1, if nothing else...).

  • Note: I could have mentioned firewall configurations earlier than now... Depending on your server/PC setup, you may not need to worry about this; chances are if you think you might, you probably don't. Run netstat -tuln | grep <port-numbers> to verify. If nothing is returned at your terminal, go ahead and run the commands below to update your firewall.

    • The basic command (for Linux users) is:
     sudo firewall-cmd --add-port=<port_num>/<protocol> --permanent
    

    (where <port_num> is the port number, and <protocol> is the Transport-layer protocol: either tcp or udp; both for port 53)

    • ... followed by a:
    sudo systemctl reload firewalld

    (you're welcome... 😁).