Meu laboratório doméstico cresceu ao longo dos anos. Lembro-me de começar com apenas dois serviços – Jellyfin e Nextcloud. Com mais de 15 serviços ativos hoje, cada um com seu próprio arquivo de compilação, raramente visito essas configurações porque elas nunca requerem atenção. Tenho vivido com LLMs locais como Gemma 4, Qwen 3.5 e DeepSeek-R1 nas últimas semanas. Tudo funciona no meu RTX 4070 Ti. Não para codificação ou bate-papo casual, eu os uso em meu fluxo de trabalho diário.
Recentemente, tentei fornecer acesso LLM local ao meu contêiner Docker para substituir meus scripts de monitoramento e alimentei Gemma com meses de logs DNS para entender os padrões de tráfego em minha rede doméstica. Para continuar minha pesquisa, decidi alimentar Gemma com todos os meus arquivos escritos. Não porque eu estivesse tentando testar a segurança, mas porque queria ver se Gemma conseguia entender toda a minha pilha de uma vez. Em vez de acumular uma pilha, comecei a questionar decisões nas quais eu havia parado de pensar há muito tempo.
Não estou procurando uma auditoria de segurança
A primeira surpresa foi diante de Gemma
Uso o Portainer desde o início. Foi até o primeiro contêiner Docker que implantei em meu servidor homelab. Quando decidi fazer esse experimento, pensei que extrair os arquivos de gravação do volume Portainer seria questão de minutos. Como implantei tudo usando o recurso de pilha do Portainer, presumi que tudo estaria bem organizado em diretórios separados.
Comecei com um docker inspect comando para encontrar o local de armazenamento real do Portainer. Uma vez eu corri sudo find comando neste volume ao procurar arquivos de composição, fiquei surpreso ao ver apenas 8 pastas de pilha, enquanto eu tinha mais de 15 pastas de pilha. O que tornou tudo mais estranho foi que todos os serviços estavam funcionando bem e eu podia ver todos eles no painel do Portainer.
Depois de horas de várias sessões SSH nas quais não consegui encontrá-las, me deparei com a página Portainer Stacks. Notei que algumas das chaminés estavam sob controle limitado. Comecei a pensar: se eu tivesse implantado todos eles usando o recurso de pilha do Portainer, por que ele tinha controles limitados? Não todos, mas quase metade. Foi quando percebi: quando atualizei o Portainer há algumas semanas, ele pode ter obtido uma nova imagem inicializada com um nome de volume diferente. Para confirmar minha teoria, lancei imediatamente docker volume ls equipe e me deu dois volumes do Portainer. Correndo sudo find a equipe descobriu todas as pilhas que faltavam no volume antigo.
Depois que obtive os diretórios de pilha de ambos os volumes, foi necessário um script Python simples para copiar os arquivos deles em um único diretório, compile_collect. Mas como dois serviços (cloudflared e Jellyfin) não eram gerenciados, exportei manualmente suas configurações e coloquei os arquivos JSON no mesmo diretório. Depois que tudo estava pronto, o próximo passo era descobrir como alimentá-los no Gemma 4 para análise.
Criando um pipeline de revisão
Ele conectou os pontos
Estou executando Gemma 4 E4B em meu RTX 4070 Ti usando Ollama. Para a interface, algo como Open WebUI pode servir. Open WebUI teria sido bom para revisar um arquivo por vez, mas eu queria despejar todos os arquivos de construção e suas dependências em uma sessão para que Gemma pudesse analisar toda a minha pilha de uma vez. Foi então que decidi criar um painel personalizado.
Criei um painel HTML local simples que aceitava vários arquivos .yml, .env e exportava simultaneamente arquivos JSON fornecidos por um proxy Python leve. O processo foi simples: quando coloquei todos os arquivos no painel e cliquei no botão Analisar com Gemma, ele combinou os arquivos brutos do Compose em um único prompt. Proxy Python somente stdlib nativo (sem instalação de pip, sem dependências) POST por Gemma via Ollama /api/chat endpoint e transmitiu a resposta de volta. Isso permitiu que Gemma entendesse como toda a minha pilha do Docker se encaixava. Nenhuma API de nuvem ou serviços externos estão envolvidos.
Os arquivos Docker Compose já eram estruturados e descritivos, portanto, os arquivos brutos tinham mais significado do que um resumo processado. A primeira versão era um único arquivo HTML (index.html) e um arquivo Python (proxy.py). Era funcional, mas simples. Como desenvolvedor independente, não gostei nada da experiência. Então, passei uma tarde tentando reconstruí-lo corretamente usando o frontend Vite + Tailwind e o backend FastAPI. Durante a construção, também decidi adicionar cartas de estatísticas e uma tabela de pilha para fazer com que parecesse mais uma ferramenta real do que um protótipo.
Afinal, mesmo antes de Gemma dizer qualquer coisa, o painel tinha detalhes dignos de nota: 18 serviços em 15 pilhas, 11 imagens não fixadas, 22 ligações e um contêiner usando a rede do host. Não descobertas de segurança, mas o suficiente para saber onde procurar enquanto Gemma estava no trabalho. Então Gemma começou a explicar o que tinha visto e, depois de algumas perguntas complementares, a conversa passou da documentação da pilha para o questionamento de algumas das decisões ocultas nela.
Alguns dos avisos foram surpreendentemente precisos
Novos olhos sobre decisões esquecidas
Depois de fazer upload de todos os arquivos, reunir as informações e clicar no botão Analisar com Gemma, Gemma teve a primeira resposta em segundos. Eu esperava que fosse um resumo da minha pilha, mas desde a primeira linha ele começou a destacar problemas críticos de segurança e a me pedir para resolvê-los imediatamente. Parecia menos um chatbot e mais um novo colega de equipe sem nenhum histórico de por que tomei essas decisões, o que acabou sendo exatamente o feedback de que eu precisava.
Ele revelou dois problemas principais com dois dos meus contêineres, Vaultwarden e Keeper. Meu arquivo de escrita do Vaultwarden tinha ADMIN_TOKEN código rígido em texto simples e o arquivo Keeper tinha GOOGLE_CLIENT_SECRET e ENCRYPTION_KEY. Todas essas credenciais eram muito confidenciais e Gemma as anotou claramente, sem se preocupar com isso. Francamente, eu tinha esquecido ADMIN_TOKEN estava até no arquivo Compose, e o Keeper o tinha para um pequeno experimento que eu estava fazendo, então criptografei os segredos para minha própria conveniência. Mas Gemma não tinha contexto para isso e os marcou mesmo assim.
Outras questões também revelaram alguns riscos de infraestrutura. Por exemplo, docker.sock foi instalado no Dockge, então Gemma sugeriu que, se o Dockge fosse comprometido, ele poderia expor o daemon do Docker. Outro elemento essencial foi que meu serviço de teste estivesse conectado /dev/sdanão é uma vulnerabilidade direta, mas expandiu o alcance do contêiner comprometido.
Ele também sinalizou meu contêiner AdGuard Home por usar a rede host para algumas portas sem especificar uma restrição de modo de rede. Ele explicou que, embora os serviços DNS devam expor essas portas, vários métodos sem um ponto de controle de entrada claro podem aumentar a superfície de ataque. No meu caso foi um falso positivo porque o AGH atende apenas minha rede local e o YAML não consegue detectar topologia de rede, regras de firewall ou controles de acesso.
Gemma me ajudou a ver suposições que parei de questionar. Nenhuma dessas configurações era nova. Eles simplesmente suportaram meses de atualizações porque nada havia quebrado ainda.
Finalmente encontrei um LLM nativo de código aberto que realmente compete com a IA da nuvem
O código aberto está chegando
Minha pilha tinha segredos que eu havia esquecido
Gemma não substituiu o scanner de segurança. Não era para ser. Mas, como um novo par de olhos, ele examinou cada arquivo gravado e questionou as decisões que tomei durante a implantação e nunca revisei. A melhor parte de todo o experimento foi que, como tudo estava sendo executado localmente, não hesitei em entregar arquivos de gravação que continham credenciais confidenciais. Algo que eu nunca faria com um LLM em nuvem. A maior conclusão não foi que Gemma descobriu os problemas de segurança, mas que isso me fez repensar as decisões que tomei e que silenciosamente se tornaram permanentes.






