Pi-hole позиціонує себе як “Network-wide Ad Blocking”, тобто рішення для блокування реклами на рівні мережі (більшість таких рішень є розширеннями браузера і працюють саме на рівні браузера).
Принцип роботи Pi-hole досить простий - він виступає DNS-сервером в локальній мережі, який отримує запити від клієнтів і обробляє їх. Якщо цей запит є в Gravity базі даних (внутрішня база, де зберігається список записів на основі списків блокування, і оновлюється відповідно), то Pi-hole відповідає, що такої адреси не знайдено (відповідно неможливо отримати контент - рекламу), якщо ж в базі він відсутній, то імʼя транслюється за допомогою DNS-серверів вищого рівня (Google за замовчанням) і результат повертається локальному клієнту. Таким чином, при підключенні пристрою до домашньої мережі непотрібні додаткові налаштування, встановлення додатків або розширень браузера.
Звісно, Pi-hole не блокує 100% реклами, але суттєво зменшує її кількість (вірогідно 60-80%), що відчутно при користуванні. У моєму випадку блокування складає близько 20% всіх DNS-запитів.

Підвищення надійності (failover)
Як я писав раніше, у вступній статті Хроніки домашньої лабораторії, у мене є 2 сервери і мені б хотілося, щоб при перезавантаженні сервера, де працює сервіс Pi-hole, клієнти не перемикались на загальнодоступні (типу Google, Cloudflare і т.д.), при використанні яких, відразу повертається увесь рекламний контент…
Найпростіше рішення - налаштування ще одного екземпляру Pi-hole на іншому сервері, продублювати всі налаштування, вказати в DNS-налаштуваннях DHCP один екземпляр як primary, інший - як secondary (в такому випадку, при недоступності primary, клієнти перемкнуться на secondary і матимуть точно такий же функціонал блокування)
Здавалося б, на цьому можна закінчити статтю, адже принцип failover лежить в основі DNS як такого (кілька серверів, переключення між ними на рівні клієнта, і т.д.). Але не все так просто в моєму випадку…
Я використовую ще один функціонал Pi-hole… а саме локальні записи DNS. Це потрібно, щоб не запамʼятовувати, який IP використовується яким сервісом, а також дає змогу налаштувати доступ до сервісів через reverse proxy (можливість забути про специфічні порти також, і використовувати адресу, що легко запамʼятати, як-от http://pi-hole.local для доступу до адмін-консолі).
Просте рішення - дублювати ці локальні записи вручну (зрештою, не так часто це потрібно). Проте я людина лінива - пішов далі…
nebula-sync це рішення, що дозволяє синхронізувати Gravity базу даних між двома екземплярами Pi-hole. До слова, ця база містить не лише записи про адреси, що потрібно блокувати, а й налаштування Pi-hole.
В моєму випадку я вирішив використовувати Docker контейнер, запущений поряд з primary екземпляром для періодичної синхронізації (використовую docker-compose, якщо бути точним).
Код docker compose файлу
---
services:
nebula-sync:
image: ghcr.io/lovelaze/nebula-sync:latest
container_name: nebula-sync
restart: unless-stopped
environment:
- PRIMARY=http://10.0.0.2|pi-hole-access-pass
- REPLICAS=http://10.0.0.5:20720|pi-hole-access-pass
- FULL_SYNC=false
- SYNC_CONFIG_DNS=true
- SYNC_CONFIG_DNS_EXCLUDE=listeningMode
- SYNC_CONFIG_DHCP=true
- SYNC_CONFIG_NTP=true
- SYNC_CONFIG_RESOLVER=true
- SYNC_CONFIG_DATABASE=true
- SYNC_CONFIG_MISC=true
- SYNC_CONFIG_DEBUG=false
- SYNC_GRAVITY_DHCP_LEASES=true
- SYNC_GRAVITY_GROUP=true
- SYNC_GRAVITY_AD_LIST=true
- SYNC_GRAVITY_AD_LIST_BY_GROUP=true
- SYNC_GRAVITY_DOMAIN_LIST=true
- SYNC_GRAVITY_DOMAIN_LIST_BY_GROUP=true
- SYNC_GRAVITY_CLIENT=true
- SYNC_GRAVITY_CLIENT_BY_GROUP=true
- CLIENT_TIMEOUT_SECONDS=60
- RUN_GRAVITY=true
- CRON=0 * * * *Таким чином я роблю всі налаштування лише на primary екземплярі, nebula-sync працює за розкладом і кожну годину синхронізує всі налаштування з primary на secondary сервер. Враховуючи нечасті зміни в налаштуваннях Pi-hole та локальних записах DNS, з великою вірогідністю ми матимемо повністю аналогічну конфігурацію при перемиканні між екземплярами.