Pi-hole im Container – Werbefilter für das ganze Heimnetz
Werbeblocker im Browser helfen genau einem Browser. Der Fernseher, das Tablet der Kinder, die Wetter-App auf dem Handy – die filtert niemand. Pi-hole setzt eine Ebene tiefer an: Es beantwortet die Namensauflösung für das gesamte Netz und lässt Anfragen an bekannte Werbe- und Tracking-Domains ins Leere laufen. Ein Gerät, ein Filter, alle profitieren.
Das läuft in einem Container auf der Proxmox-Installation aus dem vorigen Beitrag. Ein Container statt eines Raspberry Pi, so wie dort beschrieben.
Die Adressen hier sind der Standard der FritzBox: Der Router ist die .1, per
DHCP verteilt er ab Werk erst ab .20. Alles darunter ist frei für feste
Adressen – Pi-hole bekommt deshalb die .19, direkt unterhalb des Bereichs.
Bei anderen Routern lauten die ersten drei Zahlen oft 192.168.0 oder
192.168.1, dann überall entsprechend ersetzen.
Wie das im Netz aussieht
Der entscheidende Punkt: Die FritzBox verteilt weiterhin die Adressen, sagt den Geräten dabei aber, dass Pi-hole für DNS zuständig ist. Die Geräte fragen danach direkt beim Pi-hole an.
Warum Debian und nicht Ubuntu
Pi-hole braucht Port 53 für sich. Ubuntu belegt den mit systemd-resolved, das
erst abgeschaltet werden will – Debian 13 bringt das Problem nicht mit. Sonst
sind beide gleichermaßen geeignet.
Schritt 1 – Template holen
Eine Vorlage ist das fertige Grundsystem, aus dem der Container entsteht. In der Proxmox-Oberfläche:
- Links den Knoten
pveaufklappen und auf local (pve) klicken - Im Menü daneben CT Templates
- Oben auf Templates – es öffnet sich die Liste der verfügbaren Vorlagen
- In der Spalte Package
debian-13-standardsuchen, Zeile markieren, Download
Das Fenster zeigt den Fortschritt und darf danach geschlossen werden. Ist die Liste leer oder veraltet, hilft Refresh darüber.
Dasselbe in der Shell
pveam update
pveam list local
Die zweite Zeile zeigt die vorhandenen Vorlagen mit genau dem Namen, den der nächste Befehl braucht. Fehlt Debian 13 noch:
pveam available --section system | grep debian-13
pveam download local debian-13-standard_13.1-2_amd64.tar.zst
Die Versionsnummer im Dateinamen ändert sich – immer die aus der Ausgabe nehmen, nicht die hier abgetippte.
Schritt 2 – Container anlegen
Oben rechts Create CT. Der Assistent hat sieben Reiter, weiter geht es jeweils mit Next:
| Reiter | Eingabe |
|---|---|
| General | CT ID 110, Hostname pihole, Passwort setzen |
| Template | Storage local, Template die eben geladene Vorlage |
| Disks | Storage local-lvm, Disk size 8 GiB |
| CPU | Cores 2 |
| Memory | Memory 2048 MiB, Swap 512 MiB |
| Network | siehe unten |
| DNS | DNS servers 192.168.178.1 |
Im Reiter General bleibt der Haken bei Unprivileged container gesetzt und Nesting ebenfalls – das ist die Voreinstellung und für Debian 13 richtig.
Der Reiter Network ist der, auf den es ankommt:
| Feld | Wert |
|---|---|
| Bridge | vmbr0 |
| IPv4 | Static, nicht DHCP |
| IPv4/CIDR | 192.168.178.19/24 |
| Gateway (IPv4) | 192.168.178.1 |
Nach Finish fehlt noch ein Handgriff, den der Assistent nicht anbietet: Container links anklicken, Options → Start at boot auf Yes. Ohne das steht nach einem Neustart des Hosts das halbe Netz ohne Namensauflösung da.
Dann Start, und über Console anmelden als root.
Dasselbe in der Shell
110 ist die Container-Nummer, frei wählbar:
pct create 110 local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst \
--hostname pihole \
--cores 2 --memory 2048 --swap 512 \
--rootfs local-lvm:8 \
--net0 name=eth0,bridge=vmbr0,ip=192.168.178.19/24,gw=192.168.178.1 \
--nameserver 192.168.178.1 \
--features nesting=1 \
--onboot 1 --unprivileged 1 \
--password
Starten und hineinwechseln:
pct start 110
pct enter 110
Vier Angaben sind dabei keine Geschmacksfrage:
- Feste IP, kein DHCP. Ein DNS-Server, dessen Adresse wandert, ist keiner.
- Start at boot, sonst hängt das Netz nach jedem Host-Neustart.
- DNS server ist nur der Start-DNS für die Installation. Pi-hole schreibt sich das später selbst um.
- Unprivileged ist richtig, solange die FritzBox DHCP macht. Nur wenn Pi-hole auch DHCP übernehmen soll, bräuchte es mehr Rechte.
Ab hier sind alle Befehle im Container, also in dessen Console.
Schritt 3 – System vorbereiten
apt update && apt full-upgrade -y
apt install -y curl ca-certificates sudo
Schritt 4 – Pi-hole installieren
curl -sSL https://install.pi-hole.net | bash
Im Installer vier Antworten, die zählen:
| Frage | Antwort |
|---|---|
| Upstream DNS | Quad9 oder Cloudflare |
| Interface | eth0 |
| Query Logging | an |
| Privacy Level | 0 – Show everything |
Nicht die FritzBox als Upstream eintragen – das gibt eine Schleife, sobald die FritzBox ihrerseits auf Pi-hole zeigt.
Danach das Passwort für die Oberfläche setzen:
pihole setpassword
Die Oberfläche liegt unter http://192.168.178.19/admin.
Schritt 5 – Erst testen, dann umstellen
Von einem anderen Rechner aus, bevor die FritzBox angefasst wird:
nslookup heise.de 192.168.178.19
nslookup doubleclick.net 192.168.178.19
Der erste Name muss eine richtige Adresse liefern, der zweite 0.0.0.0. Wenn
das nicht stimmt, ist die FritzBox der falsche Ort zum Suchen.
Schritt 6 – Automatische Updates
Für das Betriebssystem übernimmt das Debian selbst:
apt install -y unattended-upgrades apt-listchanges
dpkg-reconfigure -plow unattended-upgrades
Dann in /etc/apt/apt.conf.d/50unattended-upgrades die beiden Zeilen
aktivieren – der Neustart eines Containers dauert zwei Sekunden:
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:30";
Pi-hole selbst hat keinen offiziellen Auto-Updater. Mit Proxmox-Backups im Rücken ist ein Cronjob vertretbar:
cat > /etc/cron.d/pihole-selfupdate <<'EOF'
30 4 * * 6 root /usr/local/bin/pihole -up >> /var/log/pihole-update.log 2>&1
EOF
Samstags um 4:30, also nach dem Fenster für die Systemupdates. Geht ein Update schief, wird das Proxmox-Backup zurückgespielt – mehr Sicherung braucht es nicht.
Die Blocklisten aktualisieren sich bereits von allein: Der Installer legt
/etc/cron.d/pihole an, das wöchentlich pihole -g ausführt.
Schritt 7 – FritzBox umstellen
Heimnetz → Netzwerk → Netzwerkeinstellungen → IPv4-Einstellungen, dort das
Feld Lokaler DNS-Server auf 192.168.178.19 setzen.
Damit bekommt jedes Gerät Pi-hole als DNS, die FritzBox selbst behält ihren eigenen Weg nach draußen. Das ist wichtig: Fällt Pi-hole aus, kommt man über die FritzBox-Oberfläche weiterhin gegensteuern.
Der umgekehrte Weg – Pi-hole unter Internet → Zugangsdaten → DNS-Server als Upstream der FritzBox – funktioniert zwar auch, kostet aber jede Client-Statistik:
Noch prüfen, dass 192.168.178.19 außerhalb des DHCP-Bereichs liegt oder fest
zugeordnet ist. Die Geräte übernehmen die neue Adresse erst mit der nächsten
DHCP-Erneuerung – WLAN einmal aus und an, oder ipconfig /renew.
IPv6 nicht vergessen
Das ist die häufigste Fehlerquelle. Die FritzBox meldet sich per Router Advertisement auch als IPv6-DNS-Server, und Windows wie Android bevorzugen IPv6. Ergebnis: Pi-hole wird umgangen, und im Dashboard kommt fast nichts an.
Unter Heimnetz → Netzwerk → Netzwerkeinstellungen → IPv6-Einstellungen die Option „DNSv6-Server auch über Router Advertisement bekanntgeben (RFC 5006)” abschalten und auch über DHCPv6 keinen DNS-Server ankündigen lassen. Dann läuft alles über IPv4 zum Pi-hole. Die Bezeichnungen wandern je nach FritzOS-Version etwas, sinngemäß steht es aber dort.
Lokale Namen behalten
Damit nas.fritz.box weiter funktioniert, im Pi-hole unter Settings → DNS →
Conditional Forwarding eintragen:
| Feld | Wert |
|---|---|
| Local network | 192.168.178.0/24 |
| IP of router | 192.168.178.1 |
| Local domain | fritz.box |
Welche Listen
Pi-hole v6 versteht Hosts-Format und Adblock-Syntax. Weniger ist mehr: Fünf sich überlappende Listen blocken kaum zusätzlich, kosten aber RAM und produzieren Fehlalarme.
Die Basis reicht für die meisten Haushalte:
| Liste | URL |
|---|---|
| HaGeZi Multi PRO | …/hagezi/dns-blocklists/main/adblock/pro.txt |
| HaGeZi Threat Intelligence (medium) | …/hagezi/dns-blocklists/main/adblock/tif.medium.txt |
Von Threat Intelligence die medium-Variante: Sie enthält nur die wichtigsten Quellen. Die volle Liste ist für einen Haushalt überdimensioniert und fällt häufiger fälschlich zu.
Sinnvolle Ergänzungen, wenn mehr sein darf:
| Liste | Zweck |
|---|---|
HaGeZi Badware Hoster (hoster.txt) |
Hoster, die fast nur Schadcode ausliefern |
HaGeZi Popup Ads (popupads.txt) |
Popup- und Weiterleitungs-Domains |
| Phishing Army | Phishing |
| URLhaus (abuse.ch) | aktive Malware-Verteilung |
Vollständig zum Kopieren:
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/pro.txt
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/tif.medium.txt
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/hoster.txt
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/popupads.txt
https://phishing.army/download/phishing_army_blocklist_extended.txt
https://urlhaus.abuse.ch/downloads/hostfile/
Dazu gehört zwingend eine Allowlist, sonst brechen Weiterleitungen in Shops und Login-Abläufe weg. Unter Lists mit Typ Allow eintragen:
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/whitelist-referral.txt
HaGeZi Pro ersetzt die mitgelieferte Standardliste praktisch vollständig; sie kann danach deaktiviert werden. Wovon ich abraten würde: die Ultimate-Variante und die Native-Tracker-Listen für Apple, Amazon oder Windows. Die blocken konsequent, aber man sucht danach regelmäßig, warum irgendein Gerät klemmt.
Nach dem Hinzufügen Tools → Update Gravity oder pihole -g.
Der Arbeitsablauf, den man sich merken sollte: Wenn etwas nicht geht, Query Log öffnen, Domain suchen, per Knopfdruck erlauben.
Ein Tag im Betrieb
So sieht es bei mir aus, einen Tag nach der Einrichtung mit genau den oben genannten Listen:
27.296 Anfragen in 24 Stunden, 12.362 davon geblockt – 45,3 Prozent. Das ist mehr, als ich erwartet hatte, und zeigt zugleich, dass die Quote wenig über die Qualität der Listen sagt: Sie hängt vor allem daran, welche Geräte im Netz hängen. Ein Smart-TV und ein paar Handys mit Apps treiben sie nach oben, während ein reiner Arbeitsrechner kaum auffällt.
Die Spitze gegen 22 Uhr ist übrigens kein Mensch, sondern Geräte, die nachts aufräumen und dabei ihre Telemetrie loswerden wollen.
Drei Stolpersteine
- Pi-hole nicht als DNS des Proxmox-Hosts eintragen. Sonst startet der Host, braucht Namensauflösung – und der Container, der sie liefern soll, läuft noch nicht. Beim Host die FritzBox oder einen externen Resolver eintragen. Dasselbe gilt für ein NAS.
- Geräte mit eingebautem DNS umgehen den Filter. Chromecasts und manche
Fernseher fragen fest
8.8.8.8, Browser mit DNS-over-HTTPS ebenfalls. Bei Android unter Privates DNS auf „Aus” oder „Automatisch” stellen. - iOS merkt sich die alte Einstellung hartnäckig. Wenn das iPhone im Dashboard nicht auftaucht: einmal neu starten. Das räumt Cache und alte Konfiguration auf.
Wie es weitergeht
Der Container läuft, die erste Woche mit dem Dashboard ist erfahrungsgemäß die interessanteste – man sieht zum ersten Mal, was die Geräte im Hintergrund so alles fragen.
Als Nächstes in dieser Reihe: Paperless für den Papierkram und ein Minecraft-Server für die Familie, beide wieder als Container auf derselben Installation.
Handbuch: docs.pi-hole.net · Listen: hagezi/dns-blocklists