anúncios

quarta-feira, 19 de agosto de 2026

Seu container está com o relogio errado (e você não sabe)

Toda segunda-feira às 8h da manhã, a equipe recebia um tsunami de tickets de "não consigo logar".

O sistema de autenticação estava quebrando religiosamente, toda segunda-feira.

Depois de 3 semanas investigando, encontrei o culpado:

O JWT tinha expiresIn: "7d", parecia correto, né?

Mas o relógio do servidor de autenticação estava 3 minutos adiantado.

E o servidor que validava os tokens? Com o relógio correto.

Resultado: o token expirava antes de deveria. E a diferença foi acumulando com o drift do relógio.

Toda segunda-feira, o acumulado de 7 dias de drift ultrapassava o threshold de tolerância.

Usuários bloqueados. Help desk sobrecarregado. Time de DevOps no modo DETETIVE.

A solução foi simples, mas ninguém pensou nela antes:

  1. Sincronizar NTP com chronyd dentro do container, porque container sem NTP é uma bomba relógio
  2. Middleware de refresh com margem de 5 minutos antes da expiração, o token renovava antes de vencer, eliminando a janela de falha.
  3. Monitoramento de drift de relógio entre servidores — se a diferença passar de 1 minuto, alerta automático.

A moral da história?

Às vezes o bug não está no código. Está na infraestrutura que sustenta o código.

Nós revisamos o JWT, testamos a lógica de expiração, validamos o fluxo de refresh. Tudo parecia perfeito.

O problema estava em algo que ninguém olhou: o relógio do container.

Você já perdeu horas debugando algo que parecia código, mas era infraestrutura?

Feito!

quinta-feira, 13 de agosto de 2026

Você ainda programa como em 2023? A nova engenharia de agentes de IA em 2026

Durante muito tempo, falar sobre IA no desenvolvimento de software significava, principalmente, aprender a escrever bons prompts.

Você tinha um problema, descrevia o contexto para uma LLM, fazia algumas perguntas, copiava o código gerado, ajustava o que fosse necessário e seguia para a próxima tarefa.

Esse modelo ainda funciona.

Mas ele já não representa o estágio mais avançado do desenvolvimento assistido por IA.

Em 2026, a discussão mudou.

O diferencial não está mais apenas em saber conversar com uma LLM, mas em compreender como construir sistemas que utilizam modelos de linguagem de maneira estruturada, previsível e integrada ao ciclo de desenvolvimento.

É nesse contexto que começam a ganhar força conceitos como Graph Engineering, Loop Engineering, sistemas de memória, SDD (Spec Driven Development), MCP e arquiteturas de agentes.

A pergunta, portanto, deixou de ser:

"Qual prompt devo escrever?"

E passou a ser:

"Como devo projetar o sistema que utiliza a LLM?"

O fim da era do prompt simples

O prompt continua sendo importante.

Porém, ele é apenas uma camada de um sistema muito maior.

Uma aplicação real possui regras de negócio, arquitetura, padrões de código, banco de dados, autenticação, testes, observabilidade, requisitos não funcionais e dezenas ou centenas de arquivos.

Nesse cenário, um prompt isolado começa a perder eficiência.

O agente precisa saber:

Qual é a arquitetura do projeto?

Quais padrões devem ser utilizados?

Quais arquivos podem ser modificados?

Quais regras de negócio existem?

Quais ferramentas estão disponíveis?

Como validar o resultado?

O que já foi executado?

Quais decisões foram tomadas anteriormente?

Quando deve parar ou pedir intervenção humana?

Isso transforma o problema.

Não estamos mais falando simplesmente de Prompt Engineering.

Estamos entrando no território da Engineering for AI Agents.

De Prompt Engineering para System Engineering

O prompt continua sendo importante. Porém, ele é apenas uma camada de um sistema muito maior.

Um agente moderno pode ser representado conceitualmente como:

Contexto → Modelo → Ferramentas → Memória → Execução → Feedback → Validação → Novo ciclo

O desenvolvedor passa a projetar esse fluxo.

Por isso, uma habilidade importante para os próximos anos será entender como uma LLM participa de um sistema maior.

O profissional não precisa apenas saber pedir:

"Faça isso."

Ele precisa conseguir especificar:

"Este é o objetivo, estas são as restrições, estas são as ferramentas disponíveis, este é o contexto relevante, estes são os critérios de aceitação e este é o mecanismo utilizado para validar o resultado."

Essa diferença parece pequena.

Na prática, ela muda completamente a forma de trabalhar.

Graph Engineering: quando o agente deixa de seguir apenas uma sequência

Um dos conceitos mais importantes nessa evolução é pensar o agente como um grafo de execução.

Em uma abordagem simples, temos:

Prompt → LLM → Resposta

Em um sistema mais sofisticado:

Entrada → Análise → Planejamento → Ferramenta → Observação → Decisão → Nova ferramenta → Validação → Resultado

Agora existem diferentes estados e caminhos possíveis.

Por exemplo, imagine um agente responsável por implementar uma funcionalidade.

Ele pode analisar a especificação, identificar os componentes envolvidos, consultar o código existente, verificar as dependências, alterar os arquivos necessários, executar os testes, analisar falhas, corrigir a implementação e executar novamente até que os critérios sejam atendidos.

Isso é muito mais próximo de um grafo de execução do que de um simples chatbot.

O desenvolvedor passa a pensar em nós, estados, transições, condições e ferramentas.

A pergunta deixa de ser:

"Qual prompt funciona melhor?"

E passa a ser:

"Qual fluxo de execução produz um resultado confiável?"

Loop Engineering: o agente precisa saber iterar

Outro conceito importante é o Loop Engineering.

Uma LLM, sozinha, gera uma resposta.

Um agente precisa conseguir trabalhar em ciclos.

Um loop típico pode ser:

Planejar → Executar → Observar → Avaliar → Corrigir → Executar novamente

Por exemplo:


Especificação
↓
Planejamento
↓
Implementação
↓
Executar testes
↓
Passou?
↓
Sim → Finalizar
Não → Analisar erro → Corrigir → Executar novamente

Essa arquitetura aproxima o agente de um processo de engenharia.

O objetivo não é simplesmente gerar código.

É produzir um resultado verificável.

Isso também explica por que agentes capazes de executar ferramentas, rodar testes, consultar documentação e analisar resultados são significativamente mais interessantes do que sistemas que apenas geram texto.

Memória: o agente não pode depender apenas do contexto imediato

