# Ubuntu/DietPi + Pi-hole + Cloudflare DNS + DNS over HTTPS

**URL:** <https://forum.hhf.technology/t/ubuntu-dietpi-pi-hole-cloudflare-dns-dns-over-https/289>\
**Category:** Home Networking\
**Tags:** cloudflare-dns, cloudflare, dns-over-https, raspberry-pi\
**Created:** [October 24, 2024, 4:48am UTC](https://forum.hhf.technology/t/ubuntu-dietpi-pi-hole-cloudflare-dns-dns-over-https/289 "2024-10-24T04:48:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![hhf.technoloy](https://forum.hhf.technology/user_avatar/forum.hhf.technology/hhf.technoloy/32/68_2.png) [@hhf.technoloy](https://forum.hhf.technology/u/hhf.technoloy)\
**Post date:** [October 24, 2024, 4:48am UTC](https://forum.hhf.technology/t/ubuntu-dietpi-pi-hole-cloudflare-dns-dns-over-https/289/1 "2024-10-24T04:48:32Z")

</div>

# DietPi + Pi-hole + Cloudflare DNS + DNS over HTTPS

it can work on a vm running diet-pi

 ![image](https://forum-cdn.hhf.technology/original/1X/2e9104d5cc0fc5d4f0e39756c15183553faf495c.png)

> **[Lightweight justice for your SBC!](https://dietpi.com/#downloadinfo)**
>
> Optimised | Simplified | For everyone - Backed by community, DietPi is a minimal OS image for SBCs - Raspberry Pi, Odroid, PINE64 etc. Install software optimised for you!

## Summary

Quick and dirty setup instructions to get Pi-hole running with DoH via Cloudflare on a headless Raspberry Pi.

I was originally using Pi-hole with Quad9 as my upstream DNS provider, but noticed that my ISP (Spectrum) was still intercepting and answering some DNS queries so I’ve switched to Cloudflare and their Argo Tunnel client for DNS over HTTPS.

Yes, I know there are other options out there like `unbound`, `stubby`, DNS over TLS, and DNSCrypt, but as of this writing the whole encrypted DNS _thing_ still feels really runny so I went with `cloudflared` because it’s a single package that’s easy to configure, update, and remove. This combination gets me to a place where my network is using encrypted DNS + DNSSEC and should automagically support ESNI once Safari implements it, and I could easily back out of DNS over HTTPS if DoT or DNSCrypt becomes more fully-baked before DoH does. I’ll also happily switch back to Quad9 if they provide a DoH proxy package like `cloudflared`, since I prefer their DNS services for their malware domain filtering.

Written for macOS, using DietPi v6.22.3, Pi-hole v4.2.2, and cloudflared version 2019.4.0.

## Required Hardware

1. Raspberry Pi
  - My pick: $35 [RPi 3 B+](https://www.adafruit.com/product/3775) in a $9 [acrylic case with a 5V fan](https://www.amazon.com/gp/product/B01LXSMY1N/)

2. Class 10 MicroSD card — don’t skimp on the speed or size of the card!
  - My pick: $8 [32GB Samsung EVO Select UHS-1 MicroSD card with adapter](https://www.amazon.com/gp/product/B06XWN9Q99/)

3. Short Cat-5E patch cable — don’t use WiFi!
  - My pick: $1 [0.5ft Monoprice Snagless Flat Cat5e Cable](https://www.monoprice.com/product?p_id=9548)

**Total cost:** $53 + tax and shipping at time of writing, with everything rounded up to the nearest dollar

## Instructions

#### 1. Flash your MicroSD card with the DietPi image

1. Download latest DietPi for Raspberry Pi from [DietPi.com](https://dietpi.com/download)
2. Download latest balenaEtcher from [etcher.io](https://etcher.io/)
3. Unzip the `DietPi_RPi-ARMv6-Stretch.7z` image
4. Launch balenaEtcher and click “Select image”
5. Select the newly-unzipped `DietPi_RPi-ARMv6-Stretch.img`
6. Verify balenaEtcher has selected your MicroSD volume as its destination
7. Click “Flash!” and wait for the process to finish  
  

#### 2. Configure your DietPi install

1. Insert the newly flashed MicroSD card into your Pi and connect it to ethernet and power
2. Get your Pi’s IP address by looking for a host with the name “DietPi” in your router’s “Devices” list or using the free [Fing iOS app](https://itunes.apple.com/gb/app/fing-network-scanner/id430921107?mt=8)
3. Copy your SSH keys to the Pi
  1. Open a new Terminal window
  2. Verify your public key exists by running `ls ~/.ssh/id_rsa.pub`
    - If `ls` returns “No such file or directory” you will need to create a new keypair by running `ssh-keygen -t rsa` and pressing Enter when prompted for a location and passphrase

  3. Copy your public key to the Pi by running `ssh-copy-id root@<IPAddressFromStep2.2>`
    - Type “yes” and press Enter when prompted to continue
    - Type “dietpi” and press Enter when prompted for root’s password

4. SSH in to your Pi by running `ssh root@<IPAddressFromStep2.2>`
  - DietPi should automatically begin its setup process
  - Press Tab followed by Enter to accept the software license and run `DietPi-Update`

5. When prompted, choose whether or not to participate in DietPi-Survey
6. Once `DietPi-Update` is complete, press Enter to reboot
7. Wait 60 seconds or so for your Pi to reboot, then reconnect by running `ssh root@<IPAddressFromStep2.2>`
8. When prompted, choose whether or not to change the user passwords for DietPi
  - Since we’ve already configured DietPi to use passwordless SSH, I recommend setting a strong password here and saving it in your password manager

9. When prompted, select to disable the serial console
10. Once DietPi loads `DietPi-Software`, scroll down to `DietPi-Config` and press Enter to configure your DietPi install
  1. Display Options:
    - Select “Display Resolution” and choose “Headless”

  2. Language/Regional Options:
    - Select “Locale” and choose “en\_US.UTF-8”
    - Select “Timezone” and choose your local Time Zone
    - Ignore “Keyboard” since we’re setting this up as a headless server

  3. Security Options:
    - If you chose not to change the Pi’s passwords, you can do so here
    - Select “Hostname” and name your Pi something like “pihole” and reboot when prompted

11. Wait 60 seconds or so for the Pi to reboot, then reconnect by running `ssh root@<IPAddressFromStep2.2>`
12. Once DietPi-Software resumes, press Tab followed by Enter to select and finish setup, which should return you to a `root@DietPi:~#` prompt  
  

#### 3. Install `avahi-daemon` to enable Bonjour

1. From the DietPi prompt, install `avahi-daemon` by running `sudo apt-get install avahi-daemon`
2. When prompted to continue, enter ‘y’ and press Enter
3. You should now be able to connect to your Pi by using the hostname set in step 2.10.3, e.g. pihole: `ssh root@pihole.local`  
  

#### 4. Install Pi-hole

1. From the DietPi prompt, begin Pi-hole installation by running `curl -sSL https://install.pi-hole.net | bash`
2. Wait for Pi-hole setup to download its dependencies, then press Enter to proceed past the welcome, donate, and static IP messages
3. When prompted, select Cloudflare as your Upstream DNS Provider
4. Choose which blocklists to enable (I left them all on) then press Tab followed by Enter
5. Choose whether to block ads over IPv4 or IPv6 then press Tab followed by Enter
6. When prompted, select to use your current network settings as a static address
7. Press Enter to proceed past the warning about static IPs
8. Press Enter to enable the web admin interface
9. Press Enter to install lighttpd
10. Press Enter to enable logging of queries
11. Use the arrow keys to select the level of logging privacy you desire (I left it on “0 Show everything”)
12. Wait for installation to proceed
13. At the “Installation Complete!” prompt, **make sure you copy the login password for the web admin interface!**
  - No seriously, copy this into your password manager – you’ll need it every 7 days if you want to access your Pi-hole’s web admin interface  
  

#### 5. Install `cloudflared`

1. From the DietPi prompt, download the latest stable `cloudflared` release by running `wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz`
2. Decompress the archive you just downloaded by running `tar -xvzf cloudflared-stable-linux-arm.tgz`
3. Move `cloudflared` into place by running `sudo cp ./cloudflared /usr/local/bin`
4. Remove the leftover files by running `rm cloudflare*`
5. Make `cloudflared` executable by running `sudo chmod +x /usr/local/bin/cloudflared`
6. Check `cloudflared` version to verify installation by running `cloudflared -v`
  - You should get a response similar to `cloudflared version 2019.4.0 (built 2019-04-03-1938 UTC)`

7. Create a cloudflared user to run the daemon by running `sudo useradd -s /usr/sbin/nologin -r -M cloudflared`
8. Create a default preference file for `cloudflared`
  1. From the DietPi prompt, run `sudo nano /etc/default/cloudflared`
  2. Paste the following 2 lines into `nano`:

```auto
# Commandline args for cloudflared
CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query

```

  1. Press Ctrl+O to save your changes
  2. Press Ctrl+X to exit `nano`

9. Run the following 2 commands to update permissions for `cloudflared` and its newly-created preferences file:

```auto
sudo chown cloudflared:cloudflared /etc/default/cloudflared
sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared

```

1. Create a `systemd` service file
  1. From the DietPi prompt, run `sudo nano /lib/systemd/system/cloudflared.service`
  2. Paste the following 15 lines into `nano`:

```auto
[Unit]
Description=cloudflared DNS over HTTPS proxy
After=syslog.target network-online.target

[Service]
Type=simple
User=cloudflared
EnvironmentFile=/etc/default/cloudflared
ExecStart=/usr/local/bin/cloudflared proxy-dns $CLOUDFLARED_OPTS
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

```

  1. Press Ctrl+O to save your changes
  2. Press Ctrl+X to exit `nano`

2. Enable the newly-created `systemd` service by running the following 3 commands:

```auto
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared

```

  

#### 6. Turn it on

1. In the Pi-hole Web Admin interface, select “Settings” from the sidebar and click on the “DNS” tab
2. In the “Upstream DNS Providers” block, deselect all active checkboxes in the Cloudflare row, and enter `127.0.0.1#5053` in the “Custom 1 (IPv4)” block and check its checkbox to point Pi-hole at your `cloudflared` service
3. This seems counterintuitive since we want DNSSEC enabled, but leave the “Use DNSSEC” checkbox in the “Advanced DNS Settings” block unchecked (`cloudflared` handles this for us)
4. Scroll to the bottom of the page and click “Save”
5. Once the Pi-hole Web Admin interface confirms that your changes have been saved, go to your router’s DNS settings and enter your Pi-hole’s address (from Step 2.2) and save your changes
6. Flush your Mac’s DNS cache
  1. Open a new Terminal window
  2. Run `sudo dscacheutil -flushcache`, enter your admin password, and press Enter  
  

#### 7. Test your setup

1. Verify your Mac is pointed at your Pi-hole for its DNS server by launching System Preferences and clicking on Network
  - Your active interface’s “DNS Server” should show the IP address from Step 2.2

2. Visit Cloudflare’s [Browsing Experience Security Check](https://www.cloudflare.com/ssl/encrypted-sni/)
  - You should see green checkmarks next to “Secure DNS”, “DNSSEC”, and “TLS 1.3”
  - As of this writing no major browsers support Encrypted SNI so you should see a red X next that feature  
  

And that’s it! 🍾🎉

All of the devices on your LAN/WLAN should be up and running with a faster and ad-free browsing experience. Some devices may need to disconnect and reassociate with your network or be rebooted to pick up the DNS change.

It does have to bypass unbound…but that is fine…becuase it is going directly to the cloudflare 1.1.1.1 authoritative DNS servers

Using this method, Installed cloudflared

> **[Connect to 1.1.1.1 using DoH clients](https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/dns-over-https-client/)**
>
> Learn how to connect to Cloudflare's 1.1.1.1 using DNS over HTTPS (DoH) clients.

added --port 5336 to this line in the service script  
`ExecStart=/usr/local/bin/cloudflared proxy-dns --port 5336`

Nice thing is Pi-hole is caching the hits just like before…no longer need unbound since it’s full encrypted to cloudflare DNS servers

Changed the upstream port in Pi-hole server to 127.0.0.1#5336 and baam

 ![image](https://forum-cdn.hhf.technology/original/1X/f8ab831e21f7daa3d46583870c3b379cf67b4ee7.png)

## Sources

[DietPi setup](https://dietpi.com/phpbb/viewtopic.php?t=9)

> **[How does DNS on HTTPS (DoH) improve online privacy? - The Business Gigs](https://thebusinessgigs.com/dns-https-doh-improve-online-privacy/)**
>
> Companies like Microsoft, Google, and Mozilla are promoting the development of DNS through HTTPS (DoH). This technology will encrypt DNS lookups to improve online privacy and security. But this is controversial: Comcast is lobbying...

[DNS over HTTPS with Cloudflare](https://docs.pi-hole.net/guides/dns-over-https/)

---

<div class="post-metadata">

**Author:** ![hhf.technoloy](https://forum.hhf.technology/user_avatar/forum.hhf.technology/hhf.technoloy/32/68_2.png) [@hhf.technoloy](https://forum.hhf.technology/u/hhf.technoloy)\
**Post date:** [October 24, 2024, 5:16am UTC](https://forum.hhf.technology/t/ubuntu-dietpi-pi-hole-cloudflare-dns-dns-over-https/289/2 "2024-10-24T05:16:33Z")

</div>

PiHole Working Compose

```yaml
# Generated from https://github.com/pi-hole/docker-pi-hole/?tab=readme-ov-file#quick-start
name: pihole # swapped version to this. version is obsolete

# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    # For DHCP it is recommended to remove these ports and instead add: network_mode: "host"
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      # - "67:67/udp" # Only required if you are using Pi-hole as your DHCP server
      - "8080:80/tcp" # changed to port 8080
    dns: 127.0.0.1 # system resolver, this is required (at least for my setup)
    environment:
      TZ: America/Denver # my timezone
      WEBPASSWORD: "blah123" # password
      PIHOLE_DNS_: "1.1.1.1;1.0.0.1" # CloudFlare DNS (why do they use Google by default??)
      FTLCONF_LOCAL_IPV4: {{local IP address}} # So PiHole "knows" that it is this address, other wise 403 admin site
    # Volumes store your data between container upgrades
    volumes:
      - ./etc-pihole:/etc/pihole
      - ./etc-dnsmasq.d:/etc/dnsmasq.d
    # https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
    # cap_add:
      # - NET_ADMIN # Required if you are using Pi-hole as your DHCP server, else not needed
    restart: unless-stopped

```

---

<div class="post-metadata">

**Author:** ![hhf.technoloy](https://forum.hhf.technology/user_avatar/forum.hhf.technology/hhf.technoloy/32/68_2.png) [@hhf.technoloy](https://forum.hhf.technology/u/hhf.technoloy)\
**Post date:** [October 24, 2024, 3:56pm UTC](https://forum.hhf.technology/t/ubuntu-dietpi-pi-hole-cloudflare-dns-dns-over-https/289/3 "2024-10-24T15:56:28Z")

</div>

```yaml
version: "3"

services:
  traefik:
    image: traefik:v2.10
    container_name: 'traefik'
    command:
      - '--log.level=DEBUG'
      - '--api.insecure=true'
      - '--api.dashboard=true'
      - '--api.debug=true'
      - '--providers.docker=true'
      - '--providers.docker.exposedbydefault=false'
      - '--entrypoints.web.address=:80'
    ports:
      - '80:80/tcp'
      - '8080:8080/tcp'
    volumes:
      - '/mnt/userdata/var/run/docker.sock:/var/run/docker.sock:ro'
    labels:
      - 'traefik.docker.network=docker_pisvc' 
      - 'traefik.http.routers.traefik.rule=Host(`traefik.rpi.home`'
      - 'traefik.http.routers.traefik.service=api@internal'
      - 'traefik.http.middlewares.traefik.entrypoints=web'
    restart: unless-stopped
    networks:
      - pisvc

  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    restart: unless-stopped
    env_file:
      - ./env/pihole.env
    volumes:
      - './etc/pihole:/etc/pihole'
      - './etc/dnsmasq.d:/etc/dnsmasq.d'
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.pihole.rule=Host(`pihole.rpi.home`)'
      - 'traefik.http.routers.pihole.entrypoints=web'
      - 'traefik.http.middlewares.pihole.addprefix.prefix=/admin'
      - 'traefik.http.services.pihole.loadBalancer.server.port=80'
    cap_add:
      - NET_ADMIN
    ports:
     - "53:53/tcp"
     - "53:53/udp"
     - "67:67/udp"
     - "853:853/tcp"
    networks:
      - pisvc

  dashboard:
    image: joseluisq/static-web-server:2
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.dashboard.rule=Host(`rpi.home`)'
      - 'traefik.http.routers.dashboard.entrypoints=web'
    volumes:
      - './var/www:/var/www:ro'
    environment:
      - 'SERVER_ROOT=/var/www'
    networks:
      - pisvc

  ptagent:
    image: portainer/agent:2.18.1
    volumes:
      - /mnt/userdata/var/run/docker.sock:/var/run/docker.sock
      - /mnt/userdata/var/lib/docker/volumes:/var/lib/docker/volumes
    restart: unless-stopped
    networks:
      - portainer

  portainer:
    image: portainer/portainer-ce:2.18.1
    command: -H tcp://ptagent:9001 --tlsskipverify --http-enabled
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.portainer.rule=Host(`portainer.rpi.home`)'
      - 'traefik.http.services.portainer.loadbalancer.server.port=9000'
      - 'traefik.http.routers.portainer.entrypoints=web'
    volumes:
      - portainer_data:/data
    restart: unless-stopped
    networks:
      - portainer
      - pisvc

networks:
  pisvc:
    driver: bridge
  portainer:
    driver: bridge 

volumes:
  portainer_data: {}

```
