This guide walks you through setting up the Pi-hole Display Controller in three phases:
- Foundation - Ensure your Raspberry Pi and Pi-hole are working
- Hardware - Install and configure the PiTFT display
- Application - Install the display controller software
Before adding the display, ensure you have a working foundation.
You need a Raspberry Pi with Raspberry Pi OS installed and running:
- Hardware: Raspberry Pi 3B, 3B+, or 4 (RPi 5 not supported due to display driver compatibility)
- Operating System: Raspberry Pi OS Lite (recommended) or Desktop
- Network: Connected to your network with SSH access (recommended for setup)
- Status: Successfully booted and accessible
Need to install Raspberry Pi OS?
- Download: https://www.raspberrypi.org/software/operating-systems/
- Installation guide: https://www.raspberrypi.org/documentation/installation/
- Tested on Raspberry Pi OS 12 (Bookworm)
Pi-hole must be installed and actively working as your network's DNS server before adding this display:
- ✅ Pi-hole is blocking ads and tracking queries on your network
- ✅ Admin interface is accessible at
http://your-pi-ip/admin - ✅ Dashboard shows statistics and blocked queries
Don't have Pi-hole yet?
- Official installation: https://docs.pi-hole.net/main/basic-install/
- Quick install:
curl -sSL https://install.pi-hole.net | bash - Complete the setup wizard and verify it's working before continuing
Update your system before installing display hardware:
sudo apt update
sudo apt upgrade -y
sudo rebootBefore continuing to Phase 2, verify:
- Your Raspberry Pi boots successfully
- You can SSH into your Pi or access the console
- Pi-hole web interface is accessible
- Pi-hole is actively blocking ads on your network
All set? Continue to Phase 2: Hardware Setup
Now that Pi-hole is running, add the physical display hardware.
You'll need the following display components:
-
Adafruit PiTFT Plus 320x240 2.8" TFT
- Product link: https://www.adafruit.com/product/2423
-
Faceplate and Buttons Pack for 2.8" PiTFTs
- Product link: https://www.adafruit.com/product/2807
-
Case (optional, but recommended)
- Example: Pi Model B+ / Pi 2 / Pi 3 Case for 2.8" PiTFT
- Product link: https://www.adafruit.com/product/3062
-
Power off your Raspberry Pi:
sudo shutdown -h now
Wait for the Pi to fully power down before proceeding.
-
Attach the PiTFT display:
- Connect the PiTFT to the 40-pin GPIO connector on your Raspberry Pi
- Press firmly but gently to ensure all pins are seated
- Install the faceplate and buttons (if using)
- Attach the button pack to the side of the display
- Install the faceplate over the display
The PiTFT display requires special drivers from Adafruit.
(Note: Adafruit has not updated their install flow to work with latest versions of Raspberry Pi OS, so the process below is my hack to make it work)
-
As root, Download Adafruit installer scripts, and create a python virtual environment:
# become root sudo su - git clone https://github.com/adafruit/Raspberry-Pi-Installer-Scripts.git cd Raspberry-Pi-Installer-Scripts python -v venv venv source venv/bin/activate
-
Hack Adafruit script:
- Edit the file
adafruit-pitft.py- In this file, change the line:
username = os.environ["SUDO_USER"]
- To:
username = os.environ.get('USER')
- In this file, change the line:
- Then, while still root, and with the virtual environment active, from the step above, and edits in place to the
adafruit-pitft.pyfile, run the command:pip3 install --upgrade adafruit-python-shell click==7.0
-
Run the PiTFT installer:
For the PiTFT 2.8" Capacitive display:
-
While still in the root virtual environment session from previous steps:
python3 adafruit-pitft.py --display=28c --rotation=90 --install-type=console
For other display types, see: https://learn.adafruit.com/adafruit-pitft-28-inch-resistive-touchscreen-display-raspberry-pi/easy-install-2
- Reboot when prompted:
sudo reboot
After reboot, the PiTFT display should show the console. You should see the normal Raspberry Pi boot messages on the small screen.
Now optimize the console for the small display.
-
Configure console font mapping:
Edit
/boot/cmdline.txt:sudo nano /boot/cmdline.txt
Add to the end of the line (after "rootwait"):
fbcon=map:10 fbcon=font:VGA8x8The complete line should look similar to:
console=serial0,115200 console=tty1 root=PARTUUID=XXXXXXXX-XX rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait fbcon=map:10 fbcon=font:VGA8x8Note: Don't change your existing PARTUUID value
Save and exit (Ctrl+X, Y, Enter)
-
Improve console font for readability:
Run the console setup utility:
sudo dpkg-reconfigure console-setup
Select these options:
- Encoding: UTF-8
- Character set: Guess optimal character set
- Font: Terminus
- Font size: 6x12 (framebuffer only)
-
Reboot to apply changes:
sudo reboot
After reboot, the console should be more readable on the small display.
⚠️ CRITICAL REQUIREMENT: The display controller requires console auto-login to start automatically on boot. Without this, the application will not start.
Configure auto-login using raspi-config:
sudo raspi-configNavigate through these menus:
- Select "1 System Options"
- Select "S5 Boot / Auto Login"
- Select "B2 Console Autologin" (Text console, automatically logged in as 'pi' user)
- Select Finish
When prompted to reboot, select "No" (we'll reboot after Phase 3)
Verify auto-login is configured:
cat /etc/systemd/system/[email protected]/autologin.confYou should see a line containing --autologin pi
Before continuing to Phase 3, verify:
- PiTFT display shows the console
- Console font is readable on the small screen
- Auto-login is enabled (verified with the cat command above)
All set? Continue to Phase 3: Application Installation
Now install the display controller software that will run PADD and handle button inputs.
-
Install required system packages:
sudo apt install python3-pip git tmux pigpio
-
Install yq (YAML configuration parser):
For most Raspberry Pi installations (32-bit OS):
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm -O /usr/bin/yq sudo chmod +x /usr/bin/yq
If you're using 64-bit Raspberry Pi OS:
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_arm64 -O /usr/bin/yq sudo chmod +x /usr/bin/yq
Clone this repository with the PADD submodule:
cd ~
git clone --recurse-submodules https://github.com/andersix/PhDC.gitIf you already cloned without submodules, initialize them:
cd ~/PhDC
git submodule update --init --recursiveAbout PADD: This project includes PADD (Pi-hole Admin Display Dashboard) as a git submodule. PADD is developed and maintained by the Pi-hole project at https://github.com/pi-hole/PADD. It's configured by default in config/config.yaml to run from the PADD/ subdirectory.
Install the required Python packages:
cd ~/PhDC
sudo pip3 install -r requirements.txtThis installs: gpiozero, PyYAML, pigpio, and setuptools.
PADD requires permission to access Pi-hole data. Add your user to the pihole group:
sudo usermod -G pihole piFor more authentication options, see: https://github.com/pi-hole/PADD?tab=readme-ov-file#authentication
Enable Remote GPIO and start the pigpio daemon:
-
Enable Remote GPIO:
sudo raspi-config
- Select "3 Interface Options"
- Select "P8 Remote GPIO"
- Select "Yes" to enable
- Select Finish
-
Enable and start pigpiod service:
sudo systemctl enable pigpiod sudo systemctl start pigpiod -
Verify it's running:
sudo systemctl status pigpiod
You should see "Active: active (running)"
Note: The pigpiod service only listens locally by default (secure).
The display controller needs to start automatically when the Pi boots.
Edit ~/.bashrc and add this code at the very top of the file:
nano ~/.bashrcAdd these lines at the top:
# Run PiHole display controller
if [ "$TERM" == "linux" ] ; then
if [ -f /home/pi/PhDC/scripts/start_display.sh ]; then
/home/pi/PhDC/scripts/start_display.sh
return 0
fi
fiSave and exit (Ctrl+X, Y, Enter)
What this does:
- Automatically runs when you log in on the console (not SSH)
- Creates a tmux session with two windows
- Starts PADD in the first window (displays Pi-hole statistics)
- Starts the button controller in the second window
- Logs startup activity to
log/startup.log
Reboot your Pi to start the display controller:
sudo rebootWhat to expect:
- The PiTFT display will show boot messages
- After ~30 seconds, PADD will appear showing Pi-hole statistics
- Buttons will be active and ready to use
Verify everything is working:
- PiTFT display shows PADD with Pi-hole statistics
- Button 1 dims the display when pressed
- Holding Button 1 for 2 seconds shows the Pi-hole Update Menu
Success! Your Pi-hole display controller is now running.
If you encounter any issues, see the Troubleshooting section below.
Most users won't need to change anything, but all settings can be customized if needed.
All settings are in: ~/PhDC/config/config.yaml
Common settings you might want to adjust:
Brightness Levels:
- Default: 8 levels from 100% down to 0% (off)
- Edit the
display.backlight.brightness_levelsarray - Values are 0.0-1.0 (0.0 = off, 1.0 = full brightness)
- Gamma correction:
display.backlight.gamma(default: 1.8 for perceptual linearity)
Timing:
- Menu timeout:
timing.confirmation_timeout(default: 30 seconds) - Feedback delay:
timing.feedback_delay(default: 3 seconds)
Paths:
- Only change if you installed PADD or this application in a non-default location
- Update
paths.padd_dirandpaths.padd_scriptif using custom PADD location
After making changes, restart the application (see below).
If you make configuration changes or want to restart the application:
-
Kill the existing tmux session:
tmux kill-session -t display
-
Restart the application:
/home/pi/PhDC/scripts/start_display.sh
The display should show PADD within a few seconds.
Alternative - Reboot the Pi:
Using command line:
sudo rebootOr using the buttons:
- Hold Button 2 for 2 seconds (System Control Menu)
- Press Button 3 (Restart System)
Check if the tmux session is running:
tmux list-sessionsYou should see a session named "display". If not:
-
Check startup logs:
cat ~/PhDC/log/startup.log -
Verify PADD submodule is initialized:
ls ~/PhDC/PADD/padd.shIf file doesn't exist, initialize submodules:
cd ~/PhDC git submodule update --init --recursive
-
Manually start the session:
/home/pi/PhDC/scripts/start_display.sh
-
Check if Python process is running:
pgrep -f "main.py"Should return a process ID. If not, the controller isn't running.
-
Verify pigpiod is running:
sudo systemctl status pigpiod
Should show "Active: active (running)". If not:
sudo systemctl enable pigpiod sudo systemctl start pigpiod -
Check application logs for errors:
tail -f ~/PhDC/log/controller.log
-
Verify auto-login is enabled:
cat /etc/systemd/system/[email protected]/autologin.conf
Should contain
--autologin pi -
Check .bashrc has startup code:
head -10 ~/.bashrcThe startup code should be at the very top of the file.
-
Verify file paths are correct:
ls -la /home/pi/PhDC/scripts/start_display.sh
Shows tmux session creation and initialization:
cat ~/PhDC/log/startup.logShows runtime activity, button presses, and errors:
tail -f ~/PhDC/log/controller.logAttach to the tmux session to see what's happening:
tmux attach -t displayTmux keyboard shortcuts:
Ctrl+bthenw- List and switch between windowsCtrl+bthen0- Switch to PADD windowCtrl+bthen1- Switch to control windowCtrl+bthend- Detach without stopping the session
When there are updates to this project:
cd ~/PhDC
git pull
sudo rebootThe reboot will automatically start the updated application via the .bashrc startup script.
Note: PADD updates are handled via Button 4 in the Pi-hole Update Menu (hold Button 1 for 2 seconds, then press Button 4). The button update runs git pull in the PADD submodule directory to fetch the latest version from the Pi-hole project repository.