Outro problema surge quando começamos a trabalhar com tarefas maiores.

Uma conversa possui contexto limitado.

Mesmo que modelos modernos suportem janelas de contexto enormes, isso não significa que devemos simplesmente colocar tudo dentro do prompt.

Um sistema de agentes pode utilizar diferentes mecanismos de memória.

Podemos pensar, por exemplo, em:

Memória de curto prazo

Informações necessárias para a tarefa atual.

Memória de longo prazo

Conhecimentos e decisões persistentes entre diferentes sessões.

Memória operacional

Estado atual da execução do agente.

Memória semântica

Informações recuperadas por similaridade ou significado.

Memória episódica

Registro de experiências, decisões e resultados anteriores.

Isso aproxima a arquitetura de agentes de conceitos tradicionais de sistemas distribuídos, bancos de dados e sistemas cognitivos.

E novamente surge uma mudança de mentalidade.

O desenvolvedor não pergunta apenas:

"Qual informação devo colocar no prompt?"

Ele começa a perguntar:

"Qual informação precisa existir, onde será armazenada e em qual momento deve ser recuperada?"

RAG não é apenas um mecanismo de busca

O mesmo acontece com RAG.

Inicialmente, RAG foi apresentado de forma relativamente simples:

Documento → Embedding → Vector Database → Similarity Search → LLM

Mas aplicações reais exigem muito mais.

É necessário decidir o que será indexado, como os documentos serão fragmentados, quais metadados serão armazenados, como será feita a recuperação, quais filtros serão aplicados e como diferentes estratégias de busca serão combinadas.

Isso transforma RAG em um problema de arquitetura.

Mais uma vez, estamos saindo do simples prompt e entrando na engenharia do sistema.

SDD: especificação antes da implementação

Outro movimento importante é o Spec Driven Development (SDD).

A ideia central é deslocar parte do foco do desenvolvimento para a especificação explícita do que deve ser construído.

Em vez de simplesmente dizer:

"Crie um endpoint para usuários."

Podemos definir algo muito mais estruturado:

Objetivo:

Criar endpoint para cadastro de usuários.

Regras:

  • E-mail deve ser único.
  • Senha deve ser armazenada com hash.
  • Nome é obrigatório.
  • API deve retornar HTTP 201 após criação.

Critérios de aceitação:

  • Usuário válido pode ser criado.
  • E-mail duplicado deve ser rejeitado.
  • Dados inválidos devem retornar erro de validação.
  • Testes automatizados devem cobrir os cenários principais.

A diferença é enorme.

A especificação deixa de ser apenas documentação para humanos.

Ela pode se tornar contexto operacional para agentes.

O agente recebe uma especificação, interpreta os requisitos, modifica o projeto e utiliza os critérios de aceitação para verificar seu próprio trabalho.

Isso cria uma relação interessante:

Especificação → Agente → Implementação → Testes → Validação

O código passa a ser uma consequência da especificação.

MCP e a conexão dos agentes com o mundo real

Um agente também precisa interagir com sistemas externos.

Git, bancos de dados, sistemas internos, ferramentas de observabilidade, documentação, IDEs e outros serviços podem fazer parte do ambiente de desenvolvimento.

É nesse contexto que protocolos como o Model Context Protocol (MCP) ganham importância.

A ideia não é simplesmente fornecer mais contexto ao modelo.

É estabelecer uma forma padronizada para conectar modelos e agentes a ferramentas e fontes de contexto.

Isso pode transformar uma LLM de um sistema que apenas responde perguntas em um componente capaz de interagir com o ambiente.


LLM / Agente
├── Git
├── Banco de dados
├── Documentação
├── APIs
└── Ferramentas

O agente deixa de estar isolado.

Ele passa a operar dentro do ecossistema de desenvolvimento.

O novo papel do desenvolvedor

Tudo isso não significa que o desenvolvedor deixou de programar.

Na realidade, significa que algumas habilidades tradicionais continuam importantes enquanto outras passam a ganhar ainda mais relevância.

Software Engineering

Arquitetura, padrões, testes, qualidade, segurança e manutenção continuam fundamentais.

LLMs

É necessário entender conceitos como tokens, contexto, inferência, embeddings, temperatura, modelos e limitações.

Agent Engineering

É necessário compreender planejamento, ferramentas, loops, estados, memória e mecanismos de validação.

Context Engineering

É necessário saber fornecer ao modelo o contexto correto, no momento correto, sem simplesmente despejar informações.

Specification Engineering

É necessário transformar requisitos ambíguos em especificações claras e verificáveis.

Evaluation Engineering

É necessário medir se o agente realmente está produzindo resultados confiáveis.

Esse último ponto será especialmente importante.

Porque gerar uma resposta convincente não significa gerar uma resposta correta.

O problema dos agentes "mágicos"

Existe uma tendência de tratar agentes de IA como uma espécie de mágica.

Você fornece uma tarefa e espera que o agente resolva tudo.

Essa abordagem pode funcionar em demonstrações.

Em sistemas reais, ela é perigosa.

Um agente precisa de limites, permissões, observabilidade, validações, políticas de segurança, tratamento de erros, controle de custos, controle de contexto, mecanismos de recuperação e intervenção humana quando necessário.

Um agente sem arquitetura pode simplesmente automatizar o caos.

Por isso, quanto mais autônomo o sistema, mais importante se torna a engenharia por trás dele.

O desenvolvedor de 2026

Talvez a principal mudança esteja justamente aqui.

O desenvolvedor de 2026 não deveria ser definido como alguém que "sabe usar ChatGPT".

Isso é apenas uma pequena parte da competência.

Um profissional moderno precisa conseguir olhar para uma tarefa e identificar:

Qual parte é código?

Qual parte é especificação?

Qual parte é contexto?

Qual parte exige recuperação de conhecimento?

Qual parte pode ser delegada a um agente?

Qual parte precisa de validação automática?

Qual parte continua exigindo decisão humana?

Essa capacidade de decomposição provavelmente será mais valiosa do que simplesmente escrever prompts sofisticados.

Programar como em 2023 já não é suficiente

Em 2023, aprender a utilizar uma LLM já representava uma vantagem competitiva.

Em 2026, essa vantagem diminuiu.

O conhecimento está se tornando mais profundo.

Não basta saber conversar com o modelo.

É necessário saber projetar o sistema que conversa, executa, recupera informações, utiliza ferramentas, mantém estado, valida resultados e aprende com o próprio fluxo de execução.

A evolução pode ser resumida assim:


2023
Prompt Engineering
↓
2024
Context + RAG + Tools
↓
2025
Agents + MCP + Workflows
↓
2026
Graph Engineering
Loop Engineering
Memory Systems
Spec Driven Development
Evaluation Engineering
↓
Próxima etapa
AI-Native Software Engineering

Isso não significa que o prompt morreu.

Significa que ele deixou de ser o centro da arquitetura.

O prompt é apenas uma interface.

O verdadeiro diferencial está no sistema ao redor dele.

O futuro pertence a quem entende a arquitetura

A próxima geração de desenvolvedores não será formada apenas por pessoas capazes de escrever código rapidamente com auxílio de IA.

Será formada por profissionais capazes de projetar sistemas nos quais humanos, código, modelos, ferramentas, dados e agentes trabalham juntos.

Essa é uma mudança de paradigma.

A IA está deixando de ser apenas uma ferramenta de geração de código e começando a se tornar uma camada arquitetural do próprio processo de desenvolvimento.

Por isso, talvez a pergunta mais importante para um desenvolvedor em 2026 não seja:

"Você sabe usar IA para programar?"

Mas sim:

"Você sabe construir uma arquitetura na qual a IA consegue programar de forma controlada, verificável e contextualizada?"

Se a resposta ainda for não, talvez esteja na hora de ir além do prompt.

Porque a era de simplesmente conversar com a IA está dando lugar à era de engenheirar sistemas com IA.

Feito!

quarta-feira, 22 de julho de 2026

Harness e Loop Engineering: Por que eles importam mais que o LLM

Se você ainda está passando horas ajustando prompts individuais para que agentes de inteligência artificial escrevam código por você, é hora de mudar a sua abordagem. O verdadeiro diferencial das equipes de alto desempenho não está em encontrar o modelo de linguagem mais recente ou pagar pela API mais cara, mas sim em construir a infraestrutura ao redor dele.

"Você não devia mais estar promptando agentes de código; você devia estar desenhando loops que promptam seus agentes." Essa afirmação de Peter Stinberg, criador do OpenClaw, resume a grande virada de chave no desenvolvimento com IA.

Um exemplo impressionante desse paradigma vem da equipe da LangChain: ao manterem exatamente o mesmo modelo de IA com os mesmos pesos e alterar apenas a infraestrutura e as ferramentas ao redor (o chamado harness), eles saltaram de fora do top 30 para a 5ª posição em um benchmark global. Mas afinal, o que são esses conceitos e por que eles mudam tudo?

1. O que é Harness Engineering?

A palavra harness vem do inglês e refere-se ao arnês ou equipamento de segurança que conecta um cavaleiro ao cavalo, ou um alpinista à parede. No contexto do desenvolvimento com IA, o harness representa tudo o que não é o modelo em si.

Se o modelo de linguagem (LLM) é o motor do carro, o harness é todo o resto do veículo: o chassi, o volante, os freios e a transmissão. Na analogia de andaimes de construção, o harness é a estrutura temporária que molda e determina completamente como o prédio final será erguido.

Em suma, o harness engloba a gestão de contexto, a estrutura das instruções do sistema, as ferramentas fornecidas e os mecanismos de verificação e controle do agente.

2. A Matemática dos erros compostos

Por que o harness é tão crucial? Porque agentes de IA falham de maneira diferente do código imperativo tradicional. A grande ameaça na automação com IA é o acúmulo de etapas e a propagação de erros compostos.

Considere uma tarefa executada em múltiplos passos em sequência:

  • Se um processo possui 10 etapas e cada uma tem excelentes 99% de chance de sucesso, a probabilidade final de o processo dar certo é de 90,4%.
  • Com 20 etapas, a taxa de sucesso cai para 81,8%.
  • Com 50 etapas, a chance de sucesso despenca para apenas 60%.

Como os agentes realizam dezenas de iterações para resolver um problema complexo, pequenas incertezas se multiplicam rapidamente. A principal missão da engenharia de harness é conter essa degradação através de mecanismos defensivos.

Como o Harness combate os erros compostos:

  1. Mecanismos de Verificação: Dar ao agente ferramentas para testar o próprio trabalho antes de avançar. Dados oficiais do Claude Code mostram que a verificação autônoma melhora a qualidade do resultado final de 2 a 3 vezes.
  2. Checkpoints: Pontos de interrupção estratégicos onde o progresso é validado antes de liberar a próxima fase.
  3. Ferramentas Enxutas ("Menos é Mais"): A equipe da Vercel realizou um experimento onde seu agente apresentava mau desempenho. Em vez de adicionar mais capabilities, eles removeram 80% das ferramentas disponíveis. A performance subiu drasticamente porque a IA passou a ter menos oportunidades de escolher a opção errada.
  4. Limpeza do Contexto: Janelas de contexto poluídas com histórico irrelevante aumentam exponencialmente as chances de interpretação equivocada.

3. O que é Loop Engineering?

Se o harness é a estrutura do carro, o loop é o piloto automático. A engenharia de loop refere-se a como o agente executa tarefas autonomamente, rodando iterações sucessivas sem a necessidade de intervenção humana constante.

Essa abordagem ganhou tração com o conceito do Ralph Loop (criado por Geoffrey Huntley e batizado em homenagem a Ralph Wiggum dos Simpsons), que consiste em rodar o agente em um loop contínuo até que a tarefa seja concluída.

Os 4 Níveis de Loop (Classificação Anthropic):

  1. Nível 1 (Turn-based): O formato clássico. O humano envia um prompt a cada rodada e direciona a execução passo a passo.
  2. Nível 2 (Goal-based): Você fornece uma condição de parada objetiva (ex: "rode até todos os testes passarem no terminal" ou "rode até o build compilar"). O agente não para quando *acha* que terminou, mas sim quando o objetivo é verificado.
  3. Nível 3 (Time-based): Execuções agendadas ou disparadas por gatilhos de tempo no ambiente, sem você estar presente.
  4. Nível 4 (Proactive): O sistema monitora ativamente o ambiente e decide por conta própria o que e quando executar.

Atenção: Criar um loop sem um critério de sucesso objetivo não é engenharia; é apenas um agente queimando tokens e gastando orçamento de API. O verdadeiro gargalo do loop não é o modelo de IA, mas a capacidade do seu verificador.

4. Os 7 Componentes Essenciais de um Harness Robusto

Para construir uma estrutura pronta para rodar em loop, seu harness deve incluir:

  • System Prompt / Constituição: As diretrizes invioláveis, limitações e convenções do projeto.
  • Ferramentas Selecionadas: Funções estritamente necessárias para evitar ambiguidades.
  • Gestão de Janela de Contexto: Decisão consciente do que incluir e descartar no histórico.
  • Mecanismos de Verificação: Executores de testes unitários, linters e validadores de código.
  • Memória Persistente: Registro de aprendizados entre sessões para evitar a repetição de erros.
  • Sandboxes: Ambientes isolados para rodar códigos e chamadas de API em segurança.
  • Hooks de Intervenção: Padrões que acionam revisões automáticas ou humanas em cenários críticos.

5. Como aplicar isso no seu dia a dia Dev

Você provavelmente já pratica engenharia de harness sem saber. Para otimizar seu fluxo de trabalho com agentes de IA, conecte-os às boas práticas de engenharia de software:

  • Arquivos de Convenção (ex: CLAUDE.md ou AGENTS.md): Mantenha um arquivo na raiz do repositório detalhando padrões de arquitetura e convenções do projeto. Isso serve como o system prompt vivo do projeto.
  • Spec-driven Development: Separe rigorosamente a fase de planejamento da fase de execução. Escreva e aprove a especificação antes de pedir para a IA codificar.
  • TDD (Test-Driven Development): Escrever testes antes da implementação provê tanto a verificação quanto a condição de parada perfeita para loops do Nível 2 (goal-based).

4 perguntas para fazer antes de trocar de LLM

Quando seu agente falhar em uma tarefa, evite trocar imediatamente para um modelo mais caro. Em vez disso, faça o seguinte diagnóstico:

  1. Onde o agente está falhando? Falhas de entendimento indicam problemas no system prompt; falhas de execução indicam problemas nas ferramentas/sandbox; erros acumulados pedem verificadores melhores.
  2. O agente possui meios de checar seu próprio trabalho? Se não, adicione suítes de testes ou linters.
  3. Qual contexto essencial está na sua cabeça, mas não foi documentado no repositório?
  4. Qual tarefa do seu projeto possui critério de sucesso 100% objetivo para ser seu primeiro loop autônomo?

Investir no seu harness traz retornos muito maiores do que simplesmente tentar usar modelos maiores. Construa a estrutura correta e veja seus agentes atingirem um novo nível de autonomia e precisão.

Feito!

sexta-feira, 17 de julho de 2026

Como sobreviver à "Inflação dos Tokens" com uma estrutura híbrida e local

Se você acompanha o mercado de tecnologia, certamente percebeu o burburinho recente. O lançamento de supermodelos como o Claude Fable 5 (derivado da poderosa e restrita família Mythos da Anthropic) trouxe um balde de água fria para a comunidade de desenvolvimento: o fim das assinaturas com uso ilimitado.

A era em que usávamos modelos de inteligência artificial de ponta de forma indiscriminada por uma taxa fixa mensal está chegando ao fim. O plano fixo virou um verdadeiro "taxímetro" de créditos e consumo real de tokens.

Mas por que isso aconteceu? E, mais importante, como nós, desenvolvedores e arquitetos de software, podemos nos adaptar a essa nova realidade sem ir à falência?

O Paradoxo da Memória: LLMs vs. Humanos

Para entender o limite dos LLMs, precisamos primeiro desmistificar o que eles são. Existe uma analogia fantástica para isso: a limitação de um LLM é muito parecida com a limitação da mente humana.

Pense bem. Um humano estuda durante anos, lê centenas de livros, faz cursos e consome horas de conteúdo de diversos assuntos. O aprendizado é eterno; sempre haverá algo que ainda não sabemos e precisamos continuar estudando. Porém, por mais inteligente que um profissional seja, ele tem uma capacidade de atenção limitada no momento presente (sua memória de trabalho). Se você lhe entregar um relatório de 1.000 páginas e exigir que ele correlacione instantaneamente uma linha da página 2 com outra da página 900, ele vai falhar ou demorar muito.

O mesmo se aplica aos LLMs:

Memória de Longo Prazo (Treinamento): O modelo foi treinado com bilhões de parâmetros de diversos assuntos. O conhecimento estático está lá.

Memória de Curto Prazo (Janela de Contexto): Na hora de resolver um problema na IDE, o modelo precisa carregar as informações na "janela de contexto". Encher o prompt de dados desnecessários gera sobrecarga cognitiva na IA (alucinações) e, principalmente, consome tokens de forma brutal.

Com as empresas de IA repassando o custo real de infraestrutura para o usuário, carregar contextos gigantescos em modelos proprietários caros tornou-se insustentável. A contabilidade bateu na porta do desenvolvimento de software.

A Rota de Fuga: IA Open Source e Execução Local

Se a "inflação de tokens" encareceu as APIs de nuvem, a comunidade Open Source nos deu a resposta perfeita: rodar modelos menores localmente para tarefas do dia a dia.

Hoje, máquinas comuns de desenvolvimento conseguem rodar com extrema facilidade e fluidez modelos eficientes de até 7B ou 8B parâmetros, como o recente Gemma 4 (Google) ou o Llama 3 (Meta).

Montar um ecossistema de IA local e totalmente gratuito é extremamente simples com três ferramentas:

Ollama (O Motor): Gerencia e executa seus LLMs locais em segundo plano de forma leve e rápida no sistema operacional.

Open WebUI (A Interface): Uma interface web fantástica, idêntica ao ChatGPT, que roda localmente. Ela permite gerenciar conversas, criar prompts do sistema e até fazer RAG (conversar com seus arquivos e PDF locais).

Continue.dev (A Integração na IDE): Uma extensão de código aberto para o VS Code que se conecta diretamente ao seu Ollama local. Ela atua como seu copiloto na geração de código, autocomplete e explicações, direto no editor.

Estratégia Híbrida: Mapeando suas Tarefas para Economizar

Para não ter que abrir mão do poder de modelos gigantescos (como o Claude Fable 5 ou o GPT-4o) quando eles forem realmente necessários, a melhor prática de engenharia é adotar uma abordagem híbrida.

Divida suas tarefas diárias com base no custo computacional e de raciocínio necessário utilizando a tabela de referência abaixo:

Complexidade Exemplo de Tarefa Modelo Recomendado Onde Rodar Custo por Token
Baixa Autocomplete de sintaxe, formatação de arquivos JSON, geração de documentação de métodos (Docstrings), refatoração simples de funções. Gemma 4 2B / 4B ou Qwen 2.5 3B Local (Ollama + VS Code) Zero (Custo Local)
Média Explicação de trechos de arquitetura de código, debug de erros comuns de runtime, geração de testes unitários com base em regras bem definidas. Gemma 4 12B ou Llama 3.1 8B Local ou API de baixo custo Extremamente baixo
Alta Arquitetura de microsserviços do zero, refatorações profundas aplicando Clean Architecture e SOLID, resolução de bugs complexos de concorrência ou segurança. Claude Fable 5 ou GPT-4o API comercial em nuvem Pago por uso (Taxímetro)

Considerações finais:

O Dev Consciente é o Novo Tech Lead da IA

O "fim do hype" não é um retrocesso; é um amadurecimento saudável do mercado de tecnologia. A ferramenta de IA deixou de ser uma "mágica de uso infinito" para se tornar um recurso de engenharia gerenciável, com custos, limites e arquitetura apropriada.

Como desenvolvedores, nossa missão agora é sermos inteligentes no uso da ferramenta de IA. Ao dominar o ecossistema local com ferramentas como o Ollama e utilizá-lo para 80% do nosso fluxo de trabalho básico, economizamos recursos preciosos para acionar a "artilharia pesada" da nuvem somente quando o desafio realmente exigir.

E você, já montou o seu ecossistema de IA local ou ainda está sofrendo com as contas das APIs na nuvem? Deixe sua experiência nos comentários!

Feito!

quarta-feira, 15 de julho de 2026

Isolamento de Ambientes no Python: Venv vs. Conda Qual escolher?

Se você já passou pela clássica frustração do "na minha máquina funciona, mas no servidor quebrou" ou acabou corrompendo as dependências globais do seu sistema operacional ao instalar uma biblioteca externa, parabéns: você descobriu a necessidade vital dos ambientes virtuais.

No ecossistema Python, duas ferramentas dominam essa arena de isolamento de dependências: o venv (nativo do Python) e o conda (proveniente da distribuição Anaconda/Miniconda). Embora ambos resolvam com primor o problema de isolar bibliotecas, eles operam de maneiras fundamentalmente diferentes sob o capô.

O que é o venv?

O venv é o gerenciador de ambientes virtuais padrão e nativo do Python, disponível nativamente a partir da versão 3.3. Ele foi desenhado com um propósito simples e focado: criar ambientes isolados para projetos Python, utilizando como base a instalação do interpretador Python que já existe de forma global no seu sistema operacional.

Como ele funciona?

Ao inicializar um ambiente usando o comando python -m venv meu_ambiente, ele gera um diretório local que contém cópias e links simbólicos que apontam para o executável do Python do seu sistema. Ao ativar esse ambiente e executar o pip install, os pacotes e suas respectivas versões são instalados isoladamente nesta pasta, sem qualquer interferência com dependências globais ou outros projetos.

O que é o conda?

O conda é um gerenciador de ambientes e também de pacotes multiplataforma de código aberto. Ao contrário do venv (que gerencia estritamente pacotes Python), o conda é agnóstico de linguagem de programação. Ele foi originalmente idealizado pela comunidade de Ciência de Dados, onde os projetos frequentemente demandam dependências complexas e binários de baixo nível written em C, C++, Fortran ou integrações com drivers de GPU.

Criando ambiente virtual no Conda

Exemplo para criar um ambiente virtual no Conda no Python 3.13

conda create --name meu_ambiente python=3.13

Pode instalar as libs junto com a criação do ambiente (Opcional)

conda create --name meu_ambiente python=3.13 numpy pandas scikit-learn

Vantagem: O gerenciador do Conda analisa a compatibilidade de todas as bibliotecas de uma vez só antes de baixar. Ele também instala binários pré-compilados e otimizados para o seu sistema operacional (como otimizações de performance da Intel para o NumPy, por exemplo).

Mas também pode instalar as libs dentro do ambiente virtual com pip

Regra de Ouro (Apenas um cuidado)

Se você optar por instalar depois com o pip, certifique-se sempre de ativar o ambiente primeiro (conda activate meu_ambiente). Se esquecer de ativar, o pip vai instalar Se você optar por instalar depois com o pip, certifique-se sempre de ativar o ambiente primeiro (conda activate meu_ambiente). Se esquecer de ativar, o pip vai instalar

conda activate meu_ambiente

pip install numpy pandas scikit-learn

Desativar o ambiente virtual conda deactivate

Como ele funciona?

Diferente do seu concorrente nativo, o conda não depende de um interpretador Python pré-instalado no sistema. Ele é capaz de baixar e instalar diferentes versões do próprio Python diretamente em cada ambiente de forma totalmente isolada. Ele gerencia binários pré-compilados diretamente de canais de distribuição (como o conda-forge), resolvendo conflitos a nível de sistema operacional.

Tabela Comparativa: Venv x Conda

Característica venv (nativo) conda (gerenciador global)
Instalação Já vem pré-instalado por padrão junto ao Python. Requer a instalação prévia do Anaconda ou do Miniconda.
Escopo de Pacotes Gerencia exclusivamente pacotes Python via indexador PyPI. Gerencia pacotes de qualquer linguagem (Python, C, R, CUDA, etc).
Versão do Python Usa obrigatoriamente a versão do sistema operacional base. Permite instalar e isolar qualquer versão do Python por ambiente.
Velocidade de Instalação Rápida, mas pode gerar conflitos silenciosos de pacotes. Mais lenta devido à rigorosa análise de resolução de dependências.
Armazenamento (Disco) Extremamente leve e enxuto. Moderado a pesado devido ao cache e compilação de binários.

Vantagens e Desvantagens

O clássico venv

Vantagens:
- Sem fricção de configuração: Não necessita de instaladores adicionais. Se você possui o Python na máquina, você já possui o venv pronto para uso.
- Alta eficiência de armazenamento: Os ambientes ocupam pouquíssimo espaço antes da instalação de novas bibliotecas.
- Padrão consolidado no desenvolvimento Web: Excelente para microsserviços, APIs (FastAPI, Flask) e deploys simplificados em containers Docker.

Desvantagens:
- Acoplado ao sistema: Dificulta o teste simultâneo de múltiplos interpretadores de Python sem o auxílio de ferramentas acessórias como o pyenv.
- Dependências não-Python: Falha em resolver dependências que exijam compilações complexas de bibliotecas de sistema C/C++ diretamente na máquina do usuário final.

O canivete suíço conda

Vantagens:
- Isolamento de baixo nível: Perfeito para gerenciar bibliotecas científicas complexas (NumPy, SciPy, TensorFlow) que dependem de otimizações de hardware.
- Portabilidade total: Garante que os pacotes binários de sistema funcionarão de forma idêntica em Windows, Linux ou macOS.
- Flexibilidade de interpretador: Criar um ambiente com Python 3.8 e outro com 3.12 é simples como executar conda create -n env python=3.12.

Desvantagens:
- Overhead de disco: Os binários ocupam consideravelmente mais armazenamento em disco.
- Complexidade extra: Para desenvolvimento de aplicações web convencionais e scripts leves de automação, seu ecossistema pode ser desnecessariamente robusto.

Dica Prática de Engenharia de Software:

Utilize o venv sempre que o deploy final do seu software for baseado em containers Docker enxutos e focados em microserviços Web tradicionais. Reserve o uso do conda para fluxos de trabalho que exijam engenharia de dados, machine learning ou computação científica de alto desempenho.

Referências

https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html

Feito!

segunda-feira, 13 de julho de 2026

Upload de arquivos no desenvolvimento de software do jeito certo

Para quem está de fora ou mesmo para desenvolvedores que estão iniciando na carreira, a funcionalidade de upload de arquivos parece uma das tarefas mais simples e triviais do desenvolvimento de software. A experiência do usuário moderno é quase mágica: basta arrastar uma foto de perfil ou um vídeo pesado para uma caixinha na tela, e o navegador faz o resto. No entanto, por trás dessa interface amigável e minimalista, esconde-se uma complexidade arquitetural gigantesca.

Se você lida com o desenvolvimento de sistemas escaláveis, sabe que tratar o upload de arquivos simplesmente como um POST tradicional que recebe um binário e o cospe em um diretório ou banco de dados é uma receita certa para o desastre. Neste artigo, vamos explorar por que essa abordagem falha, as dores do crescimento de uma infraestrutura e como desenhar uma arquitetura robusta inspirada nos padrões de grandes players de tecnologia.

O perigo da abordagem tradicional: Banco de Dados e diretórios locais

Quando começamos a construir uma aplicação monolítica rodando em um único servidor, a solução mais óbvia e simples é criar um endpoint clássico (como um POST /upload/foto), capturar o arquivo na aplicação e tomar uma de duas decisões:

  1. Salvar o binário diretamente no banco de dados: Utilizando tipos como BLOB (Binary Large Object) ou BYTEA.
  2. Salvar em um diretório local protegido: Armazenar o arquivo fisicamente no sistema de arquivos do próprio servidor que roda a aplicação, guardando apenas o caminho relativo no banco.

Embora a segunda opção seja muito superior à primeira por manter o banco de dados limpo, ambas esbarram em limites severos quando o sistema começa a escalar:

  • Saturação do Banco de Dados: Salvar arquivos pesados direto no banco destrói a performance das consultas, infla o tamanho dos backups rapidamente e inviabiliza a aplicação mesmo sob tráfego moderado. Banco de dados foi feito para dados relacionais e transacionais, não para mídia.
  • O Gargalo da Escalabilidade Horizontal (Stateless): Se sua aplicação crescer e você precisar subir múltiplas instâncias do seu backend atrás de um Load Balancer (balanceador de carga), o diretório local se torna um problema de estado. Se o usuário faz o upload de uma imagem que cai no Servidor A, quando ele tentar visualizar o arquivo e a requisição cair no Servidor B, o arquivo simplesmente não estará lá.
  • Consumo de Recursos de I/O e Banda: Processar leitura e escrita de gigabytes de dados diretamente no seu servidor de aplicação consome processamento (CPU), memória e largura de banda preciosos, impedindo que o servidor responda rapidamente a requisições HTTP leves e normais de outros usuários.

Pilares de uma arquitetura de Upload moderna e escalável

Para desatar esses nós e permitir que seu sistema suporte o upload de arquivos gigantescos, como vídeos de dezenas de gigabytes, sem derrubar a infraestrutura, o ecossistema moderno adota padrões consolidados de System Design. Abaixo estão os conceitos fundamentais para mudar o patamar da sua aplicação:

1. Divisão em pedaços (Chunking) e validação de integridade (Checksums)

Arquivos imensos não se comportam bem em conexões de rede instáveis. Em redes móveis ou conexões lentas, transmitir um arquivo único de 5 GB é inviável: se a rede oscilar nos 95%, todo o progresso é perdido. A solução para isso é o Chunking: o cliente divide o arquivo em dezenas de pedaços menores (ex: 50 blocos de 100 MB) antes do envio.

Aliado a isso, utilizamos o Checksum. O checksum funciona como uma "impressão digital" matemática calculada com base nos bits do arquivo. Com ele, o servidor consegue verificar se o arquivo não foi corrompido durante a transmissão e, em caso de interrupção, o sistema sabe exatamente quais pedaços (chunks) faltam receber para retomar o upload exatamente de onde parou, garantindo segurança contra fraudes na retomada do arquivo.

2. Desacoplamento total com Object Storage (Blob Store)

Na engenharia de software moderna, as instâncias de backend devem ser o mais stateless (sem estado) possível. Os dados transacionais e metadados (como o ID do usuário, tamanho do arquivo, tipo de mídia e status do processamento) continuam indo para o seu banco de dados relacional (ex: PostgreSQL). No entanto, o arquivo binário em si é direcionado para um serviço especialista em armazenamento de objetos grandes, amplamente conhecidos como Blob Stores, tais como o AWS S3, o Google Cloud Storage ou o Cloudflare R2.

3. Upload direto via presigned URLs (URLs Pré-Assinadas)

Se enviarmos o arquivo para a Blob Store fazendo-o passar por dentro do nosso servidor, ainda estaremos sofrendo com o gargalo de banda de rede e processamento. Para eliminar esse intermediário, o backend atua apenas como um orquestrador de segurança:

  • O cliente avisa ao backend que deseja realizar o upload de um arquivo e envia os metadados.
  • O backend valida se o usuário tem permissão, faz as checagens de segurança e solicita ao provedor de storage uma Presigned URL (uma URL temporária e autenticada com chaves criptográficas embutidas).
  • O backend devolve essa URL para o cliente, e o navegador faz o upload do arquivo binário pesado diretamente para o storage na nuvem, sem consumir um único bit de banda do seu servidor principal.

4. Processamento assíncrono com background Jobs

O fluxo de vida do arquivo não termina quando o upload é concluído. Sistemas profissionais utilizam filas de mensageria e workers em segundo plano para realizar processamentos necessários de forma assíncrona:

  • Transcodificação e Compressão: No caso de vídeos, comprimir e gerar arquivos em diferentes resoluções (480p, 720p, 1080p). No caso de imagens, redimensionar ou otimizar para formatos mais leves no cliente ou no backend.
  • Varredura Antivírus (Malware Scan): Nunca confie no arquivo enviado pelo usuário. Rotinas em segundo plano devem escanear o arquivo em busca de ameaças antes de marcá-lo como "pronto" no banco de dados.
  • Rotinas de Limpeza (Clean-up Jobs): Se um usuário iniciar um upload em pedaços e abandonar o processo no meio do caminho, esses blocos órfãos consumirão espaço e custo. Jobs agendados limpam periodicamente uploads inacabados.

A revolução dos custos: O fator Cloudflare R2

Embora AWS S3 e Google Cloud Storage dominem amplamente o mercado corporativo, um grande divisor de águas recente na arquitetura de mídias é o Cloudflare R2. O modelo tradicional de nuvem cobra pelo armazenamento (por GB guardado) e pelas chamadas de API, mas impõe taxas pesadas sobre o egresso de dados (data egress fees), ou seja, você paga caro por cada gigabyte que sai do storage para ser consumido pelos seus usuários na internet.

O R2 rompeu esse modelo ao eliminar totalmente as taxas de egresso. Para aplicações de alta intensidade de leitura, como plataformas de streaming, blogs com muitas imagens ou distribuição de software, essa mudança arquitetural reduz custos drasticamente e permite uma integração nativa e veloz com redes de entrega de conteúdo (CDNs).

Considerações finais

Migrar o modelo mental de salvar arquivos localmente em diretórios ocultos do servidor para uma infraestrutura distribuída com URLs Pré-Assinadas e Object Stores é o verdadeiro passo que separa aplicações amadoras de sistemas resilientes e prontos para produção em larga escala. Ao desonerar seu backend do tráfego pesado e delegar o armazenamento para serviços especialistas, você garante que sua aplicação possa escalar horizontalmente de forma infinita, segura e financeiramente sustentável.

Feito!

quinta-feira, 2 de julho de 2026

Blindando o servidor SSH na VPS e EC2 contra bots

Você acabou de criar uma VPS ou uma instância EC2 na AWS. Ainda nem configurou direito o servidor e, pasme, já existem bots tentando invadir. Não é exagero. Em menos de 15 minutos após ligar uma máquina na nuvem, os primeiros acessos suspeitos começam a aparecer no log do SSH.

Bots varrem a internet o tempo todo. Eles testam combinações de root, ubuntu, admin, debian com senhas fracas na esperança de encontrar uma porta aberta e mal configurada. Se você criar uma instância Ubuntu na EC2, o nome de usuário padrão é ubuntu, e os bots sabem disso. Se for um Debian, tentam admin ou debian. Eles têm listas, e elas são enormes.

A boa notícia? Com 5 configurações básicas você reduz quase que totalmente o risco de acesso indevido. Vamos a elas.

As 5 camadas de proteção

  1. Criar um usuário administrador: nunca use o usuário padrão da distro.
  2. Autenticação por chave SSH: sem senha, sem risco de força bruta.
  3. Desabilitar login como root: o alvo favorito dos bots.
  4. Desabilitar login por senha: se não aceita senha, não adianta chutar.
  5. Firewall + Fail2Ban: bloqueia quem insiste.

Antes de começar: EC2 × VPS

Se for EC2 (AWS): Quando você cria a instância EC2 na AWS já gera um par de chaves (pública/privada) no console ou via AWS CLI no momento da criação da instância. Você não precisa gerar uma nova chave, mas precisa pular a etapa de gerar e copiar a chave. As demais configurações (criar usuário, desabilitar root, firewall, fail2ban) ainda são necessárias.
Se for VPS: você vai precisar gerar a chave SSH manualmente, copiá-la para o servidor e configurar tudo do zero. O artigo cobre os dois cenários.

1. Atualizar o sistema

Sempre comece com o sistema atualizado. Pacotes desatualizados podem conter brechas conhecidas.

apt update
apt upgrade -y

2. Criar um usuário administrador

O nome de usuário padrão da sua distro (ubuntu, admin, debian etc.) é público. Os bots sabem qual é. Por isso a primeira coisa é criar um usuário só seu, com um nome que só você conhece.

adduser seu-usuario
usermod -aG sudo seu-usuario

Teste se o grupo sudo foi atribuído corretamente:

groups seu-usuario

Se aparecer sudo na lista, seu usuário tem privilégios administrativos. ✅

3. Gerar e configurar chave SSH

A chave SSH é como uma chave de casa: muito mais segura que uma senha. Enquanto senhas podem ser chutadas ou descobertas, a chave criptográfica é praticamente impossível de forjar.

🔹 Gerar a chave (Windows, Linux, macOS)

ssh-keygen -t ed25519 -C "seu-email@exemplo.com"

O comando acima cria um par de chaves usando o algoritmo Ed25519 (moderno, rápido e seguro). Você pode escolher onde salvar, o padrão ~/.ssh/id_ed25519 funciona bem.

Visualizar a chave pública (Linux e macOS)

cat ~/.ssh/id_ed25519.pub

Copie o texto que aparece. É a sua chave pública — pode compartilhá-la. A privada (id_ed25519 sem .pub) jamais deve sair da sua máquina.

Copiar a chave para o servidor (VPS)

Se for uma VPS comum, use o atalho:

ssh-copy-id -i ~/.ssh/nome-da-chave.pub seu-usuario@IP_DO_SERVIDOR

Esse comando instala sua chave pública no arquivo ~/.ssh/authorized_keys do servidor, e você já consegue conectar sem digitar senha.

Conectar ao servidor

ssh seu-usuario@IP_DO_SERVIDOR

Se tudo deu certo, você entra direto, sem pedir senha. 🎉

4. Endurecer a configuração do SSH

Agora vamos ajustar o coração da segurança: o arquivo de configuração do servidor SSH.

sudo nano /etc/ssh/sshd_config

Altere ou adicione as seguintes linhas:

