PiHole-Wireguard-and-Homebridge-on-Raspberry-Pi-Zero-2

Update, added ODOH and DNSCrypt: Removed cloudblock, and added dnscrypt-proxy to enable Oblivious-DNS-Over-HTTPS (ODoH) via DNSCrypt. In brief, DNS requests are now sent encrypted to an 'oblivious' relay, which then sends anonymized DNS requests to the resolver.


These are my install notes for setting up Pi-Hole, PiVPN, and Homebridge on my new Raspberry Pi Zero 2w. Please feel free to contribute notes, suggestions, clarifications, etc.

Pi-Hole provides DNS-based adblocking. This setup will block ads and telemetry on all devices in the home, and specific devices on-the-go using Wireguard.

Homebridge allows my home to recognize my assorted smart devices as HomeKit compatible. With this setup I can access both PiHole and Homebridge on my local network or out-of-home.

Table of contents

  1. Equipment
  2. Build Pi Zero 2
  3. Setup the Pi - add ZRAM and over/unclocking
  4. Install Pi-Hole
  5. Install PiVPN
  6. Install DNSCrypt - customize the config for ODOH
  7. Router setup
  8. Useful Pihole addons - add lists, sync multiple pi-holes, check which lists are being used
  9. Install HomeBridge
  10. Support this project

Equipment

I purchased a Raspberry Pi Zero 2 Starter kit, which included:

  • Raspberry Pi Zero 2 W
  • A UniPiCase Zero Standard Case
  • Mini HDMI to HDMI Adapter
  • USB OTG Cable
  • 32GB Class 10 SD Card - blank
  • 5.1V 2.5A Power Supply
  • 2x20 Male Header Strip
  • Set of two heatsinks

For this project, I won't be using the adapters or the header strip.

Build Pi Zero 2

  • Select the largest of the two heatsinks, peel off the sticker backing on the bottom, and attach it to the chip. You don't need the smaller heatsink.
  • Open the UniPiCase by pinching the tabs on the bottom and lightly pulling up on the top of the case
  • Put the front plate from the UniPiCase onto the Pi Zero 2, then gently push the front plate and Pi Zero 2 down into the bottom of the case. There's a little tab on the left that will hold it in place.
  • Leave the top off for now, but you can stick the little rubber feet onto the bottom of the case at this point

Get the SD card ready

  • Go to raspberrypi.com and download and install the Raspberry Pi Imager. I'm using a Mac for this install
  • I selected Raspberry Pi OS Lite 32-bit (legacy) by going to "other" section.
    • Lite: we don't need a desktop environment
    • Legacy: Bullseye (legacy) is presently required for cloudblock, and it looks like gravity-sync as well.
    • 32 vs 64: There's an exceptionally detailed techincal writeup on the Pi Zero 2 here that suggests 32-bit systems are more memory efficient on a memory-limited system such as this. However, some things like cloudflare are dropping 32-bit support. Hence, I switched to a 64-bit build for longer-term stability.
  • Before continuing, select advanced options:
    • Enable SSH: I selected allow public-key authenitcation only
    • You can leave the default/prefilled option for set authorized_keys for 'pi'. This automatically creates the required authorization keys. That means I don't have to use a password when connecting to my Pi from this computer
    • I entered a key generated by Termius, my new SSH program.
    • Set username and password
    • Set-up wifi: Set wifi SSID and password
  • Write the SD card

Setup the Pi

Connect to the Pi

  • Insert the SD card into the Pi, snap on the lid, and plug your Pi in to the A/C adapter using the right-most slot
  • Your Pi will automatically connect to your wifi. For me, the easiest way to find the Raspberry Pi's IP address was to look for it on my network using my router's app
  • (Recommended) Set a static IP for the Pi I used my wireless router settings to reserve its IP address (i.e., so the Pi doesn't change its IP on me)
  • Open Terminal and connect to it remotely by using SSH. To do so type or copy/paste ssh pi@rasberrypi.local. If you changed your Pi username, replace pi with username. If you selected allow public-key authentication only, you shouldn't have to use a password to connect.
  • Additional troubleshooting step if you've re-flashed the SD card (e.g., setting it up again from scratch):
  • Use ssh-keygen -R raspberrypi.local If you are re-creating your SD card using your previous/existing keys you may get a scary-looking error when you try and connect via SSH. This command will delete your previous, unique fingerprint and generate a new one to fix this error. If you do so, run this on your home machine prior to ssh.

Increase the Pi's memory

Prior to running ansible as part of installing Cloudblock, we need to increase the available memory or we run into errors during the install process due to limited free memory on the Pi Zero 2. There are two ways to do this, I've tested both and I'm using ZRam currently:

enable ZRam

  • Zram creates compressed RAM based block storage. This compression allows additional memory inside RAM in exchange for the processing power used for compression. This has the benefit of being faster than using the SD card for swap memory.

  • To enable, use sudo apt install zram-tools

  • (optional) increase Pi's tendency to use swap now that we are using Zram (for more information, see source for more details).

    • Use sudo nano /etc/sysctl.conf to add the following to the end of your /etc/sysctl.conf file:

      vm.vfs_cache_pressure=500
      vm.swappiness=100
      vm.dirty_background_ratio=1
      vm.dirty_ratio=50

      Then enable with:

      sudo sysctl --system

(Optional) Overclock the Pi

This carries risk. Please read and review your options first. In particular, you'll need some way to deal with heat. See discussion here for tested values, I went with relatively safe numbers: https://forums.raspberrypi.com/viewtopic.php?t=322734

sudo nano /boot/config.txt

Then paste the following to the end of the file:

# Overclock
arm_freq=1200
over_voltage=2
core_freq=500

Reboot

(alternative) Underclock the Pi

Rather than overclocking the Pi, you may wish to underclock it for additional power savings and/or thermal management. Follow the same steps above and use

# Underclock
arm_freq=600
gpu_freq=300
sdram_freq=400

(Optional) Add another device that can log-in to the Pi

  1. On your other computer that you want to also be able to log into the Pi from, open terminal and use ssh-keygen -t rsa to create a new SSH key pair. Alternatively, use one you already have.
  2. Copy the contents of the public key using cat ~/.ssh/id_rsa.pub
  3. Login to the Pi using your working device, then use echo [paste public key content here] >> ~/.ssh/authorized_keys.
  4. Alternatively, use a text-editor like nano ~/.ssh/authorized_keys and paste your public key content to a new line in that file. If you're working with nano, press esc then $ to wrap long strings of text (like these keys) to make it easy to read. Then hit control + x then y then enter to save your changes.
  5. Log out using your old device
  6. Log in using your new device, assuming you're using the defaults, you should be able to log-in using ssh pi@raspberrypi.local or ssh -i ~/.ssh/[key name] [username]@[raspberry pi ip] if you're not using defaults keys and/or user names
  7. Repeat steps 1-6 on any other devices you want to add

(Optional) Create a host file to make it easier to log in if you're not using default keys

  • If you're not using the default key name of id_rsa (e.g., you created your own name), make a file called config in your home computer's ~/.ssh/ directory and include the following

  • Host [Raspberry Pi IP]
    IndentityFile ~/.ssh/[key name]
  • This will allow you to connect to your Pi in Terminal by just using ssh [username]@[raspberry pi ip]. If you skip this step, you'll need to specify the name of your key file every time you connect, as in: ssh -i ~/.ssh/[key name] [username]@raspberry pi ip]

Install Pi-Hole

  • The most up-to-date Pi-Hole installation instructions can be found here: https://docs.pi-hole.net/main/basic-install
  • Otherwise, go ahead and use the official install script: curl -sSL https://install.pi-hole.net | bash

Install PiVPN

  • The most up-to-date PiPVN instructions can be found here: https://www.pivpn.io
  • Otherwise, go ahead and use the official install script: curl -L https://install.pivpn.io | bash

Note: if you have a dynamic dns (DDNS) address, when PiVPN asks you if you want to use an IP or a DNS address, select DNS and enter the domain here.

Set up Wireguard for split-tunnel VPN, then begin adding devices

  • First, we want to change the default settings for Wireguard that are used to create the device configs.
  • I set this up as 'split-tunnel' meaning that I only send DNS and not all my data through my Pi. I also add my home network so when I'm on the VPN, I can access the services in my home server.
  • edit the PiVPN configuration with: sudo nano /etc/pivpn/wireguard/setupVars.conf. Change the AllowedIPs line to = the IP/32 above under DNS (which is your Pi-Hole DNS address), and optionally, add your home gateway (e.g., 192.168.68.0/24)
  • Then use pivpn add to create a new device config (e.g., iphone) and pivpn qr to display the qr cod

Setup devices with Wireguard profiles

  • Use the Wireguard QR codes that were generated to setup your mobile devices. I set the profiles to on-demand except when connected to my home wifi SSID. That means that as soon as I leave home, Wireguard will connect remotely to continue ad-blocking.
  • To download the Wireguard config files to your computer, use the following secure-copy commands. Make sure you are not connected by SSH when running this on your home computer: scp -r pi@raspberrypi.local:/opt/wireguard/peer*/ [destination on home computer]
  • For example, I saved them to a folder called pihole_configs in My Documents using: scp -r 'pi@raspberrypi.local:/opt/wireguard/peer*' ~/Documents/pihole_configs

Install DNScrypt

  • Refer to this guide, or proceed making sure to update the links to the most recent release from the main repo here.
  • Install DNSCrypt-proxy, and add the configuration file:
cd /opt

sudo wget https://github.com/DNSCrypt/dnscrypt-proxy/releases/download/2.1.5/dnscrypt-proxy-linux_arm-2.1.5.tar.gz

sudo tar -xf dnscrypt-proxy-linux_arm-2.1.5.tar.gz
sudo mv linux-arm dnscrypt-proxy && cd dnscrypt-proxy
sudo cp example-dnscrypt-proxy.toml dnscrypt-proxy.toml
sudo nano dnscrypt-proxy.toml
  • This will open a text-editor with the example configuration file, which you can customize for your setup
  • Here is mine already set to use ODOH: dnscrypt-proxy.toml
  • Save any changes to the file: CTRL + X then Y and Enter
  • Then start the service:
sudo ./dnscrypt-proxy -service install
sudo ./dnscrypt-proxy -service start
sudo systemctl status dnscrypt-proxy
  • Test the service with ./dnscrypt-proxy -resolve www.google.com, you should get something like:
Resolving [www.google.com] using 127.0.0.1 port 5350

Resolver      : 172.69.207.24

Canonical name: www.google.com.

IPv4 addresses: 142.251.32.68
IPv6 addresses: 2607:f8b0:400b:807::2004

Name servers  : no name servers found
DNSSEC signed : no
Mail servers  : no mail servers found

HTTPS alias   : -
HTTPS info    : [alpn]=[h2,h3]

Host info     : -

Set-up Pi-Hole for DNScrypt-proxy

  • Login to Pi-hole web interface, Goto settings / DNS / Select Custom 1 (IPv4) and enter: 127.0.0.1#5350. Select Custom 3 (IPv6) and enter ::1#5350.
  • Uncheck everything else in Upstream DNS Servers section.
  • Reboot the Pi via sudo reboot

Router setup

  • Go to your router settings, note these steps depend entirely on your own router model
  • Forward port 51820 to your Pi's local IP address to enable Wireguard to work properly
  • Set your primary DNS in your DHCP server settings to your Pi's local IP. Leave the secondary DNS blank.

Useful Pihole Addons

Easily add adlists and whitelists

I like the pihole list tool for adding adlists and whitelists, you can install it by SSH back to your Pi, then running sudo pip3 install pihole5-list-tool --upgrade . Select the Docker version once it launches, then choose the blocklists and whitelists options from the list that appeal to you.

Set up apps that use PiHole API token

You can use PiHole apps (e.g., Pi-Hole remote) by selecting https://, using your [Raspbery Pi IP] and port: 443 along with your PiHole's API token. I set up two PiHoles in the app PiHole - local and PiHole - remote. To set up remote, I used https://, 172.18.0.5, and port:443

Use the list tool to check which lists you're actually using

The Pihole Adlist Tool is a script that will analyze 30 days worth of adblocking to see which lists you're actually using. After running the script, it can automatically disable any lists that aren't being used. To run it, ssh into your PiHole then run:

 wget https://github.com/yubiuser/pihole_adlist_tool/archive/refs/tags/2.6.3.zip
 unzip 2.6.3.zip
 rm -r 2.6.3.zip
 cd pihole_adlist_tool-2.6.3
 sudo ./pihole_adlist_tool

Then follow the prompts, noting that it may take some time to run. Note that you might want to check for the latest release of the tool, as v2.6.3 might be out of date when you read this.

If PiHole is all you wanted, then you can stop here. If you're interested in also adding HomeBridge read on!

Gravity Sync

Use Gravity Sync to sync lists with a secondary Pi-Hole

First, you'll need to set a password for user Pi if you don't already have one using:

sudo passwd pi

Then run the installation script, you'll be prompted for your secondary Pi's IP address, and the username (e.g., root) and password of the system on which it is installed.

curl -sSL https://raw.githubusercontent.com/vmstan/gs-install/main/gs-install.sh | bash

I use gravity-sync push to push my lists from Cloudblock over to the new, secondary Pi.

Next

Install Homebridge

Support this project

If you found this guide helpful, please consider buying me a coffee by clicking the link below. I'll do my best to keep this guide up to date and as user-friendly as possible. Thank you and take good care!

Donate