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.
- Raspberry Pi
- My pick: $35 RPi 3 B+ in a $9 acrylic case with a 5V fan
- Class 10 MicroSD card โ don't skimp on the speed or size of the card!
- Short Cat-5E patch cable โ don't use WiFi!
- My pick: $1 0.5ft Monoprice Snagless Flat Cat5e Cable
Total cost: $53 + tax and shipping at time of writing, with everything rounded up to the nearest dollar
- Download latest DietPi for Raspberry Pi from DietPi.com
- Download latest balenaEtcher from etcher.io
- Unzip the
DietPi_RPi-ARMv6-Stretch.7z
image - Launch balenaEtcher and click "Select image"
- Select the newly-unzipped
DietPi_RPi-ARMv6-Stretch.img
- Verify balenaEtcher has selected your MicroSD volume as its destination
- Click "Flash!" and wait for the process to finish
- Insert the newly flashed MicroSD card into your Pi and connect it to ethernet and power
- 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
- Copy your SSH keys to the Pi
- Open a new Terminal window
- 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 runningssh-keygen -t rsa
and pressing Enter when prompted for a location and passphrase
- If
- 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
- 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
- When prompted, choose whether or not to participate in DietPi-Survey
- Once
DietPi-Update
is complete, press Enter to reboot - Wait 60 seconds or so for your Pi to reboot, then reconnect by running
ssh root@<IPAddressFromStep2.2>
- 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
- When prompted, select to disable the serial console
- Once DietPi loads
DietPi-Software
, scroll down toDietPi-Config
and press Enter to configure your DietPi install- Display Options:
- Select "Display Resolution" and choose "Headless"
- 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
- 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
- Display Options:
- Wait 60 seconds or so for the Pi to reboot, then reconnect by running
ssh root@<IPAddressFromStep2.2>
- Once DietPi-Software resumes, press Tab followed by Enter to select and finish setup, which should return you to a
root@DietPi:~#
prompt
- From the DietPi prompt, install
avahi-daemon
by runningsudo apt-get install avahi-daemon
- When prompted to continue, enter 'y' and press Enter
- You should now be able to connect to your Pi by using the hostname set in step 2.10.3, e.g. pihole:
ssh [email protected]
- From the DietPi prompt, begin Pi-hole installation by running
curl -sSL https://install.pi-hole.net | bash
- Wait for Pi-hole setup to download its dependencies, then press Enter to proceed past the welcome, donate, and static IP messages
- When prompted, select Cloudflare as your Upstream DNS Provider
- Choose which blocklists to enable (I left them all on) then press Tab followed by Enter
- Choose whether to block ads over IPv4 or IPv6 then press Tab followed by Enter
- When prompted, select to use your current network settings as a static address
- Press Enter to proceed past the warning about static IPs
- Press Enter to enable the web admin interface
- Press Enter to install lighttpd
- Press Enter to enable logging of queries
- Use the arrow keys to select the level of logging privacy you desire (I left it on "0 Show everything")
- Wait for installation to proceed
- 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
- From the DietPi prompt, download the latest stable
cloudflared
release by runningwget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
- Decompress the archive you just downloaded by running
tar -xvzf cloudflared-stable-linux-arm.tgz
- Move
cloudflared
into place by runningsudo cp ./cloudflared /usr/local/bin
- Remove the leftover files by running
rm cloudflare*
- Make
cloudflared
executable by runningsudo chmod +x /usr/local/bin/cloudflared
- Check
cloudflared
version to verify installation by runningcloudflared -v
- You should get a response similar to
cloudflared version 2019.4.0 (built 2019-04-03-1938 UTC)
- You should get a response similar to
- Create a cloudflared user to run the daemon by running
sudo useradd -s /usr/sbin/nologin -r -M cloudflared
- Create a default preference file for
cloudflared
- From the DietPi prompt, run
sudo nano /etc/default/cloudflared
- Paste the following 2 lines into
nano
:
# Commandline args for cloudflared CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query --upstream https://1.0.0.1/dns-query
- Press Ctrl+O to save your changes
- Press Ctrl+X to exit
nano
- From the DietPi prompt, run
- Run the following 2 commands to update permissions for
cloudflared
and its newly-created preferences file:
sudo chown cloudflared:cloudflared /etc/default/cloudflared
sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared
- Create a
systemd
service file- From the DietPi prompt, run
sudo nano /lib/systemd/system/cloudflared.service
- Paste the following 15 lines into
nano
:
[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
- Press Ctrl+O to save your changes
- Press Ctrl+X to exit
nano
- From the DietPi prompt, run
- Enable the newly-created
systemd
service by running the following 3 commands:
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared
- In the Pi-hole Web Admin interface, select "Settings" from the sidebar and click on the "DNS" tab
- In the "Upstream DNS Providers" block, deselect all active checkboxes in the Cloudflare row
- 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) - Scroll to the bottom of the page and click "Save"
- 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
- Flush your Mac's DNS cache
- Open a new Terminal window
- Run
sudo dscacheutil -flushcache
, enter your admin password, and press Enter
- 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
- Visit Cloudflare's Browsing Experience Security Check
- 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.