Il y a quelques mois, un soir, mon Grafana a remonté ~28 % de requêtes DNS bloquées sur mon réseau. Parmi les top domaines : telemetry.microsoft.com, analytics.google.com, api.segment.io. Des trucs que j’avais jamais explicitement configurés pour appeler vers l’extérieur. Depuis que Pi-hole tourne en LXC sur le MS-01, je vois tout ça, et je bloque tout ça.
Ce guide couvre l’installation de Pi-hole 5.18 en container LXC Debian 12, avec cloudflared en DNS over HTTPS et l’intégration avec le DHCP du ZenWifi XT8.
Ce que fait Pi-hole (et ce qu’il ne fait pas)
Pi-hole est un serveur DNS qui maintient des listes de domaines publicitaires et de trackers. Quand un appareil du réseau demande ads.doubleclick.net, Pi-hole répond 0.0.0.0 au lieu de transmettre la requête – le navigateur reçoit une adresse invalide et ne charge pas la pub.
Ça bloque efficacement : les pubs display sur les sites web, les trackers tiers, la télémétrie des applications desktop, les appareils IoT qui font du reporting maison vers des serveurs externes.
Ce que ça ne bloque pas : les pubs YouTube (injectées dans le stream vidéo, même domaine que le contenu), les pubs natives des applis mobiles (qui utilisent leurs propres CDN), les pubs in-app des jeux.
C’est du DNS. Ça ne touche pas au contenu, ça coupe les connexions à des domaines connus comme problématiques.
Créer le container LXC
Pi-hole est un service d’infrastructure – il doit être joignable par tous les VLANs du réseau sans règles de routage complexes. Je le place en VLAN 1 (management) avec l’IP 192.168.1.150, fixe. Si Pi-hole tombe, le réseau doit avoir un fallback DNS configuré (voir la section DHCP).
pct create 150 local:vztmpl/debian-12-standard12.7-1amd64.tar.zst
--hostname pihole
--memory 512
--cores 1
--net0 name=eth0,bridge=vmbr0,tag=1,ip=192.168.1.150/24,gw=192.168.1.1
--storage local-lvm
--rootfs local-lvm:4
--unprivileged 1
--onboot 1
pct start 150
pct enter 150
512 Mo de RAM, c’est confortable pour Pi-hole. En pratique, après quelques jours de fonctionnement, il consomme ~85 Mo.
Installer cloudflared (DNS over HTTPS)
Avant d’installer Pi-hole, je mets en place cloudflared comme proxy DNS local. L’idée : Pi-hole transmet les requêtes non-bloquées vers cloudflared, qui les envoie à Cloudflare 1.1.1.1 en HTTPS chiffré. Le FAI ne voit plus les requêtes DNS en clair.
# Dans le LXC
apt update && apt install -y curl
# Installer cloudflared
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
dpkg -i cloudflared-linux-amd64.deb
rm cloudflared-linux-amd64.deb
# Créer l'utilisateur dédié
useradd -s /usr/sbin/nologin -r -M cloudflared
Créer le fichier de configuration :
mkdir -p /etc/cloudflared
cat > /etc/cloudflared/config.yml << 'EOF'
proxy-dns: true
proxy-dns-port: 5053
proxy-dns-upstream:
- https://1.1.1.1/dns-query
- https://1.0.0.1/dns-query
EOF
chown cloudflared:cloudflared /etc/cloudflared/config.yml
Créer le service systemd :
cat > /etc/systemd/system/cloudflared.service << 'EOF'
[Unit]
Description=Cloudflare DNS over HTTPS proxy
After=network.target
Before=pihole-FTL.service
[Service]
Type=simple
User=cloudflared
ExecStart=/usr/bin/cloudflared --config /etc/cloudflared/config.yml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --now cloudflared
La ligne Before=pihole-FTL.service est critique - voir la section "Ce qui a coincé".
Vérifier que cloudflared répond :
dig @127.0.0.1 -p 5053 you.arewel.com
# Doit retourner une réponse valide
Installer Pi-hole
curl -sSL https://install.pi-hole.net | bash
curl | bash installe et exécute du code depuis Internet sans vérification préalable. C'est la méthode officielle Pi-hole. Pour les paranoïaques (moi y compris en prod), télécharger le script, le lire, puis l'exécuter. Pour un homelab, le risque est acceptable.
L'installeur interactif pose des questions. Réponses recommandées :
- Interface réseau :
eth0 - Upstream DNS provider : Custom →
127.0.0.1#5053(cloudflared) - Blocklist : cocher StevenBlack (activée par défaut, ~130 000 domaines)
- Interface web admin : oui
- Logging : oui (utile pour analyser ce qui est bloqué)
- Privacy level : 0 (tout loguer, c'est un homelab)
À la fin, l'installeur affiche le mot de passe de l'interface web. Le noter.
Changer ce mot de passe si nécessaire :
pihole -a -p
Ajouter des blocklists
L'interface web est accessible sur http://192.168.1.150/admin. Dans Adlists, j'ajoute :
https://big.oisd.nl
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/multi.txt
OISD Big : bien maintenu, très peu de faux positifs. C'est ma liste principale.
Hagezi Multi Normal : complément solide, couvre des domaines que OISD manque.
Je n'active pas les listes "Ultimate" ou "Pro" de Hagezi - elles génèrent des faux positifs sur certains services bancaires et e-commerce français.
Après ajout, mettre à jour les listes :
pihole -g
Résultat après 48h sur mon réseau : ~28% de requêtes bloquées, ~320 000 domaines dans la blocklist.
Intégration avec le ZenWifi XT8
Le ZenWifi sert de DHCP pour tout le réseau. Je lui dis de distribuer 192.168.1.150 comme serveur DNS primaire, et 192.168.1.1 (le routeur lui-même) comme secondaire.
Le secondaire est important : si le LXC Pi-hole tombe (redémarrage Proxmox, migration, maintenance), les appareils ont un fallback DNS. Ils contournent Pi-hole temporairement, mais ils restent connectés.
Dans l'interface de l'ASUS ZenWifi : LAN > DHCP Server > DNS Server 1 : 192.168.1.150 / DNS Server 2 : 192.168.1.1.
Forcer le renouvellement DHCP sur les appareils (ou attendre la fin du bail) pour que le changement prenne effet.
Ce qui a coincé
Après la première mise à jour de Pi-hole via pihole -up, cloudflared refusait de démarrer correctement. Pi-hole démarrait en premier, tentait de résoudre des dépendances réseau via cloudflared qui n'était pas encore là, échouait silencieusement, puis utilisait des serveurs DNS alternatifs (en clair). Le DoH n'était plus actif.
La cause : pihole-FTL.service avait une dépendance After=network.target mais pas de relation avec cloudflared.service. Au démarrage, les deux services partaient en même temps, et Pi-hole gagnait la course.
La correction était la ligne Before=pihole-FTL.service dans l'unit cloudflared. Elle force systemd à démarrer cloudflared avant pihole-FTL. C'est tout. Ça a pris 45 minutes à diagnostiquer parce que le service Pi-hole semblait fonctionner normalement - il bloquait des domaines - mais le DNS upstream était 8.8.8.8 en clair au lieu de 127.0.0.1#5053.
Vérifier la config DNS active de Pi-hole :
Série « Homelab Proxmox MS-01 » - Article 5/10