Skip to content

Latest commit

 

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 

Repository files navigation

RPi5-RecursiveDNS-Guide and security practices

This is a guide for setting up a Raspberry Pi with Pi-hole and Unbound, plus some basic security practices. This is the "hard-mode" with the official image. If you're looking for something easy to set up, look into DietPi

Note: This guide targets Pi-hole v6 and Raspberry Pi OS Bookworm. Pi-hole v6 removed lighttpd and PHP, the web interface is now built into pihole-FTL itself, and all settings live in /etc/pihole/pihole.toml.

1. Download rpi-imager

  • For the device choose RaspberryPi5
  • For the OS, go to "Raspberry Pi OS (other)" and choose Raspberry Pi OS Lite 64-bit.

Links:

2. Format SDCard with rpi-imager

  • Choose the device + OS + storage
  • Click the gear/settings icon and set up SSH login, username and password before writing

3. After formatting

  • Insert the SDCard in the Pi, connect the Pi with an ethernet cable and power it on
  • Open your router page and find the Pi in the connected devices / DHCP client list
  • Note its MAC address and assign it a static IP (for example 192.168.1.5)

If you have a monitor and keyboard attached instead, you can find the MAC with ip link show

4. Login with SSH

ssh username@staticIPhere

5. Update system and reboot

sudo apt update && sudo apt upgrade -y && sudo reboot

6. Enable asking for sudo password

  • Edit the file with visudo, which checks the syntax before saving:
sudo visudo -f /etc/sudoers.d/010_pi-nopasswd
  • Change yourusername ALL=(ALL) NOPASSWD: ALL to yourusername ALL=(ALL) PASSWD: ALL
  • Mind the spaces and don't change anything else.

Don't edit this file with plain nano. A typo in a sudoers file can lock you out of sudo completely, which is painful on a headless machine. visudo refuses to save a broken file.

7. Change default openssh port for increased security

  • Edit the following file with:
sudo nano /etc/ssh/sshd_config
  • Uncomment Port 22 and change it to your liking

8. Reboot to apply your changes

sudo reboot

9. Install uncomplicated firewall

sudo apt install ufw -y

10. Add the SSH port you chose earlier to UFW

sudo ufw allow SSHPort/tcp

Do this before enabling the firewall, or you'll lock yourself out.

11. Disallow six or more SSH connections within 30 seconds

sudo ufw limit SSHPort/tcp

12. Extra commands that might be useful later

  • Check ports being currently used with:
sudo ss -tupln
  • Check which service is using which port number with:
sudo lsof -i :PORT

13. Make the RPi unpingable

sudo nano /etc/ufw/before.rules
  • Under # ok icmp codes for INPUT add a new line:
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP

14. Restart RPi5 and SSH into it using the newly defined port

sudo reboot
ssh username@RPiIPHere -p SSHPortHere

15. Remove the motd (Optional)

  • Clear it once with:
sudo truncate -s 0 /etc/motd
  • If a system upgrade brings it back, add this line to ~/.bashrc instead:
sudo truncate -s 0 /etc/motd 2>/dev/null
  • Reload bashrc with:
source ~/.bashrc

Some older guides suggest adding export TERM=xterm to .bashrc for terminals like kitty. Avoid it, it tells every program your terminal is a basic xterm and breaks 256-colour support. If kitty gives you trouble over SSH, use kitty +kitten ssh from your client instead.

16. If there are error messages like "expected kernel"

  • Some Debian 12 (bookworm) packages complain about the architecture
  • The processor microcode module only supports AMD and Intel, not aarch64 (64-bit ARM)
  • You can "fix" this by removing the needrestart package with:
sudo apt purge needrestart -y
  • Or you can change the following value:
sudo sed -i 's/#\$nrconf{ucodehints} = 0;/$nrconf{ucodehints} = 0;/' /etc/needrestart/needrestart.conf

17. Disable onboard Wifi if you're using ethernet (Optional)

sudo nano /boot/firmware/config.txt
  • Add the following line at the end of the file:
dtoverlay=disable-wifi

On Bookworm this file lives in /boot/firmware/, not /boot/. Editing /boot/config.txt on Bookworm does nothing.

  • Reboot for it to take effect

18. Install Pi-Hole

  • Install Pi-Hole with (choose Google or Cloudflare DNS for now, we replace it with Unbound later):
curl -sSL https://install.pi-hole.net | bash
  • Set the web interface password with:
pihole setpassword

By default Pi-hole v6 binds to port 80 (and 443 for HTTPS). If either is already taken during install, it falls back to 8080. See step 24 if you want to move it.

19. Install Unbound (recursive DNS)

  • Install Unbound with:
sudo apt install unbound -y
  • Copy the config found here
  • Paste it into:
sudo nano /etc/unbound/unbound.conf.d/pi-hole.conf
  • Restart Unbound:
sudo systemctl restart unbound

20. Disable the following Unbound service because it can cause issues in Debian

