Self-host Pi-hole
A DNS sinkhole that blocks ads and trackers for every device on your network — no client software needed. Runs on almost nothing and gives you a tidy dashboard of what your network is really talking to.
Key facts
Pick Pi-hole when you want the DNS sinkhole with the largest community behind it: a decade of block lists, guides and add-ons, an optional DHCP server, and a documented floor of 512 MB of RAM and 2 GB of disk — that RAM figure is upstream's. Since v6 the `pihole-FTL` binary is the whole server (DNS, API and web UI on 80/443), the container is the officially supported Docker route, and the licence is EUPL-1.2. It blocks at the DNS layer only, so it shares AdGuard Home's ceiling on YouTube and in-app ads.
What you need
- Any VPS with at least 512 MB of RAM
- A domain you control — most self-hosted setups need HTTPS in front of them
- Under an hour if you've used Docker before
Paid link — we earn a commission if you shop through it.
Install with Docker Compose
Save this as compose.yml and run docker compose up -d:
# Pi-hole — official compose quick start (github.com/pi-hole/docker-pi-hole)
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
- "443:443/tcp" # FTL generates a self-signed certificate
environment:
TZ: 'Etc/UTC'
FTLCONF_webserver_api_password: 'changeme'
# Required on Docker's default bridge network
FTLCONF_dns_listeningMode: 'ALL'
volumes:
- './etc-pihole:/etc/pihole'
cap_add:
- NET_ADMIN # only needed if Pi-hole is your DHCP server
- SYS_TIME # only needed if Pi-hole is your NTP client
- SYS_NICE # optional: more processing time
restart: unless-stopped
# On Ubuntu/Fedora, free port 53 first (docs.pi-hole.net/docker/tips-and-tricks → "Disable systemd-resolved port 53"):
# sudo sh -c 'mkdir -p /etc/systemd/resolved.conf.d && printf "[Resolve]\nDNSStubListener=no\n" | tee /etc/systemd/resolved.conf.d/no-stub.conf'
# sudo sh -c 'rm -f /etc/resolv.conf && ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf'
# sudo systemctl restart systemd-resolved
# docker compose up -d → http://SERVER_IP/adminWhat you take on
Pi-hole v6 changed how the container is configured; the docker docs and prerequisites cover the traps: