O laboratório nasceu embaixo de uma mesa de madeira. Um OptiPlex mini comprado usado, dois discos USB, e a promessa que todo mundo faz: "é só pra testar umas coisas".
Seis meses depois eu tinha 17 guests rodando, e o que era brinquedo já era a máquina de onde eu trabalho, o DNS da casa e as fotos da família. Só que ele continuava parecendo brinquedo: cabos, um dock de HD em cima da mesa, nada padronizado.
Comprei um rack Tecmojo de 4U, formato 10 polegadas, feito exatamente para mini PC. Não é homelab de influencer com rack de 42U. É pequeno, branco, cabe numa prateleira, e o que me convenceu foi ver que sobrava espaço: quatro unidades são mais do que eu preciso hoje.
São 15 containers e 2 VMs. Nem todos aparecem abaixo: a lista traz os que importam. O critério de "um serviço por container" não é dogma de arquitetura bonita, é sobre o que você faz às 2 da manhã quando algo quebrou: se o buscador cai, não quero descobrir que levou a automação junto porque dividiam o mesmo container.
Barramento e automação
- n8n— orquestração dos fluxos. É o que amarra o resto.
- SearXNG — metabusca self-hosted. Serve de backend de busca para os agentes, sem depender de API paga.
- Evolution API — gateway de WhatsApp para os fluxos internos.
Camada de IA
- LiteLLM — gateway único para todos os provedores de modelo. Centraliza chaves, aplica teto de gasto por serviço e roteia por custo: tarefa simples não precisa do modelo caro.
- Hindsight — servidor de memória de longo prazo dos agentes, com Postgres e busca vetorial.
- Pi-hole — o resolvedor de DNS de toda a rede. Guarde esse nome, ele volta lá embaixo como o vilão do pior incidente que eu tive.
Armazenamento e proteção
- OpenMediaVault — NAS com dois discos USB (2 TB + 1 TB) via SMB. É onde vive o meu vault de notas.
- Proxmox Backup Server — datastore em HD externo, 14 jobs escalonados de madrugada, `keep-last=7` cada. São 14 de 17 guests: os outros três são o template base e dois que ficam desligados.
Qualidade e observabilidade
- SonarQube — análise estática no que eu escrevo.
- Homarr — o painel único com o estado de tudo.
Pessoal
- Jellyfin + stack de mídia completa (indexador, gerenciadores, legendas).
- Immich — as fotos da família.
- Home Assistant – automações da casa.
O agente que cuida do lab
"Eu não quero ter trabalho de monitorar."
Rodando agora, sem eu tocar em nada:
- um **watchdog a cada 15 minutos** que verifica integridade, recursos, containers em crash-loop e serviços fora do ar, e "corrige o que consegue" antes de me avisar;
- um "checador de mounts de hora em hora" — aprendi da pior forma que um share que cai não avisa;
- um "health check do gateway de IA a cada 5 minutos", com fallback automático entre provedores;
- um "ciclo noturno" que consolida memória e revisa o dia;
- e um "mensal que varre o parque inteiro" contra estado conhecido: pacotes pendentes, guest que não subiu, backup faltando, DNS divergente, disco cheio. Diferente do watchdog, o mensal não age: ele reporta e me deixa decidir.
Isso mudou quando percebi que monitorar "o job rodou sem erro" não quer dizer nada. Eu tinha todos os jobs com status verde enquanto o conteúdo da pipeline não saía havia dias. Job que executa sem crashar não é job que funcionou.
As três coisas que doeram:
- Bind mount por IP de LAN é uma bomba-relógio.
Eu tinha mounts apontando para o endereço do host de origem. Quando ele trocou de rede, o caminho simplesmente não existia mais. O container subia, o serviço não, e o erro não dizia nada útil.
Correção: os mounts passaram a usar o endereço da malha privada em vez do IP da LAN. A malha sobrevive à troca de rede, o IP da LAN não.
- O hypervisor reescreve o `/etc/resolv.conf` de cada container a cada boot.
Descobri isso quando o DNS do lab inteiro caiu, silenciosamente.
O cliente da malha subiu no host e passou a injetar o próprio IP de resolver naquele arquivo. O hypervisor, a cada boot, copia esse arquivo do host para dentro de cada container. Resultado: os 17 guests herdaram um único resolver, um Pi-hole rodando numa instância gratuita de nuvem, fora de casa.
Ou seja: todo guest sem `nameserver` próprio dependia de um servidor na internet estar de pé. Não estava. E o sintoma que eu via era o disco de mídia não montar, o que não tinha relação nenhuma com o problema real.
Correção: `nameserver` declarado na config de cada container, que sobrevive a reboot. E a lição que ficou — quem não tem a malha não alcança o IP dela (é faixa CGNAT), então esses ficaram como exceção explícita com DNS público. Exceção documentada, não descuido.
- Fiz backup tarde.
Rodei meses com backup em 5 dos 14 guests que existiam, zero backup, porque na hora era "só um lab". Quando finalmente montei o backup server e varri o parque, encontrei quase 800 pacotes pendentes de atualização nos guests esperando a primeira manutenção de verdade. O ciclo seguinte atualizou quase 900 pacotes no total, porque os repositórios publicaram mais coisa no meio do caminho. Não quebrou por sorte.
O que eu faria diferente:
Backup no primeiro dia.
A decisão de como fazer backup fica pior quanto mais serviços existem. Com 3 guests você configura em uma tarde. Com 17, você monta um PBS, descobre que o mount do HD externo não sobrevive a reboot, e acaba com 14 jobs escalonados entre 02:45 e 05:45.
Documentar no momento da decisão.
Metade dos problemas que resolvi aqui eu já tinha resolvido antes, e resolvi de novo do zero porque a solução ficou só na minha cabeça. Hoje escrevo o motivo junto com a correção. O "por quê" é a parte que não volta.
Números, pra quem gosta
- 17 guests (15 containers + 2 VMs) num mini PC usado
- Rack de 4U em 10 polegadas, **duas unidades livres**
- 14 de 17 guests com job de backup escalonado, `keep-last=7`
- ~890 pacotes atualizados no ciclo de manutenção seguinte, zero erros
- Watchdog a cada 15 min, monitor de mount de hora em hora, health do gateway a cada 5 min
O lab cabe numa prateleira.
A dívida técnica dele não caberia.
Pergunta pra quem tem lab:
qual foi a decisão que você adiou achando que era cedo demais?
Aqui foi o backup, e foi o único item que me custou tempo de verdade.
Source: r/autohospedagem · by /u/Oceanstone