# Desabilita login como root (os bots adoram tentar root)
PermitRootLogin no

# Permite autenticação por chave (é o que você acabou de configurar)
PubkeyAuthentication yes

# Desabilita login por senha (força bruta depende de senha)
PasswordAuthentication no

# Desabilita interação com senha (camada extra)
KbdInteractiveAuthentication no

# Opcional: alterar a porta SSH (fugir do padrão 22)
Port 2222
💡 Atenção para EC2 e VPS: em instâncias Ubuntu da AWS e VPS, existe o arquivo /etc/ssh/sshd_config.d/50-cloud-init.conf que sobrescreve as configurações do sshd_config. Você precisa editar também esse arquivo:
sudo nano /etc/ssh/sshd_config.d/50-cloud-init.conf

E adicionar:

PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes

Depois de salvar, reinicie o serviço SSH:

sudo systemctl restart ssh

Pronto. A partir de agora, não é mais possível fazer login com root ou com senha. Só entra quem tem a chave privada correta.

5. Firewall com UFW

O UFW (Uncomplicated Firewall) é um firewall simples e direto. Vamos liberar apenas o essencial.

sudo apt install ufw -y

# Bloquear toda conexão que entra (ninguém de fora se conecta sem sua autorização)
sudo ufw default deny incoming

# Liberar toda conexão que sai (você pode baixar pacotes, acessar sites etc.)
sudo ufw default allow outgoing

# Liberar SSH (porta padrão 22)
sudo ufw allow 22/tcp

# Se você alterou a porta SSH, libere a nova porta substituindo pela 22

# Liberar HTTP e HTTPS (para sites e APIs)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Ativar o firewall
sudo ufw enable

Verifique as regras ativas:

sudo ufw status

O UFW agora funciona na seguinte lógica: tudo que chega do exterior é bloqueado por padrão, a menos que você explicitamente libere (como fez com SSH, HTTP e HTTPS). Já tudo que sai do servidor é permitido, você consegue fazer atualizações, acessar APIs, baixar pacotes, tudo normal.

É o princípio do menor privilégio aplicado à rede: nada de fora entra sem permissão, mas o servidor pode se comunicar livremente com o mundo.

6. Fail2Ban o segurança do SSH

O Fail2Ban monitora os logs do sistema e bloqueia temporariamente (por meio do firewall) IPs que fazem muitas tentativas de login com falha. É como um segurança na porta da balada: "já errou a senha 5 vezes? Pode ir embora."

sudo apt install fail2ban -y

# Habilitar para iniciar com o sistema
sudo systemctl enable fail2ban

# Iniciar agora
sudo systemctl start fail2ban

# Verificar se está rodando

sudo systemctl status fail2ban

7. (Bônus) Atualizações automáticas de segurança

Manter o sistema atualizado é fundamental. As atualizações automáticas instalam correções de segurança sem você precisar lembrar.

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure unattended-upgrades

Na tela que aparecer, selecione Sim.

Facilitando a conexão: o arquivo de configuração do SSH

Digitar ssh usuario@IP -p 2222 toda vez é chato. Crie um atalho no arquivo ~/.ssh/config da sua máquina local:

nano ~/.ssh/config

Adicione algo como:

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa
    IdentitiesOnly yes

Host vps_ou_ec2
    HostName IP_DA_SUA_VPS
    User seu-usuario
    IdentityFile ~/.ssh/id_ed25519
    Port 2222
    ServerAliveInterval 60
    ServerAliveCountMax 3

Agora, para conectar, basta digitar:

ssh vps_ou_ec2

E para testar a conexão com GitHub:

ssh -T git@github.com

Se tudo estiver certo, o GitHub responde algo como:

Hi seu-usuario! You've successfully authenticated, but GitHub does not provide shell access.

Investigando: como ver quem está tentando entrar

Quer ver os bots em ação? Esses comandos mostram em tempo real as tentativas de acesso no seu servidor:

# Ver tentativas de login em tempo real
sudo tail -f /var/log/auth.log

# Ver bloqueios do Fail2Ban
sudo tail -f /var/log/fail2ban.log

# Status detalhado do Fail2Ban para o SSH
sudo fail2ban-client status sshd

O log do auth.log vai mostrar dezenas (ou centenas) de tentativas de login vindo de IPs do mundo inteiro. O fail2ban.log vai mostrar os IPs que foram bloqueados. É assustador e ao mesmo tempo satisfatório saber que o Fail2Ban está fazendo o trabalho dele.

Testando a blindagem

Depois de aplicar todas as configurações, é hora de confirmar que está tudo funcionando. O teste é simples: tente conectar sem usar a chave SSH.

Na sua máquina local, tente conectar como root:

ssh root@IP_DO_SERVIDOR

Você deve receber algo como:

root@IP_DO_SERVIDOR: Permission denied (publickey).

Agora tente com o usuário que você criou, também sem informar a chave:

ssh seu-usuario@IP_DO_SERVIDOR

O resultado é o mesmo:

seu-usuario@IP_DO_SERVIDOR: Permission denied (publickey).
✅ Isso é bom! A mensagem Permission denied (publickey) significa que o servidor rejeitou a conexão porque você não apresentou uma chave válida. O servidor nem sequer pediu senha, porque a autenticação por senha está desabilitada. Exatamente o que queremos.

Agora faça o teste com a chave para confirmar que o acesso legítimo continua funcionando:

ssh -i ~/.ssh/sua-chave.pub seu-usuario@IP_DO_SERVIDOR

Se entrou sem pedir nada, parabéns! 🎉 Sua VPS ou EC2 está blindada contra bots, força bruta e hackers metidos a cracker.

Recapitulando

Com esses passos, seu servidor passa de "porta escancarada" para "cofre blindado". Veja o resumo:

Configuração Protege contra
Usuário personalizado Bots que tentam nomes de usuário padrão
Chave SSH Força bruta de senha
Root desabilitado Ataques direcionados ao root
Senha desabilitada Qualquer ataque baseado em senha
UFW + Fail2Ban Varreduras e múltiplas tentativas

Considerações finais

Configurar segurança no SSH não é frescura, é responsabilidade de quem coloca um servidor na internet. Os bots não dormem. Enquanto você lê este artigo, centenas de scripts automatizados estão escaneando IPs atrás de uma porta 22 aberta com PermitRootLogin yes e senha fraca.

Gaste 15 minutos aplicando essas configurações. Sua VPS/EC2 com seus dados, agradecem.

Feito!