Monitorando o homelab inteiro com Prometheus, Grafana e Loki

4 min de leitura

Durante meses o homelab cresceu sem visibilidade nenhuma: eu só descobria que algo tinha caído quando o Jellyfin parava de responder, ou quando a automação da casa ficava muda no meio da noite. No fim de setembro resolvi parar de adivinhar e montei uma stack de observabilidade de verdade. Este post é o mapa do que ficou pronto — o que monitoro, como, e as pegadinhas que apareceram no caminho.

A stack

O coração de tudo é uma VM pequena (3 GB de RAM) que concentra Prometheus para métricas, Grafana para os dashboards e Loki para os logs. Em volta deles, uma turma de coletores faz o trabalho pesado:

  • node_exporter — CPU, RAM, disco e rede de cada host;
  • UnPoller — telemetria do gateway UniFi (clientes, tráfego, pontos de acesso);
  • GoFlow2 — NetFlow/sFlow para enxergar quem conversa com quem na rede;
  • pihole-exporter — consultas DNS e taxa de bloqueio dos Pi-holes;
  • Vector — coleta syslog e entrega tudo no Loki.

O que está sendo vigiado

Depois que os alvos estão cadastrados, a primeira pergunta que eu faço é sempre a mesma: up. Ela devolve 1 para quem está de pé e 0 para quem caiu. Rodando agora, o resultado é um retrato fiel do homelab:

# PromQL
up

# (resultado resumido — tudo em 1 = saudável)
instance=pve            => 1
instance=unpoller:9130  => 1
instance=pihole-1       => 1
instance=pihole-2       => 1
instance=monitor        => 1
instance=mediacenter    => 1
instance=homeassistant  => 1
instance=openclaw       => 1
app=sonarr      instance=mediacenter => 1
app=radarr      instance=mediacenter => 1
app=prowlarr    instance=mediacenter => 1
app=lidarr      instance=mediacenter => 1
app=bazarr      instance=mediacenter => 1
app=seerr       instance=mediacenter => 1
app=jellyfin    instance=mediacenter => 1
app=qbittorrent instance=mediacenter => 1

UniFi e Pi-hole

O gateway UniFi é a caixa-preta da casa: sem ele, internet, VLANs e Wi-Fi somem juntos. O UnPoller expõe as métricas dele direto pro Prometheus — clientes por banda, tráfego por porta, saúde dos pontos de acesso. Do lado do DNS, os dois Pi-holes viram alvos do pihole-exporter, e eu acompanho o percentual de bloqueio e as consultas por cliente.

Dica: cedo ou tarde você vai querer responder “quem está comendo a banda?”. Com o GoFlow2 + NetFlow isso vira um painel, sem precisar habilitar SNMP em cada dispositivo da rede.

Proxmox

O hypervisor entra na stack por dois ângulos: o node_exporter cuida do host (um Lenovo Tiny com SSD de 1 TB e 16 GB de RAM) e o exporter do Proxmox traz o estado das VMs — uptime, CPU e memória por máquina. Assim eu vejo numa tela só se o gargalo é o host ou uma VM específica.

O mediacenter, alvo a alvo

O mediacenter é o alvo mais chato, porque não basta o servidor estar de pé — cada app tem vida própria. Então, além do node_exporter, eu monitoro a saúde de cada serviço pelo seu próprio endpoint HTTP. Na prática, cada um deles vira um alvo no Prometheus:

# fragmento de scrape_configs (apps do mediacenter)
- job_name: apps-mediacenter
  static_configs:
    - targets:
        - http://mediacenter:8989/ping            # Sonarr
        - http://mediacenter:7878/ping            # Radarr
        - http://mediacenter:9696/ping            # Prowlarr
        - http://mediacenter:8686/ping            # Lidarr
        - http://mediacenter:6767/                # Bazarr
        - http://mediacenter:8096/health          # Jellyfin
        - http://mediacenter:8080/api/v2/app/version  # qBittorrent
        - http://mediacenter:5055/api/v1/status   # Jellyseerr

O mesmo raciocínio vale para os discos: com o coletor de SMART eu pego temperatura e setores realocados do SSD de dados, e com o node_exporter acompanho as units do systemd — se o serviço do Jellyfin morrer, o alerta chega antes da reclamação lá de casa.

Logs com Loki e Vector

Métricas contam o que aconteceu; logs contam o porquê. O Vector coleta o syslog dos hosts e entrega no Loki, e a partir daí eu consulto tudo com LogQL. Uma busca simples por erros fica assim:

# LogQL — últimas linhas com "error" ou "warn"
{job=~".+"} |~ "error|warn"

Pegadinha: essa query me devolveu uma linha do gateway UniFi que diz exatamente “Process’ stime is unknown (not an error)”. Ou seja, o próprio log avisa que não é erro, mas a palavra “error” está lá. Filtrar por palavra-chave é só o primeiro passo — o trabalho real é separar ruído de sinal, senão você vira o alerta que ninguém mais lê.

O que aprendi

  • Comece por disponibilidade (up) e só depois invente alertas. Um painel que mostra “tudo verde” já resolve 80% da dor;
  • Um exporter por host, não um por serviço. Cada exporter a mais é um ponto de falha a mais;
  • Alert fatigue é real: se você alertar para cada linha “error”, em uma semana ninguém olha mais. Reserve alertas para o que de fato derruba serviço;
  • Dashboards bonitos não consertam nada sozinhos, mas transformam “está lento?” em “olha o gráfico de I/O do disco às 21h”.

A stack está rodando e o próximo passo é fechar o ciclo: alertas no Telegram pros casos que importam e um dashboard único de “status da casa”. Quando isso sair, vira outro post.