Pessoal,
Pois é, pessoal, quem me conhece sabe que sou um entusiasta de tecnologia, mesmo sendo médico anestesiologista. Meu fim de semana foi dedicado a resolver um pepino na minha rede doméstica, algo que venho postergando há um tempo. Tenho dois Pi-holes rodando aqui em casa, um em uma máquina virtual no Proxmox e outro em um Raspberry Pi 2B. A ideia por trás disso é simples: ter redundância de DNS. Se um Pi-hole cair, o outro assume automaticamente, garantindo que a internet continue funcionando sem interrupções.
Acontece que, por um bom tempo, esses dois Pi-holes eram totalmente independentes, ou seja, caso eu colocasse um domínio em uma allowlist ou colocasse uma nova blocklist, eu tinha que configurar manualmente nos dois. Era um trabalho chato, repetitivo e eu sempre acabava esquecendo de sincronizar um ou outro. Isso gerava inconsistências, com um dispositivo funcionando de um jeito e outro de outro.
Infraestrutura:
Minha configuração é a seguinte:
-
Pi-hole 1: Roda em uma máquina virtual no Proxmox, com Ubuntu 24.04. O IP local dele é 192.168.1.xx1.
-
Pi-hole 2: Está em um Raspberry Pi 2B, com IP local 192.168.1.xx2.
-
Synology NAS: Tenho um Synology NAS que roda Docker e, claro, o Portainer para gerenciar meus contêineres.
-
Rede: Tudo isso está em uma rede doméstica comum, sem VLANs complexas ou configurações mirabolantes.
- Tailscale: todos os meus dispositivos estão ligados entre via Tailscale, de modo que posso conectar com eles fora de casa (inclusive usar o Pi-hole de casa para filtrar anúncios no meu iPhone quando estou no trabalho ou de férias, em outro país)!
O que é o Pi-hole e por que ter dois
Para quem não conhece, o Pi-hole é um “buraco negro” para anúncios na internet. Já falei bastante dele aqui, quando comentei sobre bloqueadores de anúncios e as melhores opções para redes doméstica! Resumidamente, ele atua como um servidor DNS na sua rede doméstica, filtrando as requisições para domínios conhecidos por ter publicidade, rastreadores e conteúdo malicioso. Em vez de resolver o endereço desses domínios, ele os bloqueia, resultando em uma navegação mais limpa, rápida e segura.
Ter um Pi-hole já é ótimo, mas ter dois é ainda! E a REDUNDÂNCIA é o motivo!
Se o Pi-hole principal tiver algum problema (uma atualização que deu errado, queda de energia, etc), o segundo Pi-hole entra em ação. Seus dispositivos automaticamente mudam para o DNS secundário, e você nem percebe que algo aconteceu. O problema, como mencionei, era manter esses dois Pi-holes sincronizados, garantindo que ambos tivessem as mesmas listas de bloqueio e permissão.
Gravity Sync vs Nebula Sync
Antigamente, a solução clássica para sincronizar dois Pi-holes era o Gravity Sync. Eu até tentei usá-lo no passado, mas o projeto foi abandonado. Com a chegada do Pi-hole v6 e a mudança na arquitetura do programa, o Gravity Sync simplesmente não é mais compatível (funciona muito bem ainda nas versões 5.x do Pi-hole, como próprio GitHub deles avisa. Mas para o Pi-hole já é passado.
O Pi-hole 5 era construído sobre peças separadas que se comunicavam entre si: o dnsmasq resolvia o DNS, o lighttpd servia as páginas web, o PHP renderizava o frontend, o SQLite guardava as queries. O FTL (Faster Than Light) era um processo à parte que interceptava o dnsmasq via socket, o que tornava a arquitetura frágil, pois qualquer atualização do dnsmasq podia quebrar tudo.
Com a mudança da arquitetura, no Pi-hole 6 o FTL foi reescrito para ser o centro de tudo. Ele absorveu o dnsmasq internamente, passou a servir o frontend diretamente e eliminou o lighttpd e o PHP. O resultado é um único binário que faz DNS, serve a interface web e expõe uma API REST nativa com autenticação por token. Excelente!
Essa alteração da arquitetura do Pi-hole 5 para o 6 é exatamente o que matou o Gravity Sync, uma vez que simplesmente ele copiava arquivos diretamente via SSH (o gravity.db e os arquivos de configuração do dnsmasq). No Pi-hole 6, esses arquivos mudaram de estrutura ou simplesmente deixaram de existir. Essa sincronização por arquivo bruto deixou de funcionar.
Foi aí que descobri o Nebula Sync. Ele é o substituto atual, ativamente mantido em 2025/2026 e feito sob medida para a nova arquitetura do Pi-hole 6. É a solução que a comunidade tem recomendado. O repositório oficial no GitHub, para quem quiser dar uma olhada, é este: https://github.com/lovelaze/nebula-sync. O Nebula Sync resolve isso de forma elegante: usa a API REST do FTL nos dois Pi-holes, exporta via teleporter (o mecanismo oficial de backup do Pi-hole 6) de um lado e importa no outro. Não depende de arquivos internos, não depende de SSH, não quebra com atualizações. É por isso que ele é o substituto correto para o Pi-hole 6.
A instalação do Nebula Sync
Minha escolha para rodar o Nebula Sync foi o Synology NAS, usando o Portainer. Como o Synology já tem Docker e Portainer instalados e fica ligado 24/7, era o local perfeito para um serviço de sincronização.
A instalação foi via stack no Portainer (basicamente um arquivo docker-compose.yml). No início, tive um pequeno perrengue. Tentei usar variáveis de ambiente antigas, como PRIMARY_HOST_BASE_URL e SECONDARY_HOST_1_BASE_URL, que eram de versões anteriores do Nebula. O contêiner não subia, reclamando de variáveis ausentes.
Depois de consultar a documentação no GitHub do Nebula Sync, descobri o formato correto. As variáveis agora usam um pipe (“|”) para separar a URL e a senha. O compose final que funcionou perfeitamente foi este:
services:
nebula-sync:
image: ghcr.io/lovelaze/nebula-sync:latest
container_name: nebula-sync
environment:
- PRIMARY=http://192.168.1.xx1|senha_do_pihole1
- REPLICAS=http://192.168.1.xx2|senha_do_pihole2
- FULL_SYNC=true
- RUN_GRAVITY=true
- CRON=0 * * * *
Com esse docker-compose.yml, o Nebula Sync foi implantado com sucesso!. A variável FULL_SYNC=true garante que tudo (allowlist, blocklist, grupos e clientes) seja sincronizado entre os dois piholes. RUN_GRAVITY=true faz com que o gravity update seja executado no Pi-hole secundário após a sincronização. E CRON=0 * * * * define a sincronização para acontecer a cada hora.
Os logs que deixei rodando
Antes de sair liberando domínio, resolvi ser (mais) metódico e deixei os dois Pi-holes rodando por algumas horas usando o comando pihole tail | grep -i "blocked" para ver o que estava sendo bloqueado em tempo real. Isso me deu uma visão clara do que estava impactando minha rede.
A análise dos logs revelou uma série de domínios, que pude categorizar em três grupos:
- Pode deixar bloqueado (telemetria pura): domínios que são principalmente de telemetria, analytics e rastreadores. Bloqueá-los não afeta a funcionalidade dos aplicativos ou sites, apenas impede que eles coletem dados sobre seu uso.
-
-
-
-
app-measurement.com, ssl.google-analytics.com: Relacionados ao Google Analytics e Firebase.
-
telemetry.mozilla.org: Telemetria do Firefox.
-
notes-analytics-events.apple.com, metrics.icloud.com: Eventos e métricas da Apple.
-
io, o4503966…sentry.io: Serviços de relatórios de erros e crash reports.
-
github.com: Telemetria do GitHub.
-
twitter.com, ads-api.twitter.com: Diagnósticos e APIs de anúncios do X (antigo Twitter).
-
app-analytics-services.com: Serviços genéricos de análise de aplicativos.
-
statcounter.com: Contadores de visita em sites.
-
googleadservices.com: Serviços de anúncios do Google.
-
analytex-us.userpilot.io: Plataforma de analytics.
-
purchasely.io: Analytics de compras.
-
brainstormforce.com: Analytics de temas e plugins WordPress.
-
api.mega.co.nz: Estatísticas do MEGA, não afeta o funcionamento do serviço.
-
dl-debug.dropbox.com, client-log.box.com: Logs de debug e cliente do Dropbox e Box, não afetam o uso.
-
svc.ui.com: Telemetria da Ubiquiti/UniFi, não afeta o funcionamento da rede.
-
linkwithin.com, cdn.shorte.st: Widgets de blog e encurtadores de URL, só afetam se você visita sites que os utilizam.
-
-
-
- Domínios que podem causar problema visível: domínios que, se bloqueados, podem realmente impactar a experiência de uso de aplicativos e sites.
-
-
-
-
xx.fbcdn.net: CDN (Content Delivery Network) do Facebook e Instagram. Bloquear isso quebra o carregamento de imagens e outros conteúdos de mídia nessas plataformas.
-
graph-fallback.instagram.com: Um domínio de fallback do Instagram, pode causar lentidão ou falhas no carregamento.
-
c10r.facebook.com, instagram.c10r.instagram.com: Domínios relacionados à conectividade e funcionamento interno do Facebook e Instagram.
-
gvt2.com, beacons.gvt3.com: Beacons do Google Chrome. Embora sejam telemetria, em alguns casos, o bloqueio pode causar pequenos atrasos ou comportamentos inesperados em serviços Google.
-
..minerva.devices.a2z.com: Domínios relacionados a dispositivos Amazon, como a Alexa. O bloqueio pode quebrar funcionalidades importantes desses dispositivos.
-
appsgrowthpromo-pa.googleapis.com: Promoções de aplicativos do Google. Geralmente inofensivo, mas pode impactar a descoberta de apps.
-
crashlyticsreports-pa.googleapis.com: Relatórios de crash do Crashlytics. Embora não quebre o app, pode impedir o envio de relatórios de erro.
-
-
-
- Os wildcards liberados:
Com base na análise dos logs e nos problemas que já tinha enfrentado, decidi liberar um total de 14 wildcards. Isso inclui os domínios que estavam causando problemas com WhatsApp e X, que eu já havia identificado antes.
-
-
-
- X.com / Twitter
-
-
pihole allow --wild x.com
pihole allow --wild twimg.com
pihole allow --wild t.co
pihole allow --wild whatsapp.net
pihole allow --wild whatsapp.com
-
-
-
- Facebook / Instagram
-
-
pihole allow --wild fbcdn.net
pihole allow --wild c10r.facebook.com
pihole allow --wild c10r.instagram.com
pihole allow --wild instagram.com
-
-
-
- Google Chrome beacons
-
-
pihole allow --wild gvt2.com
pihole allow --wild gvt3.com
-
-
-
- Amazon / Alexa
-
-
pihole allow --wild a2z.com
Cada um desses comandos foi executado no Pi-hole 1 (o que roda na VM no Proxmox) e, através do Nebula Sync, todas essas permissões foram automaticamente replicadas para o Pi-hole 2, garantindo que ambos os servidores DNS tenham exatamente as mesmas regras! Desse modo, qualquer alteração que eu faça no meu Pi-hole 1 é replicada automaticamente no Pi-hole 2 a cada hora. Não preciso mais me preocupar em fazer tudo manualmente, o que me economiza, esforço e garante a consistência da minha rede.
Onde o Tailscale entra nisso tudo?
Para que os dispositivos conectados via Tailscale usem os Pi-holes como DNS, a configuração não fica no Pi-hole, mas no painel de administração do Tailscale. Em DNS → Nameservers, você adiciona os IPs dos dois Pi-holes (no meu caso, os IPs do Tailscale deles, como 100.90.xxx.yy1 , o Pi-hole1, e 100.87.xxx.yy2, o Pi-hole 2) como nameservers globais e ativa a opção Override local DNS. A partir daí, qualquer dispositivo na sua tailnet passa a resolver DNS pelos Pi-holes, independente de onde esteja no mundo.
O segundo passo é garantir que o Pi-hole aceite consultas DNS vindas da faixa de IPs do Tailscale, que é o range 100.64.0.0/10. Por padrão o Pi-hole aceita queries de qualquer origem local, mas dependendo da configuração de interface no FTL, pode rejeitar pacotes chegando pela interface do Tailscale (tailscale0). A solução é garantir que nas configurações do Pi-hole, a opção Listen on all interfaces esteja ativa, ou adicionar explicitamente a interface tailscale0 nas interfaces monitoradas.
O terceiro ponto é o MagicDNS do Tailscale. Se você usa MagicDNS para resolver nomes dos seus próprios dispositivos na tailnet (tipo proxmox.tail1234.ts.net), precisa tomar cuidado para não deixar o Pi-hole tentar resolver esses domínios localmente. O correto é manter o MagicDNS ativo no Tailscale e deixar o Pi-hole só filtrar o tráfego externo, sem tentar ser autoritativo para os domínios .ts.net.
Na prática, o fluxo funciona assim: dispositivo fora de casa conecta no Tailscale (via Wifi público ou 5G), o Tailscale força o DNS para os Pi-holes via 100.90.xxx.yy1 ou 100.87.xxx.yyy2, o Pi-hole filtra normalmente e devolve a resposta. O resultado é que você tem bloqueio de ads e trackers funcionando em qualquer rede, inclusive no celular via dados móveis, sem precisar de VPN adicional. O Tailscale já é a VPN, o Pi-hole já é o DNS, os dois se complementam.
Mas como a vida não é uma cereja e nem tudo são flores, claro que tem um preço a pagar. E esse preço é a latência aumentada.
Quando estou em uma rede boa, como Wi-Fi de casa ou do hospital ou até em fibra de hotel, a diferença é imperceptível. Mas em redes móveis com sinal ruim, como 3G ou 4G congestionado, o fato de cada consulta DNS precisar viajar até minha casa no Brasil, ser resolvida pelo Pi-hole e voltar, adiciona um atraso perceptível. Páginas que deveriam abrir em instantes ficam girando por mais tempo do que o normal. Para páginas, até que não é problemático. O problema é o segundo problema, abaixo.
O segundo problema são as imagens e vídeos. Isso não é culpa direta do Tailscale ou do Pi-hole, só que a combinação dos dois em uma rede lenta amplifica o problema. Alguns CDNs de imagens, especialmente os do Facebook, Instagram, WhatsApp e X, dependem de uma resolução DNS rápida para direcionar o usuário para o servidor mais próximo. Com o DNS resolvendo do Brasil, o CDN pode direcionar para um servidor subótimo, resultando em carregamento lento de imagens. Vídeos em streaming sofrem o mesmo problema, com buffering mais frequente em conexões móveis. Às vezes as imagens e vídeos nem são carregados!
A solução que uso na prática é simples: quando estou em uma rede ruim e preciso de velocidade máxima, desativo temporariamente o Tailscale no iPhone. Isso libera o DNS para o servidor local da operadora, que é geograficamente próximo e resolve em milissegundos. Para navegação cotidiana, o custo da latência extra vale a pena pelo ganho em privacidade e ausência de anúncios.
Para streaming ou download de arquivos grandes em rede ruim, desativar temporariamente é a decisão pragmática.
Bom, é isso por hoje, pessoal!
