What is Pi-hole?

Pi-hole is a DNS filter that runs locally on your network. When a device looks up a domain, the request goes to Pi-hole first. If Pi-hole recognises the domain as an ad server or tracker, it returns 0.0.0.0. If it does not, it forwards the request to a real DNS resolver like 1.1.1.1 or 9.9.9.9.

Pi-hole v6 was released in January 2025 and is a complete rewrite. The new version ships with a redesigned web interface and no longer needs lighttpd as a separate service. The web server is now built into Pi-hole itself.

Pi-hole does not require a Raspberry Pi. It runs on any Linux machine. A Pi 3, 4, or 5 is ideal though: low power, silent, and more than capable of handling DNS for a home network.

What you need

SD cards die. Use an SSD.

Pi-hole's gravity.db is a SQLite database that constantly logs DNS queries and periodically updates blocklists. That is not occasional writes. It is steady I/O. SD cards are not built for that, and most die within 6-18 months under Pi-hole load. You usually find out at night when the whole household loses internet and nobody knows why.

A USB3 SSD adapter plus a 120 GB+ SSD is a one-time cost of around 25-35 EUR and solves the problem permanently. Samsung 870 Evo and Kingston A400 are both solid choices. For something more compact, a high-endurance USB stick works too. Samsung FIT Plus and the SanDisk Endurance series are well-tested options.

On Pi 4 and Pi 5 you can boot directly from USB SSD. Set the boot order to USB-first in raspi-config:

sudo raspi-config
# Advanced Options → Boot Order → USB Boot

Flash the OS image directly to the SSD with Raspberry Pi Imager and the Pi will ignore the SD card entirely.

Static IP for the Pi

Pi-hole needs a fixed IP address. Without one, the address changes on the next reboot and your network can no longer find the DNS server. The easiest approach is a DHCP reservation in your router: look up the Pi's MAC address and assign it the same IP every time.

Alternatively, set a static IP directly in Pi OS. Open /etc/dhcpcd.conf and add:

interface eth0
static ip_address=192.168.1.100/24
static routers=192.168.1.1
static domain_name_servers=127.0.0.1 1.1.1.1

Replace 192.168.1.100 with the IP you want and 192.168.1.1 with your router's address. Use wlan0 instead of eth0 for WiFi. Then reboot:

sudo reboot

Installation

The official installation method is a single command:

curl -sSL https://install.pi-hole.net | bash

The installer is interactive. It asks which upstream DNS provider to use (pick 1.1.1.1 or 9.9.9.9), which starting blocklist to include, and whether to install the web interface. Accept the defaults unless you have a specific reason to change them. At the end, the installer displays a password for the admin interface. Write it down.

Docker Compose (recommended)

A single docker run command works, but Docker Compose is much better: easier to update, restart, and extend with additional services. With Docker Compose on SSD you can run Pi-hole, Portainer, Heimdall, and AdGuard Home on the same Pi without conflicts.

Create a directory and a docker-compose.yml:

mkdir ~/pihole && cd ~/pihole
version: "3"
services:
  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    restart: unless-stopped
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80/tcp"
    environment:
      TZ: "Europe/Copenhagen"
      WEBPASSWORD: "change-this"
    volumes:
      - ./etc-pihole:/etc/pihole
      - ./etc-dnsmasq.d:/etc/dnsmasq.d
    cap_add:
      - NET_ADMIN

Replace change-this with a real password. Start Pi-hole:

docker compose up -d

Data is stored in ./etc-pihole and ./etc-dnsmasq.d relative to the directory you ran the command from. With Docker Compose on SSD it is straightforward to add other services to the same docker-compose.yml as you need them.

The admin interface and first login

Open a browser and go to:

http://[pi-ip]/admin

Log in with the password shown at the end of the installer. If you need to set a new one:

pihole -a -p

The dashboard shows live queries, blocking rate, and a Query Log where you can see exactly what has been blocked and what passed through.

Point your router at Pi-hole

For all devices on the network to automatically use Pi-hole, set the router's DNS to the Pi's IP. Log in to your router's admin page (typically 192.168.1.1 or 192.168.0.1), find the DHCP settings, and set the primary DNS to the Pi's IP.

Important: Always set a secondary DNS (e.g. 1.1.1.1) on your router. If the Pi reboots, your entire network loses DNS resolution without a fallback.

Example router settings:

Primary DNS:    192.168.1.100   (Pi's IP)
Secondary DNS:  1.1.1.1         (Cloudflare fallback)

After saving, restart devices on your network (or renew their DHCP lease) so they pick up the new DNS server.

Add better blocklists

Pi-hole's default list is the StevenBlack hosts file with around 120,000 domains. It is a solid starting point, but OISD Basic is better maintained, covers over 1 million domains, and is known for very low false positives.

Go to Settings, Adlists, and add:

https://big.oisd.nl/

Click Add, then run a gravity update so Pi-hole downloads and processes the new lists:

pihole -g

Gravity usually takes a couple of minutes. Afterwards the dashboard shows the updated blocked domain count.

Test that it works

From a terminal on any device on your network:

nslookup doubleclick.net [pi-ip]

If the response is 0.0.0.0 or :: (IPv6), Pi-hole is blocking correctly. If it returns a real IP, the domain is not on your current blocklist.

Check the Query Log in the Pi-hole dashboard as well. You can watch requests come in live and verify blocking is happening.

What Pi-hole does NOT do

Pi-hole blocks DNS queries, not HTTPS traffic. That means it cannot block ads that are embedded in application code rather than loaded from a separate ad domain. YouTube ads are the classic example: they are served from Google's own domains and bypass Pi-hole.

Apps with hardcoded DNS servers (for example, querying 8.8.8.8 directly) bypass Pi-hole entirely. It is not common, but it happens. You can intercept those with a DNS redirect rule on your router, but that is outside the scope of this guide.

Useful commands

# Check status
pihole status

# Update blocklists (gravity)
pihole -g

# Disable for 5 minutes
pihole disable 5m

# Re-enable
pihole enable

# Whitelist a domain
pihole -w example.com

# Tail the live query log
pihole -t

Keeping Pi-hole updated

Pi-hole updates itself with:

pihole -up

Run it manually every now and then, or schedule it as a cron job.

Quick reference: Admin UI: http://pi.hole/admin · DNS port: 53 · Disable temporarily: pihole disable 5m · Update blocklists: pihole -g · Whitelist domain: pihole -w example.com

Frequently asked questions

Does Pi-hole block ads in apps?

Yes, for apps that call a separate ad domain. Apps that serve ads from their own domain — YouTube and Spotify being the main examples — cannot be blocked via DNS. That is a fundamental limitation of how DNS-based blocking works.

Can Pi-hole slow down my internet connection?

No. Pi-hole caches responses locally and is typically faster than most ISP DNS servers. You will usually see faster DNS lookups, not slower ones. The only exception is a Pi already under heavy load from other tasks.

What is the best blocklist to start with?

Start with StevenBlack Unified (included by default). It is conservative, well-documented and has a low false-positive rate. Add OISD Full once you are comfortable with the setup. The most aggressive lists block too much and are frustrating to tune.

Sources