Raspberry Pi 5 with pihole and grafana
Backstory
I’ve had and posted about working with Raspberry Pi’s before and recently bought the new Raspberry Pi 5. I picked mine up from CanaKit, and it’s almost complete silent! Woohoo! So I’m going to run this one running all the time and have it act like a server basically.
This post is about setting this up and tying it into Grafana Cloud for monitoring.
Assumptions
A couple basic ones:
- You’ve already put your Raspberry Pi, it’s connected to your network, you’re ready to rock.
- You’ve setup your Pi to have a static IP on your network. Most routers allow you to do this
- You’ve setup the
grafana-agent
on your Pi. Follow the docs in the instructions and it’ll give you a one-liner that’ll setup theapt
repo.
Setting up the pihole and grafana monitoring
Get Docker, or whatever you want to use to run your containers up and running. As of the writing on this document, the package name is docker.io
.
$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Package names may change, but I’m just using Docker with docker-compose
to get this up and running quickly:
sudo apt install docker.io docker-compose
(Optional) Personally, I like using the docker
command from an unprivieged user to limit the need to run it as root. To do this, you’ll need to change your na
sudo usermod -aG docker pi # substitute pi with your user
newgrp docker pi # substitute pi with your user
docker-compose.yml
For the configuration, I do a couple non-default things:
- I allow the Apple Private Relays to work and not be blocked.
FTLCONF_BLOCK_ICLOUD_PR
is how you pass that to the FTL config with pihole. Removing that line will block the relays. - I use the Cloudflare malware blocking name servers instead of Google name servers.
- I use Farenheit for temperatures because I’m American.
- I use a dark theme for the pihole interface. Don’t most people prefer dark at this point?
This is what your docker-compose.yml
could look like:
version: "3"
# 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"
- "80:80/tcp"
environment:
PIHOLE_DNS_: '1.1.1.2;1.0.0.2;2606:4700:4700::1112;2606:4700:4700::1002' # Cloudflare
DNSSEC: 'true'
TEMPERATUREUNIT: 'f'
QUERY_LOGGING: 'false'
WEBTHEME: 'default-dark'
TZ: 'America/Chicago'
WEBPASSWORD: 'Amaz1ngP4sswordF0rB1og' # This password is used in PIHOLE_PASSWORD, too
FTLCONF_BLOCK_ICLOUD_PR: 'false'
# 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
# See: https://github.com/eko/pihole-exporter
pihole_exporter:
container_name: 'pihole-exporter'
image: 'ekofr/pihole-exporter:latest'
# Agent is running in VM, so moved this config to ports
# expose:
# - 9617
ports:
- "127.0.0.1:9617:9617/tcp" # So agent on VM can poll this service on localhost
environment:
PIHOLE_HOSTNAME: '192.168.1.123' # UPDATE with the static IP of your Pi
PIHOLE_PORT: 80
PIHOLE_PASSWORD: 'Amaz1ngP4sswordF0rB1og' # Same as the password used on the pihold
INTERVAL: 30s
PORT: 9617
restart: always
It’s in the file as comments, you need to copy the password for the pihole for the pihole_exporter
service to be able to login to the pihole to get stats.
Now, bring it up!
docker-compose up -d
Validate the services are up and running and haven’t prematurely exited:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
88f378db2b37 pihole/pihole:latest "/s6-init" 4 minutes ago Up 4 minutes (healthy) 0.0.0.0:53->53/tcp, :::53->53/tcp, 0.0.0.0:80->80/tcp, 0.0.0.0:53->53/udp, :::80->80/tcp, :::53->53/udp, 67/udp pihole
9ae16022d83f ekofr/pihole-exporter:latest "./pihole-exporter" 4 minutes ago Up 4 minutes 127.0.0.1:9617->9617/tcp
Test out your configuration by using tools like dig
to query against the IP of you Pi from other machines on your network to make sure things are resolving:
$ dig @192.168.1.123 google.com
; <<>> DiG 9.10.6 <<>> @192.168.1.123 google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50127
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 75 IN A 142.250.115.138
google.com. 75 IN A 142.250.115.101
google.com. 75 IN A 142.250.115.113
google.com. 75 IN A 142.250.115.102
google.com. 75 IN A 142.250.115.100
google.com. 75 IN A 142.250.115.139
;; Query time: 82 msec
;; SERVER: 192.168.1.123#53(192.168.1.123)
;; WHEN: Sun Jan 21 11:01:46 CST 2024
;; MSG SIZE rcvd: 135
Update your router
Now that you’ve verified your that your pihole is responding to DNS requests from another machine on your network, you can update your router to use the pihole! If you need at least two name servers, see the notes in the Google Fiber section on how to add another interface to your Pi.
Example Grafana Agent Config
This configuration is used so I can collect metrics from the Pi for a Linux dashboard as well as the pihole.
integrations:
prometheus_remote_write:
- basic_auth:
password: YOUR-GRAFANA-CLOUD-TOKEN
username: YOUR-GRAFANA-CLOUD-ID
url: https://YOUR-GRAFANA-CLOUD-ENDPOINT/api/prom/push
agent:
enabled: true
relabel_configs:
- action: replace
source_labels:
- agent_hostname
target_label: instance
- action: replace
target_label: job
replacement: "integrations/agent-check"
metric_relabel_configs:
- action: keep
regex: (prometheus_target_sync_length_seconds_sum|prometheus_target_scrapes_.*|prometheus_target_interval.*|prometheus_sd_discovered_targets|agent_build.*|agent_wal_samples_appended_total|process_start_time_seconds)
source_labels:
- __name__
# Add here any snippet that belongs to the `integrations` section.
# For a correct indentation, paste snippets copied from Grafana Cloud at the beginning of the line.
node_exporter:
enabled: true
metric_relabel_configs:
# drop extensive scrape statistics
- action: drop
regex: node_scrape_collector_.+
source_labels: [__name__]
relabel_configs:
- replacement: 'pi5'
target_label: instance
- replacement: integrations/raspberrypi-node
target_label: job
logs:
configs:
- clients:
- basic_auth:
password: YOUR-GRAFANA-CLOUD-TOKEN
username: YOUR-GRAFANA-CLOUD-ID
url: https://YOUR-GRAFANA-CLOUD-ENDPOINT/loki/api/v1/push
name: integrations
positions:
filename: /tmp/positions.yaml
scrape_configs:
# Add here any snippet that belongs to the `logs.configs.scrape_configs` section.
# For a correct indentation, paste snippets copied from Grafana Cloud at the beginning of the line.
metrics:
configs:
- name: integrations
remote_write:
- basic_auth:
password: YOUR-GRAFANA-CLOUD-TOKEN
username: YOUR-GRAFANA-CLOUD-ID
url: https://YOUR-GRAFANA-CLOUD-ENDPOINT/api/prom/push
scrape_configs:
# Add here any snippet that belongs to the `metrics.configs.scrape_configs` section.
# For a correct indentation, paste snippets copied from Grafana Cloud at the beginning of the line.
- job_name: 'pihole'
static_configs:
- targets: ['localhost:9617']
global:
scrape_interval: 60s
wal_directory: /tmp/grafana-agent-wal
Google Fiber
Add Another Interface to your Pi
With the DNS setup as of January 2024, you can specify up to three IPv4 DNS servers, the minimum number of name servers you can set is two. You could run two piholes on two different machines… or you could just add another interface to your pi.
Find an IP that is not used. I use arp
to check to see what IPs are used and will run ping
against an IP I think is free, then run arp
again to see if it shows up in the list.
When you have an IP selected, create a file in /etc/network/interfaces.d
. If you have a fresh OS install, that directory is likely empty. I created a file called /etc/network/interfaces.d/eth01
and put the following in (sub out with the appropriate values for your network):
auto eth0:1
iface eth0:1 inet static
address 192.168.1.124
netmask 255.255.255.0
network 192.168.1.0
gateway 192.168.1.1
metric 10
THen bring up the interface:
$ ifup eth0:1
You can’t set/override IPv6 name servers
This is flat frustrating. Most reputable routers allow this to be set out of the box.
You will get the Google IPv6 name servers and you can’t override it. I personally prefer to use Cloudflare name servers, specifically the a 1.1.1.2 ones, which blocks malware. You will see some people prefer Cloudflare to reduce the amount of data Google can collect about you and your browsing habits.
I’ve contacted Google Fiber about this and asked them to do this. At this time, I’m not replacing the Google router or running the Raspberry Pi as a DHCP server. I might do this later. I will say, Google Fiber does provide great equipment by default if you do ever consider their services. With previous providers, my first step was to replace the stock modem and wireless router with my own.
Getting around this
- You can set devices to only use the pihole and remove the other name servers (not ideal)
- Run your own DHCP server, which means your own equipment. There’s not an option to turn off DHCP with Google Fiber.
Surprises
Apple Private Relay
I didn’t expect for this to get blocked. I just hadn’t really thought about it, I could see for some folks this being an issue. Luckily with some research and digging through the FTL project, being able to set FTLCONF_BLOCK_ICLOUD_PR
to false
in my docker-compose.yml
to resolve that issue to allow iPhones and other Apple devices to use private relay.
Some folks are worried about data going through Apple, I’m okay with it. When it comes to privacy, I do trust Cloudflare and Apple more than the other options available.
If you don’t disable the iCloud block, you’ll see popups that the private relay isn’t available on things like iPhones if you have that feature enabled.
Samsung TVs
I didn’t realize how much data my TV sends back to Samsung! It’s the top ad domain by specific domain.