sudo systemctl disable --now unbound-resolvconf.service
sudo sed -Ei 's/^unbound_conf=/#unbound_conf=/' /etc/resolvconf.conf
sudo rm -f /etc/unbound/unbound.conf.d/resolvconf_resolvers.conf

21. If you want to make PiHole your DHCP server (Optional)

  • Open the Pi-hole interface -> Settings -> DHCP
  • Enable "DHCP server enabled"
  • Choose an IP range, for example 192.168.1.21 to 192.168.1.151
  • For Router (gateway) IP address put your router IP, e.g. 192.168.1.1
  • Open your router page
  • Turn off the DHCP server in your router, and set primary and secondary DNS to your Pi (don't forget to save)

22. Point Pi-hole at Unbound

  • List your connections on the Pi with:
nmcli connection show
  • Edit your ethernet connection (Wired connection 1 in my case):
sudo nmcli connection edit "Wired connection 1"
  • Now set the parameters according to your connection:
set ipv4.method manual
set ipv4.addresses RPiIP/your_subnet
set ipv4.gateway RouterIP
set ipv4.dns 127.0.0.1
save persistent
quit
  • To revert any changes:
sudo nmcli connection edit "Wired connection 1"
reset
save persistent
quit
  • Go to the Pi-hole interface -> Settings -> DNS
  • Untick all upstream DNS servers, tick Custom 1 (IPv4) and enter 127.0.0.1#5335

23. Check if unbound is working

  • Shut down your router and your Raspberry Pi
  • Turn your router on first
  • Turn on the Pi
  • Check Unbound answers with:
dig pi-hole.net @127.0.0.1 -p 5335
  • You should get a NOERROR status and an answer section. The first query may be slow while Unbound builds its cache.

24. Change the PiHole web interface port (Optional)

  • Check the current port with:
pihole-FTL --config webserver.port
  • Change it with:
sudo pihole-FTL --config webserver.port 8080
  • Or edit /etc/pihole/pihole.toml directly and restart FTL:
sudo systemctl restart pihole-FTL

If you plan to run a reverse proxy such as Nginx Proxy Manager on the same Pi, move Pi-hole off ports 80 and 443 first. Pi-hole only auto-falls back to 8080 if a conflict exists at install time, installing a proxy afterwards will collide, and Let's Encrypt HTTP-01 challenges need port 80 free.

25. Enable ports used by PiHole and Unbound in UFW

sudo ufw allow 53/tcp   # DNS resolution
sudo ufw allow 53/udp   # DNS resolution
sudo ufw allow 67/udp   # only needed if you use Pi-hole as your DHCP server
sudo ufw allow 80/tcp   # Pi-hole web interface (HTTP)
sudo ufw allow 443/tcp  # HTTPS — Pi-hole native HTTPS, or a reverse proxy such as Nginx Proxy Manager
  • If you moved the web interface to a custom port, allow that instead of 80:
sudo ufw allow YOURPORT/tcp
  • Enable the firewall with:
sudo ufw enable

26. Install and configure fastfetch (Optional)

sudo apt install fastfetch -y
  • Generate a config you can edit:
fastfetch --gen-config
  • The config lands in ~/.config/fastfetch/config.jsonc

27. Add fastfetch to bashrc (Optional)

  • Open .bashrc:
nano ~/.bashrc
  • Add fastfetch at the end of the file, save and exit
  • Reload bashrc with:
source ~/.bashrc

28. Install tldr, nala and neovim (Optional)

sudo apt install nala tldr neovim -y

29. Install Docker and Docker Compose

The docker package in Debian repos is not Docker, use the official install script, which also installs the Compose v2 plugin:

curl -fsSL https://get.docker.com | sh
  • Add your current user to the docker group:
sudo usermod -aG docker "$USER"
  • Enable docker autostart:
sudo systemctl enable docker
  • Reboot so that your user is actually in the docker group:
sudo reboot
  • Check both are working:
docker --version
docker compose version

30. Install Portainer-CE (Optional)

  • Create the directory and cd into it (note: no quotes around ~):
mkdir -p ~/Docker/portainer-ce && cd ~/Docker/portainer-ce
  • Create the following file:
nano docker-compose.yml
  • Paste the following inside (change PORT to a port you want), exit and save:
services:
  portainer-ce:
    image: portainer/portainer-ce
    container_name: portainer
    command: -H unix:///var/run/docker.sock
    ports:
      - 'PORT:9000'
    volumes:
      - 'portainer_data:/data'
      - '/var/run/docker.sock:/var/run/docker.sock'
    restart: always

volumes:
  portainer_data:
  • Start it with:
docker compose up -d
  • Allow the port through the firewall:
sudo ufw allow PORT/tcp
  • Go to your browser and open http://RPiIP:PORTAINERPORT
  • Choose a name for your user and a password

About

Guide for setting up RaspeberryPi5 for PiHole

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors