Conversando com a infraestrutura: como transformei meu servidor LAMP em um assistente no Telegram com n8n e IA

Notas de campo de quem passou anos em infra e redes e agora está colocando a mão na massa com IA — sem hype, com sudoers, SSH e cron no meio do caminho.

Quem trabalha com infraestrutura há um tempo desenvolve um certo reflexo: monitoramento “resolvido” é monitoramento que ninguém olha. Temos Zabbix, Prometheus, Grafana, Netdata — dashboards lindos que, na correria, viram abas esquecidas no navegador. A informação existe; o que falta, muitas vezes, é a interface certa no momento certo.

Foi essa incômoda observação que me levou a um experimento. Estou estudando IA aplicada de forma prática (longe dos slides de “IA vai mudar tudo”) e quis responder a uma pergunta concreta: e se a interface de operação do servidor fosse simplesmente uma conversa? E se, em vez de abrir um terminal ou caçar um painel, eu pudesse perguntar “como está o servidor?” e agir a partir da resposta — e se o próprio servidor me chamasse quando algo saísse do trilho?

O resultado é um assistente que vive no Telegram, fala português e opera um servidor com segurança. Abaixo, a arquitetura, as decisões de infra por trás dela e o que aprendi tratando um LLM como mais um componente do sistema — não como mágica.


O problema, do ponto de vista de quem opera

Monitoramento tradicional é pull e dashboard: uma ferramenta coleta métricas e você vai até ela. Funciona, mas tem duas fricções clássicas:

  1. Latência humana de consulta. Entre a dúvida (“será que o disco encheu?”) e a resposta, há login, navegação, filtro. Pequeno, mas suficiente para você adiar.
  2. Fadiga de contexto. Para uma ação simples (reiniciar o um serviço), você sai do canal onde já está — o celular, uma conversa — e entra em outro contexto operacional.

A proposta aqui não é substituir Zabbix nem Prometheus. É adicionar uma camada de interface conversacional por cima da operação: rápida de consultar, natural de comandar, e capaz de me cutucar proativamente. Pull e push, no canal onde eu já vivo.


A arquitetura, sem romantismo

[Reativo]  Telegram Trigger ─┐
[Proativo] Schedule (6h)     ─┼─►  AGENTE / LÓGICA  ─►  Sub-workflow "Servidor"
[Proativo] Schedule (10min)  ─┘                          (Code → SSH → script Python)
                                                              │
                                                         servidor

A peça central é um sub-workflow de coleta que ninguém vê: recebe uma operação, valida, abre SSH até o servidor e roda um script Python que devolve JSON. Tudo o mais — o bot que conversa, o resumo das 6h, o vigia que roda de 10 em 10 minutos — apenas consome esse núcleo. É o princípio de não repetir lógica (DRY) aplicado à automação: uma fonte de verdade para coletar e agir.

Aqui entra a primeira decisão de infra que vale ouro: o n8n roda em Docker. Para quem é de infra, o alerta acende sozinho — um container é uma fronteira de isolamento. Qualquer execução “local” acontece dentro do container, que não enxerga o systemctl, os logs nem o Python do host monitorado. A tentação de usar um nó de “Execute Command” morre aqui. A resposta correta é a que qualquer admin usaria: SSH com autenticação por chave, saindo do container e entrando no servidor pela porta 22. Sem senha, sem expor nada além do canal já controlado por firewall.


As ferramentas do n8n, com lente de infra

O n8n é, na prática, um orquestrador visual de fluxos. O que importa é entender o papel de cada bloco:

Trigger (Telegram ou Schedule). É o que decide quem inicia. Telegram = evento (reativo). Schedule = relógio (proativo). Trocar um pelo outro, mantendo o resto, é o que permite ter os dois modos com o mesmo núcleo.

AI Agent (Tools Agent). O orquestrador de decisão. Ele recebe a frase, decide se precisa de ferramenta, qual e com quais parâmetros, executa e redige a resposta. Pense nele como um operador que sabe quando chamar cada script — não como a fonte dos dados.

Chat Model. O motor de linguagem do agente. É plugável: você troca o modelo sem refazer o fluxo.

Memory (Simple Memory). Memória de curto prazo da conversa, com o chat.id como chave de sessão. Sem ela, cada mensagem é um stateless request e o bot perde o fio.

Call n8n Workflow Tool + Code node. A ponte para a ação real. E aqui está o ponto de segurança mais importante de todo o projeto: o Code node aplica uma whitelist. O LLM pode até “decidir” mandar um comando esquisito, mas só serviços e ações de uma lista fixa passam. Em termos de infra, esse nó é o plano de controle; o LLM é apenas entrada não confiável.

SSH node. Executa no servidor monitorado usando a chave do usuário de serviço. É o equivalente, dentro do n8n, ao que eu faria num runbook: conectar e rodar um comando idempotente.

Schedule Trigger. Cron. Simples assim — e com uma pegadinha que já me pegou e detalho mais abaixo.


O LLM como componente não confiável (e os modelos que testei)

Talvez a mudança de mentalidade mais útil que tirei desse experimento: tratar o modelo de IA como um operador júnior muito rápido, porém não auditável. Ele é ótimo para interpretar intenção e formatar saída, mas não pode ser a autoridade final sobre o que roda no servidor. Por isso a validação determinística (whitelist, regex anti-injeção, sudoers restrito) é quem manda. O LLM sugere; a infra decide.

Com essa régua, o modelo vira uma escolha de custo/latência/qualidade, não de confiança. Os que considerei:

  • Groq — minha escolha pela latência ridícula de baixa e tier gratuito. Atenção operacional: em junho de 2026 a Groq descontinuou o llama-3.3-70b-versatile e o llama-3.1-8b-instant. Hoje miro em openai/gpt-oss-120b (mais capaz, bom em tool calling), openai/gpt-oss-20b (leve e barato) ou qwen/qwen3.6-27b (meio-termo).
  • Anthropic (Claude) — muito sólido em seguir instruções e em tool calling encadeado; linha Sonnet equilibra custo e qualidade, Haiku para o barato e rápido.
  • OpenAI (GPT) — o “padrão de mercado”, previsível e bem documentado.
  • Google Gemini — forte em contexto longo e multimodal, caso um dia eu queira que ele leia um print de gráfico.
  • Mistral, xAI Grok, DeepSeek — todos com nó pronto no n8n e bom custo-benefício.
  • Ollama (on-premise) — para quem, por compliance ou paranoia saudável, não quer que nenhum dado saia da própria rede. Roda um modelo open-weight local. Troca velocidade/qualidade por soberania total dos dados.

Observação de quem testou: modelos pequenos às vezes “respondem de cabeça” em vez de chamar a ferramenta. Quando isso acontece, ou subo de modelo ou endureço a system message. A regra “nunca invente números, sempre use a ferramenta” precisa estar explícita — é, no fundo, uma política operacional escrita em linguagem natural.


“Se você está usando IA, por que não faz tudo com IA?”

É a pergunta que mais ouço quando mostro esse projeto — e a resposta revela, na minha visão, a diferença entre usar IA e entender onde usá-la.

Eu poderia ter colocado um agente de IA autônomo dentro do servidor, com acesso ao shell, e pedido “descubra o uso de disco e me diga”. Funcionaria… às vezes. E é justamente esse “às vezes” que produção não tolera. Optei por um script Python determinístico por razões que, para quem é de infra, beiram o óbvio:

Determinismo. Código faz a mesma coisa toda vez. df -h / devolve o número real, sempre. Um LLM é probabilístico por natureza — excelente para linguagem, inadequado como fonte de verdade sobre o estado de um sistema.

Zero alucinação no dado crítico. Um agente perguntado “quanto de disco está livre?” pode, num dia ruim, inventar um número plausível ou rodar um comando que você não previu. Um script que executa df literalmente não tem como alucinar a saída — ele apenas transporta o que o sistema operacional respondeu.

Auditabilidade. O Python está versionado, é legível, testável e reproduzível. Eu sei exatamente o que ele faz, linha a linha. A decisão de um agente autônomo é opaca e não reproduzível — péssima propriedade quando algo quebra às 3h da manhã.

Superfície de ataque e raio de explosão. Um agente com shell livre no servidor é um convite. Um script atrás de whitelist faz só o que foi autorizado a fazer. Menos poder, menos risco.

Custo e latência. Coletar métrica é uma operação resolvida, instantânea e gratuita no shell. Embrulhar isso numa chamada de LLM adiciona tokens, latência e um ponto de falha externo — para ler um termômetro. Não compensa.

A síntese que adotei é simples: IA na borda, determinismo no núcleo. O modelo cuida da parte difusa — interpretar “reinicia o apache aí”, resumir um JSON em português, conversar. O código cuida da parte exata — coletar, validar, executar. Cada um no que é bom.

E aqui está o ponto que costuma faltar nessa discussão: conhecimento de servidor e de programação não é o que a IA substitui — é o que me permite traçar a fronteira certa. Quem não domina o terreno tende a delegar demais ao agente, porque não percebe que aquela tarefa poderia ter sido um df de uma linha. Saber operar e programar é justamente o que me dá a confiança de dizer “isto aqui não precisa de IA” — e essa decisão elimina alucinação, economiza tokens e devolve previsibilidade.

Isso não significa que agente autônomo no servidor nunca tenha lugar. Para diagnóstico exploratório e aberto — o tipo “investigue por que a aplicação está lenta”, onde você não consegue pré-roteirizar todos os caminhos — um agente com ferramentas pode brilhar. Mas para coletar métrica e reiniciar serviço, tarefas determinísticas e bem definidas, código é mais barato, mais seguro e mais confiável. IA (ainda) não é para tudo, e reconhecer isso não é ceticismo: é engenharia.


Reativo + proativo: pull e push no mesmo canal

A versão inicial era puramente reativa. Mas monitoramento de verdade é proativo. A graça da arquitetura é que inverter o sentido não exige reescrever nada: troca-se o gatilho, reaproveita-se o núcleo. No fim, três fluxos coexistem, todos chamando o mesmo sub-workflow de coleta:

1. Bot conversacional (pull, sob demanda). “Como está o servidor?”, “reinicia o serviço”, “desabilita um vhost”. Eu pergunto, ele age.

2. Resumo diário às 6h (push agendado). Um Schedule Trigger (0 6 * * *) coleta o status e me manda o bom-dia:

☀️ Bom dia, Kleber! O servidor amanheceu com 80% de disco livre, memória em 45% (1.800 de 4.000 MB) e CPU em 12%. Serviços ativos.

Para esse resumo prefiro um template determinístico (um pequeno Code node) em vez de gastar tokens — confiabilidade acima de criatividade. Mas, se quiser variação de tom, dá para rotear o JSON por um modelo e deixar a frase mais humana a cada dia. Decisão de produto, não de engenharia.

3. Watchdog a cada 10 minutos (push por exceção). Um Schedule (*/10 * * * *) coleta e avalia limites: disco ≥ 90%, memória ≥ 90%, qualquer serviço inativo. Se estiver tudo bem, ele cala a boca — não emite item algum e o Telegram nem dispara. Só fala quando há o que falar.

E aqui entra outro reflexo de infra: fadiga de alerta. Um watchdog ingênuo que roda de 10 em 10 minutos com o disco a 95% vira spam — e alerta que vira spam é alerta ignorado. A solução é deduplicação por estado: guardo a “assinatura” do último alerta na static data do workflow e só notifico quando o estado muda (apareceu um problema, ou ele se resolveu). É o mesmo princípio de flapping detection dos monitores clássicos, só que em três linhas de JavaScript.

O passo seguinte, que estou amadurecendo, é a autocura: se um cair, o watchdog primeiro chama a ação de restart e só então me avisa — “o Serviço estava fora, reiniciei e voltou”. Aí o assistente deixa de vigiar e começa a operar. Com a devida cautela: ação automática em produção pede idempotência, limites de tentativas e log de tudo. Não é porque é fácil de escrever que é seguro deixar solto.


Segurança: o de sempre, porque o de sempre funciona

Dar a um agente de IA acesso a um servidor não muda os fundamentos — só aumenta a importância deles:

  • Menor privilégio. O sudoers libera comandos específicos e nada mais. Nunca um ALL aberto. O usuário de serviço faz exatamente o que precisa, e só.
  • Autenticação por chave. SSH sem senha, chave dedicada ao bot, e idealmente um usuário de serviço sem shell interativo amplo.
  • Whitelist como plano de controle. A entrada do LLM é tratada como não confiável; o que executa é decidido por código determinístico.
  • AuthN no canal. Um filtro por chat.id garante que só o meu Telegram comanda. Sem isso, qualquer um que ache o bot teria um console remoto.
  • Aprovação humana para o destrutivo. Para parar serviço ou desabilitar vhost, um passo de confirmação. Automatize o reversível; pause o irreversível.

Nada disso é novidade para quem é de infra. É justamente o ponto: a IA entra como interface e orquestração, sobre uma base de segurança que você já domina.


O script de coleta e o que vale a pena adicionar

O agente no servidor é um Python enxuto que recebe flags e responde sempre em JSON — formato que o orquestrador adora. A versão inicial cobre CPU, memória, disco, status de serviços, logs e gestão de vhosts. Expandir é só somar uma função. Da minha lista de “infra quer saber disso”:

  • Load average e uptime — saturação real costuma aparecer melhor na média de carga que no pico instantâneo de CPU.
  • Top processos — para responder “o que está pesando agora?”.
  • Espaço por partição — todas, não só a /; quase sempre é a /var que enche primeiro.
  • Expiração de certificados SSL — dias até vencer, por vhost. O clássico incidente evitável.
  • Pacotes de segurança pendentes — higiene de patching ao alcance de uma pergunta.
  • Status do Fail2ban — IPs banidos por jail; ótimo termômetro de ataque em curso.
  • Banco de dados — tamanho dos schemas e, com réplica, o status de replicação.
  • Conexões ativas (Web server server-status) — tráfego em tempo real.
  • a2ensite e configtest — reativar sites e validar a config antes do reload, para nunca derrubar o serviço com um arquivo quebrado.

A regra de limite (o “≥ 90%”) pode viver no Code node (flexível, ajusta sem tocar no servidor) ou no próprio script (centraliza a política). Ambos funcionam; é uma escolha de onde você quer que more a fonte de verdade.


A pegadinha que todo mundo erra: timezone

Como o n8n está em Docker, o cron usa o fuso da instância — e o padrão de container é UTC. Resultado: um 0 6 * * * “bom dia” dispara às 3h da manhã no horário de Brasília. A correção é definir GENERIC_TIMEZONE e TZ (ex.: America/Sao_Paulo) no container, ou ajustar o fuso direto no nó. Detalhe bobo, mas é exatamente o tipo de coisa que separa o “funcionou no teste” do “funcionou em produção”.


Onde isso se encaixa (e onde não)

Sejamos honestos: isto não substitui uma stack de observabilidade séria. Não tem histórico de métricas, não tem retenção, não correlaciona eventos como um Prometheus + Grafana. O que ele faz, e faz bem, é ser a camada de interação humana — a ponta amigável que torna a operação rápida e o alerta presente no canal certo. Penso nele como um complemento: o Zabbix guarda a verdade histórica; o assistente traz a verdade do agora para a conversa e age sobre ela.


O que aprendi testando IA na prática

Três conclusões que levo desse experimento, de quem olha pela ótica de infra:

  1. A IA não é o sistema; é um componente. Ela orquestra e traduz. A robustez continua vindo de fundamentos — validação, menor privilégio, idempotência, tratamento de erro.
  2. Prompt é configuração. A system message é, na prática, um arquivo de política. Versionar e tratar com o mesmo rigor de um playbook compensa.
  3. O ganho real é de interface, não de inteligência. O encanto não está no modelo ser “esperto”, e sim em reduzir o atrito entre intenção e ação. Para operação, isso é ouro.

Saí desse projeto convencido de que o lugar mais imediato da IA na minha rotina não é decidir por mim — é remover fricção. E isso, para quem vive de manter sistemas de pé, já é transformador.

E você, que está em infra: confiaria a um agente de IA o restart automático de um serviço em produção? Em quais tarefas deixaria solto e em quais exigiria o dedo humano no gatilho? Curioso para ler os contrapontos nos comentários.s.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *