<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Kristyan Carvalho</title><description>Pensamentos e notas pessoais sobre código, tecnologia e tudo mais.</description><link>https://blog.kristyan.dev</link><language>pt-BR</language><lastBuildDate>Tue, 14 Jul 2026 04:00:00 GMT</lastBuildDate><pubDate>Tue, 14 Jul 2026 04:00:00 GMT</pubDate><ttl>60</ttl><generator>Astro</generator><atom:link href="https://blog.kristyan.dev/rss.xml" rel="self" type="application/rss+xml"/><item><title>Da intenção ao binário: como um compilador faz o código conversar com a máquina</title><link>https://blog.kristyan.dev/posts/arquitetura-de-compiladores</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/arquitetura-de-compiladores</guid><description>Uma caminhada pelos bastidores do compilador, do primeiro token até o binário que o sistema operacional carrega na memória.</description><pubDate>Tue, 14 Jul 2026 04:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Compilador é uma daquelas peças de software que ficam no caminho de todo desenvolvedor, mas quase sempre passam invisíveis.&lt;/p&gt;
&lt;p&gt;Você escreve &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;struct&lt;/code&gt;, &lt;code&gt;class&lt;/code&gt;, &lt;code&gt;fn&lt;/code&gt;, &lt;code&gt;match&lt;/code&gt;, &lt;code&gt;async&lt;/code&gt;, roda um comando e espera que algo coerente saia do outro lado. Se der certo, aparece um binário, bytecode, JavaScript transpilado, WebAssembly, assembly ou alguma representação que outra ferramenta ainda vai mastigar. Se der errado, aparece uma mensagem dizendo que você esqueceu um &lt;code&gt;;&lt;/code&gt;, violou uma regra de tipos, usou uma variável fora do escopo ou tentou convencer a linguagem de que um texto e um inteiro deveriam se casar.&lt;/p&gt;
&lt;p&gt;A parte curiosa é que essa caixa preta não é magia. É uma linha de produção bem organizada, cheia de decisões históricas, teoria formal e muita engenharia pragmática.&lt;/p&gt;
&lt;p&gt;Compiladores existem porque computadores não executam intenção. Eles executam instruções. Entre a ideia que você escreve e a sequência de operações que a CPU entende existe um abismo enorme. O compilador é a ponte sobre esse abismo e, em muitos casos, também é quem avisa que a travessia não faz sentido.&lt;/p&gt;
&lt;p&gt;Este texto reorganiza minhas anotações de estudo em uma caminhada completa: de onde vieram os compiladores, por que eles existem, como leem código, como constroem árvores, como verificam significado, como geram representações intermediárias, como otimizam, como emitem código de máquina e como o programa finalmente vira processo em execução.&lt;/p&gt;
&lt;h2&gt;Compilador nasceu de uma dor bem prática&lt;/h2&gt;
&lt;p&gt;Compiladores não surgiram porque alguém queria escrever um livro difícil. Eles surgiram porque programar diretamente em linguagem de máquina era um castigo.&lt;/p&gt;
&lt;p&gt;Nos primeiros computadores, escrever software significava lidar com códigos numéricos, endereços e detalhes físicos da máquina. Assembly já foi um salto enorme porque deu nomes simbólicos a instruções e endereços. Mas assembly ainda prende o programador à arquitetura. Você continua pensando no idioma da CPU.&lt;/p&gt;
&lt;p&gt;O passo seguinte foi escrever em uma linguagem mais próxima do problema e deixar uma ferramenta fazer a tradução. O FORTRAN, criado na IBM nos anos 1950 sob liderança de John Backus, é um marco dessa virada. A promessa era quase abusada para a época: permitir que cientistas escrevessem fórmulas em uma linguagem de alto nível e ainda obtivessem código eficiente.&lt;/p&gt;
&lt;p&gt;Isso importava porque havia desconfiança. Se o código gerado fosse muito pior que assembly escrito à mão, ninguém sério usaria. Desde cedo, compiladores carregam essa tensão: abstração para humanos, eficiência para máquinas.&lt;/p&gt;
&lt;p&gt;Depois vieram ALGOL, COBOL, Lisp, C, Pascal, ML, Java, JavaScript, C#, Go, Rust e uma fila interminável de linguagens tentando equilibrar expressividade, segurança, portabilidade e desempenho. No caminho, ferramentas como Lex, Yacc, GCC, LLVM e muitos compiladores acadêmicos transformaram o campo em uma mistura curiosa de teoria formal e pragmatismo industrial.&lt;/p&gt;
&lt;p&gt;Essa história explica uma coisa importante: compilador não é apenas uma ferramenta de tradução. É uma negociação entre linguagem, hardware, sistema operacional, bibliotecas, economia e ergonomia. Parece exagero até você lembrar que uma decisão de ABI tomada décadas atrás ainda pode aparecer no seu debugger numa tarde ruim.&lt;/p&gt;
&lt;h2&gt;O problema real é traduzir sem perder significado&lt;/h2&gt;
&lt;p&gt;Um compilador é, no sentido mais direto, um programa que traduz outro programa.&lt;/p&gt;
&lt;p&gt;Essa definição parece burocrática, mas esconde a dificuldade inteira. Traduzir &lt;code&gt;position = initial + rate * 60&lt;/code&gt; para instruções de máquina não é substituir palavras por opcodes. O compilador precisa entender que &lt;code&gt;position&lt;/code&gt; é um nome, que &lt;code&gt;=&lt;/code&gt; é uma atribuição, que &lt;code&gt;*&lt;/code&gt; tem precedência maior que &lt;code&gt;+&lt;/code&gt;, que &lt;code&gt;rate&lt;/code&gt; talvez seja &lt;code&gt;float&lt;/code&gt;, que &lt;code&gt;60&lt;/code&gt; talvez precise virar &lt;code&gt;60.0&lt;/code&gt;, que valores temporários podem sumir, que registradores são poucos, que a ABI da plataforma tem regras, que o linker ainda vai resolver símbolos externos e que o sistema operacional vai carregar tudo isso na memória.&lt;/p&gt;
&lt;p&gt;Ou seja, o compilador não está apenas traduzindo texto. Ele está preservando comportamento observável enquanto muda radicalmente a forma do programa.&lt;/p&gt;
&lt;p&gt;Essa é a razão de a arquitetura de compiladores ser tão bonita. Ela pega uma coisa ambígua, humana e textual, e transforma em uma sequência de decisões cada vez mais explícitas.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/da-inten-o-ao-bin-rio-2f5f963f3d.svg&quot; alt=&quot;Da intenção ao binário&quot; /&gt;&lt;h2&gt;Compilador, interpretador e a zona cinzenta&lt;/h2&gt;
&lt;p&gt;A divisão clássica é simples.&lt;/p&gt;
&lt;p&gt;Um compilador traduz um programa escrito em uma linguagem fonte para um programa equivalente em outra linguagem alvo. Essa linguagem alvo pode ser assembly, código de máquina, bytecode, C, JavaScript, WebAssembly ou outra representação. O resultado pode ser salvo e executado depois.&lt;/p&gt;
&lt;p&gt;Um interpretador executa o programa diretamente, geralmente lendo uma representação do código e decidindo o que fazer durante a execução.&lt;/p&gt;
&lt;p&gt;Essa distinção é útil, mas também é um pouco limpa demais para o mundo real.&lt;/p&gt;
&lt;p&gt;Java, por exemplo, normalmente compila código fonte para bytecode. Esse bytecode roda sobre a JVM. A JVM pode interpretar bytecode, mas também pode usar um compilador JIT, &lt;em&gt;Just-In-Time&lt;/em&gt;, para transformar trechos quentes em código nativo enquanto o programa executa. JavaScript moderno faz algo parecido nos motores de navegador. Python costuma ser chamado de interpretado, mas CPython compila &lt;code&gt;.py&lt;/code&gt; para bytecode antes de executar na máquina virtual.&lt;/p&gt;
&lt;p&gt;O ponto não é decorar uma caixinha. O ponto é entender o eixo principal: quanto do trabalho acontece antes da execução e quanto acontece durante a execução.&lt;/p&gt;
&lt;p&gt;Compilação antecipada, ou AOT, tende a produzir execução rápida e diagnóstico cedo, mas gera artefatos mais presos à plataforma. Interpretação tende a favorecer flexibilidade e portabilidade, mas paga overhead em tempo de execução. JIT tenta ficar no meio, observando o programa enquanto roda e compilando melhor os caminhos que realmente importam.&lt;/p&gt;
&lt;p&gt;Esse meio do caminho é onde muita engenharia moderna vive. Porque software real raramente respeita dicotomias bonitas.&lt;/p&gt;
&lt;h2&gt;Antes do compilador, existe uma linha de montagem&lt;/h2&gt;
&lt;p&gt;Quando alguém diz “compilei um programa em C”, normalmente está comprimindo várias etapas em uma frase só.&lt;/p&gt;
&lt;p&gt;Em um fluxo clássico, o arquivo &lt;code&gt;.c&lt;/code&gt; passa pelo pré-processador, depois pelo compilador, depois pelo assembler, depois pelo linker. Na execução, o loader do sistema operacional entra na história.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/a-linha-de-montagem-de-um-programa-nativo-eaefdb369f.svg&quot; alt=&quot;A linha de montagem de um programa nativo&quot; /&gt;&lt;p&gt;O pré-processador lida com diretivas como &lt;code&gt;#include&lt;/code&gt; e &lt;code&gt;#define&lt;/code&gt;. Ele expande macros, inclui cabeçalhos e entrega ao compilador um texto já transformado.&lt;/p&gt;
&lt;p&gt;O compilador propriamente dito analisa esse código, verifica regras e gera uma forma mais baixa, frequentemente assembly ou algum IR interno que depois vira assembly.&lt;/p&gt;
&lt;p&gt;O assembler converte assembly em código de máquina relocável, normalmente em arquivos &lt;code&gt;.o&lt;/code&gt; ou &lt;code&gt;.obj&lt;/code&gt;. Relocável significa que o código já está em formato binário, mas ainda não sabe todos os endereços finais.&lt;/p&gt;
&lt;p&gt;O linker junta objetos e bibliotecas. Ele resolve símbolos externos, como uma chamada a &lt;code&gt;printf&lt;/code&gt;, e monta o executável final. Em sistemas modernos, parte disso pode ficar para o linker dinâmico em tempo de carregamento.&lt;/p&gt;
&lt;p&gt;O loader, no sistema operacional, mapeia o executável na memória, prepara segmentos, pilha, bibliotecas dinâmicas, argumentos, variáveis de ambiente e transfere controle para o ponto de entrada do programa.&lt;/p&gt;
&lt;p&gt;Essa visão é importante porque o compilador não vive sozinho. Ele é uma peça central, mas conversa com ABI, formato de objeto, biblioteca padrão, linker, loader, sistema operacional e CPU. Toda abstração elegante termina batendo em alguém que precisa colocar bytes no lugar certo.&lt;/p&gt;
&lt;h2&gt;Front-end, middle-end e back-end&lt;/h2&gt;
&lt;p&gt;Uma forma clássica de organizar um compilador é separá-lo em partes.&lt;/p&gt;
&lt;p&gt;O front-end entende a linguagem fonte. Ele faz análise léxica, análise sintática, análise semântica e constrói representações que preservam o significado do programa. É aqui que erros de sintaxe, escopo e tipo costumam aparecer.&lt;/p&gt;
&lt;p&gt;O middle-end trabalha sobre uma representação intermediária. Ele não quer saber se o programa veio de C, Rust, Swift ou outra linguagem. Ele quer transformar uma forma semântica em outra forma mais eficiente, preservando comportamento. É aqui que vivem muitas otimizações.&lt;/p&gt;
&lt;p&gt;O back-end entende a máquina alvo. Ele seleciona instruções, aloca registradores, respeita convenções de chamada, gera assembly ou objeto e lida com detalhes da arquitetura.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/as-tr-s-regi-es-de-um-compilador-915099fe69.svg&quot; alt=&quot;As três regiões de um compilador&quot; /&gt;&lt;p&gt;Essa separação explica por que LLVM virou uma infraestrutura tão importante. Se várias linguagens conseguem descer para uma IR comum, e vários back-ends conseguem subir dessa IR para arquiteturas diferentes, você evita reescrever o universo para cada combinação de linguagem e CPU.&lt;/p&gt;
&lt;p&gt;Na prática, claro, nada é tão limpo. Linguagens têm semânticas próprias. Máquinas têm detalhes inconvenientes. Otimizações podem depender de informação específica do front-end. Ainda assim, a divisão mental é excelente.&lt;/p&gt;
&lt;h2&gt;Análise léxica: transformar caracteres em unidades com sentido&lt;/h2&gt;
&lt;p&gt;O primeiro choque de realidade é que o compilador recebe texto.&lt;/p&gt;
&lt;p&gt;Texto é uma sequência de caracteres. Só que a gramática da linguagem não quer lidar com cada caractere individualmente o tempo todo. Ela quer unidades com significado: identificadores, números, operadores, palavras reservadas, delimitadores, strings e assim por diante.&lt;/p&gt;
&lt;p&gt;A análise léxica, também chamada de scanning ou lexing, faz essa primeira digestão. Ela lê caracteres e produz tokens.&lt;/p&gt;
&lt;p&gt;Considere a linha:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;position = initial + rate * 60
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O analisador léxico pode produzir algo conceitualmente parecido com isto:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;IDENT(position) ASSIGN IDENT(initial) PLUS IDENT(rate) STAR INT(60)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Os espaços desaparecem porque, nesse contexto, servem apenas para separar palavras. Comentários também costumam ser descartados ou preservados apenas para ferramentas auxiliares, como formatadores, documentação e análise estática.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/fluxo-dos-tokens-f3c13e7b23.svg&quot; alt=&quot;Fluxo dos tokens&quot; /&gt;&lt;p&gt;Essa etapa parece simples até você lidar com detalhes reais: Unicode, strings com escapes, comentários aninhados, números em várias bases, palavras reservadas que também parecem identificadores, indentação significativa, macros, templates, interpolação de string e mensagens de erro decentes.&lt;/p&gt;
&lt;p&gt;O lexer também costuma registrar identificadores na tabela de símbolos ou pelo menos entregar informação suficiente para que fases posteriores façam isso. A tabela de símbolos é uma das estruturas centrais do compilador. Ela guarda nomes, escopos, tipos, posições, vínculos e metadados necessários para entender o programa.&lt;/p&gt;
&lt;p&gt;Sem ela, &lt;code&gt;rate&lt;/code&gt; é só uma sequência de letras. Com ela, &lt;code&gt;rate&lt;/code&gt; pode ser uma variável local do tipo &lt;code&gt;float&lt;/code&gt;, declarada em determinado bloco, ocupando determinado slot, capturada por uma closure ou exportada por um módulo. Computadores gostam de detalhes. Compiladores também.&lt;/p&gt;
&lt;h2&gt;Análise sintática: descobrir a forma do programa&lt;/h2&gt;
&lt;p&gt;Tokens ainda são uma fila. A análise sintática transforma essa fila em estrutura.&lt;/p&gt;
&lt;p&gt;O parser verifica se a sequência de tokens obedece à gramática da linguagem. Ele entende que uma atribuição precisa ter um lado esquerdo válido, que operadores possuem precedência, que parênteses mudam agrupamento e que blocos precisam abrir e fechar corretamente.&lt;/p&gt;
&lt;p&gt;Na expressão:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;position = initial + rate * 60
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;o parser precisa entender que a multiplicação acontece antes da soma. A árvore sintática deixa isso explícito.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/rvore-sint-tica-da-express-o-75166738ba.svg&quot; alt=&quot;Árvore sintática da expressão&quot; /&gt;&lt;p&gt;Uma árvore sintática concreta pode conter muitos detalhes de superfície: parênteses, vírgulas, delimitadores, palavras reservadas, nós que existem mais por conveniência da gramática do que por significado semântico. Ela é útil para parsing, mas não costuma ser a forma ideal para o restante do compilador.&lt;/p&gt;
&lt;p&gt;Por isso muitos compiladores constroem uma AST, &lt;em&gt;Abstract Syntax Tree&lt;/em&gt;. A AST remove ruído sintático e mantém o que importa para o significado do programa.&lt;/p&gt;
&lt;p&gt;Em uma linguagem parecida com C, por exemplo, estes dois trechos podem ter formas textuais diferentes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;x = (((a + b)));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;x = a + b;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mas a AST relevante pode ser praticamente a mesma: atribuir a &lt;code&gt;x&lt;/code&gt; o resultado da soma entre &lt;code&gt;a&lt;/code&gt; e &lt;code&gt;b&lt;/code&gt;. Os parênteses extras já cumpriram seu papel, não precisam assombrar todas as fases posteriores.&lt;/p&gt;
&lt;h2&gt;AST: a forma que começa a parecer programa&lt;/h2&gt;
&lt;p&gt;A AST é uma das grandes viradas do compilador. Antes dela, temos texto e tokens. Depois dela, temos uma estrutura navegável que representa a intenção do programa.&lt;/p&gt;
&lt;p&gt;Uma AST para uma chamada de função pode dizer: este nó é uma chamada, o callee é &lt;code&gt;print&lt;/code&gt;, os argumentos são uma string e uma expressão. Para um &lt;code&gt;if&lt;/code&gt;, pode dizer: condição, bloco verdadeiro, bloco falso opcional. Para uma função, pode dizer: nome, parâmetros, tipo de retorno, corpo, atributos.&lt;/p&gt;
&lt;p&gt;Essa estrutura permite que as fases seguintes façam perguntas melhores.&lt;/p&gt;
&lt;p&gt;O nome foi declarado? O tipo da expressão é compatível? A função retorna em todos os caminhos? Existe código inalcançável? A variável foi movida? A referência vive tempo suficiente? O método chamado existe para aquele tipo? A captura da closure é por valor ou referência?&lt;/p&gt;
&lt;p&gt;A AST também é a ponte para ferramentas que não são exatamente compiladores. Formatadores, linters, servidores de linguagem, indexadores, refactorings e analisadores estáticos vivem em cima da mesma ideia: transformar código em estrutura, depois raciocinar sobre ela.&lt;/p&gt;
&lt;p&gt;Quando você usa “ir para definição” no editor, existe uma árvore, uma tabela de símbolos ou um índice semântico trabalhando por trás. O compilador vazou para a experiência diária de programação e ninguém pediu licença.&lt;/p&gt;
&lt;h2&gt;Análise semântica: sintaxe válida ainda pode ser bobagem&lt;/h2&gt;
&lt;p&gt;O parser responde uma pergunta: o programa tem uma forma permitida pela gramática?&lt;/p&gt;
&lt;p&gt;A análise semântica responde outra: essa forma faz sentido dentro das regras da linguagem?&lt;/p&gt;
&lt;p&gt;O trecho abaixo pode ser sintaticamente válido em uma linguagem imaginária:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;total = nome + 10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mas se &lt;code&gt;nome&lt;/code&gt; é uma string e &lt;code&gt;10&lt;/code&gt; é um inteiro, a linguagem precisa decidir se isso é erro, concatenação, coerção implícita, chamada de operador sobrecarregado ou algum crime contra a legibilidade.&lt;/p&gt;
&lt;p&gt;É na análise semântica que entram verificação de tipos, resolução de nomes, escopos, coerções, validação de retornos, controle de acessibilidade, regras de mutabilidade, checagens de inicialização e várias restrições específicas da linguagem.&lt;/p&gt;
&lt;p&gt;No exemplo das anotações:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;position = initial + rate * 60
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;se &lt;code&gt;rate&lt;/code&gt; for &lt;code&gt;float&lt;/code&gt; e &lt;code&gt;60&lt;/code&gt; for um inteiro, o compilador pode inserir uma conversão implícita:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;position = initial + rate * inttofloat(60)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Essa conversão não estava escrita no código, mas passa a existir na representação interna. O programa fonte é apenas parte da história. A linguagem define o restante.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/an-lise-sem-ntica-c9795cf893.svg&quot; alt=&quot;Análise semântica&quot; /&gt;&lt;p&gt;Essa fase é onde linguagens modernas diferem bastante.&lt;/p&gt;
&lt;p&gt;C permite uma quantidade histórica de coisas perigosas porque nasceu próximo da máquina e carrega compatibilidade como religião. Rust coloca o compilador para provar regras de posse, empréstimo e tempo de vida antes de aceitar o programa. TypeScript tenta sobrepor um sistema de tipos estrutural em cima de JavaScript sem quebrar o mundo. Haskell empurra inferência de tipos para um nível que faz muita gente olhar para o terminal com respeito e medo.&lt;/p&gt;
&lt;p&gt;Em todos os casos, a pergunta é parecida: o programa quer dizer alguma coisa permitida pela linguagem?&lt;/p&gt;
&lt;h2&gt;Escopo, ambiente e estado&lt;/h2&gt;
&lt;p&gt;Para entender análise semântica direito, vale separar duas ideias que costumam se misturar na cabeça: ambiente e estado.&lt;/p&gt;
&lt;p&gt;O ambiente mapeia nomes para lugares. O estado mapeia lugares para valores.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/ambiente-e-estado-687150c7e1.svg&quot; alt=&quot;Ambiente e estado&quot; /&gt;&lt;p&gt;Quando você escreve &lt;code&gt;x = x + 1&lt;/code&gt;, o nome &lt;code&gt;x&lt;/code&gt; precisa ser resolvido para algum local. Depois, o valor guardado naquele local é lido, incrementado e escrito de volta. O lado esquerdo de uma atribuição está preocupado com localização. O lado direito está preocupado com valor.&lt;/p&gt;
&lt;p&gt;Essa distinção aparece em conceitos como &lt;em&gt;l-value&lt;/em&gt; e &lt;em&gt;r-value&lt;/em&gt;. Ela também influencia otimizações, análise de aliasing, passagem de parâmetros e regras de mutabilidade.&lt;/p&gt;
&lt;p&gt;Escopo é a regra que define onde um nome é visível. Em escopo léxico, também chamado de escopo estático, a região de validade de um nome pode ser determinada olhando a estrutura textual do programa. Em escopo dinâmico, a resolução pode depender da pilha de chamadas em tempo de execução.&lt;/p&gt;
&lt;p&gt;A maioria das linguagens modernas de uso geral favorece escopo léxico porque ele é mais previsível para humanos e compiladores. Se uma variável declarada em um bloco &lt;code&gt;{}&lt;/code&gt; só existe ali dentro, a tabela de símbolos pode refletir a estrutura aninhada do programa. Um bloco interno pode sombrear uma variável externa. Isso é simples de explicar, mas gera detalhes suficientes para manter implementadores ocupados por bastante tempo.&lt;/p&gt;
&lt;h2&gt;Representação intermediária: o computador imaginário&lt;/h2&gt;
&lt;p&gt;Depois que o compilador entende o programa, ele costuma gerar uma representação intermediária, ou IR.&lt;/p&gt;
&lt;p&gt;A IR existe porque AST é próxima demais da linguagem fonte e código de máquina é próximo demais da arquitetura alvo. Entre os dois, o compilador precisa de uma forma conveniente para análise, transformação e otimização.&lt;/p&gt;
&lt;p&gt;Uma IR comum em livros é o código de três endereços. Nele, cada instrução faz uma operação relativamente simples, usando temporários explícitos.&lt;/p&gt;
&lt;p&gt;Para a expressão:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;position = initial + rate * 60
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;uma IR possível seria:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;t1 = inttofloat(60)
t2 = rate * t1
t3 = initial + t2
position = t3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso parece mais verboso que o código original, e é mesmo. Mas essa verbosidade ajuda o compilador. Cada passo fica claro. Dependências ficam explícitas. Temporários podem ser analisados. Otimizações podem atacar partes pequenas.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/ast-e-ir-olham-para-problemas-diferentes-8b81afe26e.svg&quot; alt=&quot;AST e IR olham para problemas diferentes&quot; /&gt;&lt;p&gt;LLVM IR, por exemplo, é uma representação de baixo nível, tipada, baseada em SSA, com instruções que lembram assembly abstrato. Outras infraestruturas usam bytecode, árvores, grafos, MIR, HIR, LIR e variações conforme a linguagem e o projeto.&lt;/p&gt;
&lt;p&gt;O nome muda. A necessidade continua: criar uma forma intermediária onde o compilador consiga raciocinar sem carregar todo o peso da sintaxe original nem cair cedo demais nos detalhes da CPU.&lt;/p&gt;
&lt;h2&gt;SSA: quando cada variável recebe valor uma vez&lt;/h2&gt;
&lt;p&gt;Uma das ideias mais influentes em compiladores modernos é a forma SSA, &lt;em&gt;Static Single Assignment&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Em SSA, cada nome recebe valor apenas uma vez. Se uma variável muda, na prática o compilador cria uma nova versão dela.&lt;/p&gt;
&lt;p&gt;Um trecho simples:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;x = 1
x = x + 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;pode virar:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;x1 = 1
x2 = x1 + 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso facilita muito a análise de dependências. Se &lt;code&gt;x2&lt;/code&gt; depende de &lt;code&gt;x1&lt;/code&gt;, a relação está explícita. O compilador não precisa perguntar qual valor de &lt;code&gt;x&lt;/code&gt; está vivo naquele ponto com a mesma dificuldade.&lt;/p&gt;
&lt;p&gt;O caso interessante aparece em desvios de controle:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;if cond:
  x = 1
else:
  x = 2
y = x + 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Em SSA, o valor de &lt;code&gt;x&lt;/code&gt; depois do &lt;code&gt;if&lt;/code&gt; depende do caminho tomado. Para representar isso, usa-se uma função phi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;x1 = 1
x2 = 2
x3 = phi(x1, x2)
y1 = x3 + 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;phi&lt;/code&gt; não é uma função normal executada como chamada de runtime. Ela é um marcador na IR dizendo que o valor vem de um predecessor ou de outro no grafo de fluxo de controle.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/ssa-e-fun-o-phi-641e0e3bf4.svg&quot; alt=&quot;SSA e função phi&quot; /&gt;&lt;p&gt;SSA é importante porque várias otimizações ficam mais simples ou mais eficientes: propagação de constantes, eliminação de código morto, análise de fluxo de dados, simplificação de expressões e muitas outras. É uma daquelas ideias que parecem pequenas até você perceber que boa parte de um compilador moderno gira ao redor dela.&lt;/p&gt;
&lt;h2&gt;Otimização: melhorar sem mentir&lt;/h2&gt;
&lt;p&gt;O otimizador tem uma missão ingrata: reescrever o programa para ficar melhor sem mudar o comportamento que a linguagem promete preservar.&lt;/p&gt;
&lt;p&gt;Melhor pode significar mais rápido, menor, mais econômico em energia, mais amigável ao cache, menos dependente de memória, mais fácil de vetorização ou mais adequado a uma arquitetura específica.&lt;/p&gt;
&lt;p&gt;No exemplo inicial, a IR era:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;t1 = inttofloat(60)
t2 = rate * t1
t3 = initial + t2
position = t3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Um otimizador pode perceber que converter &lt;code&gt;60&lt;/code&gt; para &lt;code&gt;60.0&lt;/code&gt; não precisa acontecer em runtime. Pode fazer isso em tempo de compilação. Também pode eliminar temporários desnecessários:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;t1 = rate * 60.0
position = initial + t1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso é um exemplo pequeno de &lt;em&gt;constant folding&lt;/em&gt; e simplificação de temporários.&lt;/p&gt;
&lt;p&gt;Outras otimizações comuns incluem eliminação de código morto, propagação de constantes, &lt;em&gt;common subexpression elimination&lt;/em&gt;, inlining, unrolling de loops, &lt;em&gt;loop invariant code motion&lt;/em&gt;, vetorização, especialização, análise de escape e alocação mais inteligente de objetos.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/arquitetura-de-compiladores/um-ciclo-simplificado-de-otimiza-o-2f05c01947.svg&quot; alt=&quot;Um ciclo simplificado de otimização&quot; /&gt;&lt;p&gt;O problema é que otimização não pode ser chute. Ela depende das garantias da linguagem.&lt;/p&gt;
&lt;p&gt;Se a linguagem permite aliases agressivos, o compilador precisa ser conservador. Alias acontece quando duas referências podem apontar para o mesmo local de memória. Imagine uma função que recebe duas referências &lt;code&gt;x&lt;/code&gt; e &lt;code&gt;y&lt;/code&gt;. Se &lt;code&gt;x[10]&lt;/code&gt; e &lt;code&gt;y[10]&lt;/code&gt; podem ser a mesma posição, uma escrita via &lt;code&gt;x&lt;/code&gt; pode afetar uma leitura via &lt;code&gt;y&lt;/code&gt;. Isso atrapalha otimizações porque o compilador não pode fingir independência onde talvez exista compartilhamento.&lt;/p&gt;
&lt;p&gt;Esse é um dos motivos de regras de aliasing importarem tanto em C, de &lt;code&gt;restrict&lt;/code&gt; existir, de Rust ser tão rígido com empréstimos mutáveis e de linguagens gerenciadas tomarem decisões diferentes. Otimização gosta de informação. Linguagens seguras e restritivas às vezes dão ao compilador mais espaço para ser agressivo sem invocar comportamento indefinido como entidade cósmica.&lt;/p&gt;
&lt;h2&gt;Geração de código: o choque com a máquina real&lt;/h2&gt;
&lt;p&gt;Depois da IR otimizada, chega a hora de emitir código para a arquitetura alvo.&lt;/p&gt;
&lt;p&gt;Essa fase envolve seleção de instruções, alocação de registradores, agendamento de instruções, layout de pilha, convenções de chamada e emissão de assembly ou código objeto.&lt;/p&gt;
&lt;p&gt;O código intermediário:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;t1 = rate * 60.0
position = initial + t1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;pode virar algo conceitualmente assim em uma máquina hipotética:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-asm&quot;&gt;LDF  R2, rate
MULF R2, R2, #60.0
LDF  R1, initial
ADDF R1, R1, R2
STF  position, R1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O exemplo é didático, mas mostra o ponto: agora o compilador precisa lidar com registradores físicos, formatos de instrução, modos de endereçamento e custo real de operações.&lt;/p&gt;
&lt;p&gt;Alocação de registradores é um problema especialmente importante. CPUs têm poucos registradores rápidos. Memória é maior, mas mais lenta. O compilador quer manter valores usados com frequência em registradores, mas nem tudo cabe. Quando não cabe, ele precisa fazer &lt;em&gt;spill&lt;/em&gt;, salvando valores na pilha e recarregando depois.&lt;/p&gt;
&lt;p&gt;É aqui que a teoria encosta com força no hardware. Uma IR pode ter temporários infinitos. A CPU não.&lt;/p&gt;
&lt;p&gt;Também entram as convenções de chamada. Quem passa argumento em qual registrador? Quem preserva quais registradores? Onde fica o valor de retorno? Como alinhar a pilha? Como chamar funções externas? Como lidar com exceções, unwinding, debug info e chamadas variádicas?&lt;/p&gt;
&lt;p&gt;Se o front-end é a parte que entende o programador, o back-end é a parte que entende a máquina. E máquinas são rápidas, mas não são exatamente simpáticas.&lt;/p&gt;
&lt;h2&gt;Linking: costurando pedaços de programa&lt;/h2&gt;
&lt;p&gt;O compilador geralmente não produz sozinho tudo que um programa precisa.&lt;/p&gt;
&lt;p&gt;Seu código chama funções de bibliotecas, acessa símbolos definidos em outros arquivos, depende de runtime, inicialização, destrutores, tabelas, metadados e objetos separados. O linker resolve essa bagunça.&lt;/p&gt;
&lt;p&gt;Quando um arquivo objeto chama &lt;code&gt;printf&lt;/code&gt;, ele pode conter uma referência simbólica dizendo “existe um símbolo chamado &lt;code&gt;printf&lt;/code&gt; que eu preciso”. O linker encontra a definição em uma biblioteca compatível e resolve os endereços necessários.&lt;/p&gt;
&lt;p&gt;Em ligação estática, o código das bibliotecas pode ser incorporado ao executável. Em ligação dinâmica, o executável referencia bibliotecas compartilhadas que serão carregadas em tempo de execução, como &lt;code&gt;.so&lt;/code&gt; no Linux, &lt;code&gt;.dylib&lt;/code&gt; no macOS ou &lt;code&gt;.dll&lt;/code&gt; no Windows.&lt;/p&gt;
&lt;p&gt;O resultado final não é apenas um monte de instruções. É um arquivo em formato específico, como ELF, Mach-O ou PE, contendo seções, símbolos, metadados, relocations, permissões de segmentos e informações que o sistema operacional e o loader entendem.&lt;/p&gt;
&lt;p&gt;Essa parte costuma ficar invisível até quebrar. Aí surgem mensagens sobre símbolo indefinido, ABI incompatível, biblioteca ausente, ordem errada no link, versão de GLIBC, &lt;code&gt;rpath&lt;/code&gt;, &lt;code&gt;ld.so&lt;/code&gt;, arquitetura incorreta e outras formas refinadas de humilhação.&lt;/p&gt;
&lt;h2&gt;Execução: quando o binário vira processo&lt;/h2&gt;
&lt;p&gt;Depois do linking, ainda falta o programa rodar.&lt;/p&gt;
&lt;p&gt;No Linux, por exemplo, executar um binário ELF envolve o kernel reconhecer o formato, mapear segmentos na memória virtual do processo, preparar permissões, configurar pilha inicial, carregar o interpretador dinâmico quando necessário e transferir controle para o ponto de entrada.&lt;/p&gt;
&lt;p&gt;Antes de &lt;code&gt;main&lt;/code&gt;, muita coisa pode acontecer. Runtime da linguagem, inicialização da libc, construtores globais, preparação de TLS, configuração de ambiente e código de suporte podem executar antes de o seu código “começar”.&lt;/p&gt;
&lt;p&gt;Isso é importante porque “meu programa começa em &lt;code&gt;main&lt;/code&gt;” é uma simplificação útil, não uma verdade cósmica.&lt;/p&gt;
&lt;p&gt;Em linguagens com runtimes mais ricos, a distância aumenta. Java inicializa JVM, carrega classes, verifica bytecode, interpreta ou compila JIT. Go inicializa scheduler, pilhas de goroutines e runtime. Rust em binários nativos pode parecer mais próximo de C, mas ainda respeita runtime mínimo, inicialização e regras de panic conforme configuração.&lt;/p&gt;
&lt;p&gt;Do ponto de vista da máquina, programa publicado é só o começo. Execução é um acordo entre binário, loader, runtime, sistema operacional, memória virtual, bibliotecas e CPU.&lt;/p&gt;
&lt;h2&gt;Passagem de parâmetros, aliases e outras dores úteis&lt;/h2&gt;
&lt;p&gt;As anotações originais também tocavam em passagem de parâmetros, e esse assunto parece periférico até você olhar para otimização e semântica.&lt;/p&gt;
&lt;p&gt;Chamada por valor copia o valor do argumento para o parâmetro da função. Alterar o parâmetro não altera a variável original. C usa chamada por valor, inclusive quando o valor copiado é um ponteiro. Java também passa valores, embora esses valores possam ser referências para objetos, o que causa muita confusão didática.&lt;/p&gt;
&lt;p&gt;Chamada por referência faz o parâmetro se comportar como um apelido para a variável original. Alterações dentro da função afetam o lado de fora.&lt;/p&gt;
&lt;p&gt;A diferença importa para o compilador porque define quem pode modificar o quê. Se uma função recebe referências mutáveis para estruturas que podem se sobrepor, o compilador precisa assumir que escritas em uma podem afetar leituras em outra. Isso fecha portas para reordenação, cache em registrador e eliminação de leituras redundantes.&lt;/p&gt;
&lt;p&gt;Alias é uma das palavras que fazem otimizadores perderem o sorriso.&lt;/p&gt;
&lt;p&gt;O compilador quer transformar:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;a[i] = 10;
x = b[i];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mas se &lt;code&gt;a&lt;/code&gt; e &lt;code&gt;b&lt;/code&gt; podem apontar para a mesma região, a escrita em &lt;code&gt;a[i]&lt;/code&gt; talvez altere o valor lido de &lt;code&gt;b[i]&lt;/code&gt;. Sem prova de independência, uma otimização aparentemente óbvia pode quebrar o programa.&lt;/p&gt;
&lt;p&gt;Essa é a razão de análise de aliasing existir, e também uma das razões de linguagens modernas tentarem expressar melhor posse, mutabilidade e exclusividade. Quando o compilador sabe mais, ele pode arriscar menos e otimizar mais.&lt;/p&gt;
&lt;h2&gt;Compiladores também estão fora dos compiladores&lt;/h2&gt;
&lt;p&gt;Estudar compiladores não serve apenas para escrever um compilador.&lt;/p&gt;
&lt;p&gt;As mesmas técnicas aparecem em ferramentas de segurança, linters, formatadores, IDEs, bancos de dados, motores de template, navegadores, VMs, JITs, transpiladores, analisadores de configuração, parsers de protocolo e sistemas de consulta.&lt;/p&gt;
&lt;p&gt;Um SQL planner, por exemplo, recebe uma consulta declarativa, valida nomes, constrói uma representação interna, otimiza um plano e executa uma estratégia. Isso soa familiar porque é familiar. Um motor de regex compila uma expressão para uma máquina interna. Um navegador parseia HTML, CSS e JavaScript, constrói estruturas, aplica regras, otimiza e executa. Um linter parseia código e procura padrões suspeitos.&lt;/p&gt;
&lt;p&gt;Compiladores ensinaram a engenharia de software a fazer uma coisa poderosa: transformar texto em estrutura, validar significado e reescrever semântica de forma controlada.&lt;/p&gt;
&lt;p&gt;Depois que você enxerga esse padrão, ele aparece em todos os lugares. É meio irritante. Também é libertador.&lt;/p&gt;
&lt;h2&gt;O ponto central&lt;/h2&gt;
&lt;p&gt;Um compilador não é um botão mágico que transforma código em binário. É uma arquitetura em camadas que reduz ambiguidade passo a passo.&lt;/p&gt;
&lt;p&gt;Primeiro caracteres viram tokens. Tokens viram árvores. Árvores viram estruturas semanticamente anotadas. Essas estruturas viram IR. A IR é analisada, simplificada e otimizada. Depois vira instrução para uma máquina real. O assembler e o linker terminam de empacotar o resultado. O loader coloca tudo em memória. A CPU finalmente executa.&lt;/p&gt;
&lt;p&gt;O processo inteiro existe para equilibrar duas forças que brigam desde FORTRAN: deixar humanos escreverem programas em uma linguagem expressiva e ainda entregar algo que o hardware execute com eficiência.&lt;/p&gt;
&lt;p&gt;É por isso que estudar compiladores muda a forma de programar. Você passa a entender por que um erro aparece antes da execução, por que uma otimização é possível, por que aliasing atrapalha, por que tipos importam, por que uma ABI quebra seu dia, por que JITs são tão agressivos, por que &lt;code&gt;undefined behavior&lt;/code&gt; assusta e por que uma simples linha de código carrega uma quantidade indecente de engenharia.&lt;/p&gt;
&lt;p&gt;No fim, compiladores são menos magia negra e mais engenharia disciplinada. O que, sinceramente, é bem mais interessante.&lt;/p&gt;
&lt;h2&gt;Referências e leituras recomendadas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://suif.stanford.edu/dragonbook/&quot;&gt;Compilers: Principles, Techniques, and Tools, Alfred V. Aho, Monica S. Lam, Ravi Sethi e Jeffrey D. Ullman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.elsevier.com/books/engineering-a-compiler/cooper/978-0-12-815412-0&quot;&gt;Engineering a Compiler, Keith D. Cooper e Linda Torczon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.elsevier.com/books/advanced-compiler-design-and-implementation/muchnick/978-1-55860-320-2&quot;&gt;Advanced Compiler Design and Implementation, Steven S. Muchnick&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cs.princeton.edu/~appel/modern/&quot;&gt;Modern Compiler Implementation, Andrew W. Appel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://craftinginterpreters.com/&quot;&gt;Crafting Interpreters, Robert Nystrom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://llvm.org/docs/LangRef.html&quot;&gt;LLVM Language Reference Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://llvm.org/docs/&quot;&gt;LLVM Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gccint/&quot;&gt;GCC Internals Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pfalcon.github.io/ssabook/latest/book-full.pdf&quot;&gt;Static Single Assignment Book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dl.acm.org/doi/10.1145/115372.115320&quot;&gt;Cytron et al., Efficiently Computing Static Single Assignment Form and the Control Dependence Graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gitlab.com/x86-psABIs/x86-64-ABI&quot;&gt;System V Application Binary Interface, AMD64 Architecture Processor Supplement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Software genérico: o imposto oculto da abstração</title><link>https://blog.kristyan.dev/posts/software-generico-o-imposto-oculto-da-abstracao</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/software-generico-o-imposto-oculto-da-abstracao</guid><description>Emaranhado opinativo e informativo sobre software genérico com base nas minhas leituras da semana</description><pubDate>Sun, 12 Jul 2026 19:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Reutilizar código é inteligente. O problema é que a indústria transformou o reuso em um dogma inquestionável, onde escrever duas linhas de código em casa é pecado mortal e importar uma biblioteca genérica de dez mil linhas é virtude de engenharia.&lt;/p&gt;
&lt;p&gt;Você precisa de um parser de data? Importa uma biblioteca. Precisa de um validador de struct? Importa uma biblioteca. Precisa de um client HTTP um pouco mais esperto? Importa um framework que promete resolver todos os problemas de rede da história da humanidade.&lt;/p&gt;
&lt;p&gt;E aí mora o problema.&lt;/p&gt;
&lt;p&gt;Não porque reaproveitar código seja ruim por si só. A biblioteca padrão do Go está aí para provar que uma boa stdlib carrega o piano de quase qualquer aplicação comercial sem pedir ajuda. O problema real é o software genérico por obsessão, aquele que tenta rodar em qualquer ambiente, sob qualquer configuração, atendendo a qualquer caso de uso imaginável do universo.&lt;/p&gt;
&lt;p&gt;Na tentativa de agradar a todos, esse tipo de software cria tantas camadas de abstração que se torna pesado, lento e terrivelmente complexo. Ele deixa de ser uma solução elegante para virar um imposto oculto na sua aplicação.&lt;/p&gt;
&lt;p&gt;Bonito no GitHub, um inferno no go.mod.&lt;/p&gt;
&lt;h2&gt;O ecossistema expandido e a profecia de Rob Pike&lt;/h2&gt;
&lt;p&gt;Como desenvolvedor Go, a frase mais famosa de Rob Pike provavelmente já cruzou o seu terminal ou o seu feed:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;A little copying is better than a little dependency.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pike apresentou esse conceito de forma detalhada na palestra clássica da dotGo 2015 (no compilado de Go Proverbs). O argumento dele ataca diretamente a cultura do software hiper-genérico. Quando você traz uma dependência externa gigante para resolver um problema minúsculo, você não está importando apenas uma função; você está importando as decisões arquiteturais, os bugs de concorrência, o grafo de subdependências e as falhas de segurança de outra pessoa.&lt;/p&gt;
&lt;p&gt;Antes disso, no ensaio oficial &quot;Less is exponentially more&quot; (2012), Pike já destrinchava a filosofia por trás do design do Go. Ele mostrava como linguagens como C++ e Java inflaram porque tentaram adotar todo tipo de recurso genérico e hierarquia de tipos imaginável. O resultado? Sistemas onde o programador gasta mais tempo gerenciando a complexidade da própria arquitetura do que resolvendo o problema de negócio.&lt;/p&gt;
&lt;p&gt;O diagrama abaixo ilustra o que acontece na prática quando trocamos uma linha de código sob medida por uma abstração genérica:&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/software-generico-o-imposto-oculto-da-abstracao/o-custo-de-uma-depend-ncia-gen-rica-bcba0c0966.svg&quot; alt=&quot;O Custo de uma Dependência Genérica&quot; /&gt;&lt;h2&gt;A engenharia que esqueceu o hardware&lt;/h2&gt;
&lt;p&gt;Quando o software se torna excessivamente genérico para poder rodar em qualquer lugar, ele se desconecta da máquina física.&lt;/p&gt;
&lt;p&gt;No ensaio clássico &quot;A Plea for Lean Software&quot; (1995), publicado na Computer, Niklaus Wirth (o criador do Pascal) já alertava sobre essa tendência de inchaço na seção &quot;Where software heft comes from&quot;. Wirth argumenta que a facilidade de obter hardware mais rápido mascarou a incompetência da indústria em projetar softwares eficientes. Em vez de refinarmos algoritmos para os dados que temos, jogamos camadas de abstrações dinâmicas e genéricas que devoram memória. O software fica gordo. E, como diz a própria Lei de Wirth, ele desacelera mais rápido do que o hardware consegue avançar.&lt;/p&gt;
&lt;p&gt;Essa desconexão é o alvo das críticas atuais de programadores de sistemas como Casey Muratori. No seu artigo e benchmark comparativo &quot;Clean Code, Horrible Performance&quot; (2023), Muratori provou o custo real de seguir cegamente regras rígidas de abstração genérica, como as defendidas no movimento tradicional de Clean Code.&lt;/p&gt;
&lt;p&gt;Ao criar getters, setters, polimorfismo dinâmico e invocações genéricas para proteger o código contra futuras mudanças teóricas, os desenvolvedores criaram um código que roda até 100 vezes mais lento do que uma função direta que simplesmente processa um array de dados na memória de forma linear.&lt;/p&gt;
&lt;h2&gt;Módulos profundos vs. Astronautas da Arquitetura&lt;/h2&gt;
&lt;p&gt;Para não parecer que a solução é reescrever o mundo em Assembly toda segunda-feira, o equilíbrio reside no conceito que John Ousterhout traz no livro &quot;A Philosophy of Software Design&quot; (2018).&lt;/p&gt;
&lt;p&gt;No Capítulo 6 (&quot;General-Purpose Modules&quot;), Ousterhout introduz uma discussão cirúrgica sobre até onde um código deve ser genérico. Ele defende que os módulos devem ser profundos (Deep Modules), ou seja, devem ter uma interface simples, mas implementar uma funcionalidade robusta por trás.&lt;/p&gt;
&lt;p&gt;No entanto, no mesmo capítulo, ele traça o limite exato de onde a genericidade vira um tiro no pé. Se você começa a injetar dezenas de parâmetros de configuração e comportamentos alternativos para prever cenários hipotéticos que o seu negócio nunca vai enfrentar, você está criando um módulo raso, complexo e inflado. É o que Joel Spolsky chamava de Astronautas da Arquitetura: engenheiros que sobem tanto o nível de abstração que esquecem como o oxigênio funciona aqui embaixo.&lt;/p&gt;
&lt;p&gt;O custo de customizar, esticar e entortar uma grande ferramenta genérica para que ela obedeça às regras específicas da sua empresa frequentemente supera, e muito, o custo de ter escrito uma solução interna simples desde o início. É a famosa complexidade acidental que Fred Brooks descreve detalhadamente na seção &quot;Buy versus Build&quot; do seu lendário manifesto &quot;No Silver Bullet&quot; (1986).&lt;/p&gt;
&lt;h2&gt;O &quot;Suficientemente Bom&quot; sempre vence o &quot;Perfeitamente Abstrato&quot;&lt;/h2&gt;
&lt;p&gt;Se a história da computação nos ensinou algo, é que a simplicidade da implementação prática sempre vence a perfeição teórica da genericidade absoluta.&lt;/p&gt;
&lt;p&gt;Esse fenômeno foi batizado por Richard P. Gabriel no ensaio &quot;The Rise of Worse is Better&quot; (1991). Na Seção 2.1, ele compara a abordagem do MIT (que buscava designs ultra-genéricos, corretude absoluta e arquiteturas perfeitas) com a abordagem de New Jersey (adotada na criação do Unix e do C).&lt;/p&gt;
&lt;p&gt;A filosofia de New Jersey dizia que a simplicidade do design é importante, mas a simplicidade da implementação é ainda mais crítica. O software precisa ser fácil de entender, direto ao ponto e focado em resolver o caso comum com eficiência, mesmo que não cubra perfeitamente 100% dos cenários abstratos do mundo acadêmico. O Unix e o C dominaram o planeta exatamente por causa disso.&lt;/p&gt;
&lt;h2&gt;Menos Slogan, Mais Perfilamento&lt;/h2&gt;
&lt;p&gt;Antes de instalar aquela biblioteca que promete abstrair o seu banco de dados, a sua fila de mensageria e o seu café da manhã em uma única interface mágica e genérica, faça a si mesmo algumas perguntas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Eu realmente preciso de suporte a 5 bancos de dados diferentes se a minha infraestrutura inteira roda no Postgres há 8 anos?&lt;/li&gt;
&lt;li&gt;Essa interface genérica não está escondendo o uso ineficiente de memória (como alocações ocultas na heap em Go)?&lt;/li&gt;
&lt;li&gt;Quanto tempo eu vou gastar lendo a documentação dessa biblioteca comparado ao tempo que eu gastaria escrevendo a lógica exata que eu preciso?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Software genérico tem o seu valor para prototipagem rápida e ecossistemas compartilhados. Mas em produção, no hot path do seu serviço, o código que conhece os seus dados e respeita o seu hardware sempre vai andar de cabeça erguida.&lt;/p&gt;
&lt;p&gt;Falta de critério arquitetural compila em qualquer linguagem. Só que o custo da CPU, esse sempre chega na fatura do mês seguinte.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Virtualização: Tanenbaum é um louco genial</title><link>https://blog.kristyan.dev/posts/virtualizacao-tanenbaum-e-um-louco-genial</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/virtualizacao-tanenbaum-e-um-louco-genial</guid><description>Uma síntese técnica sobre virtualização, hipervisores, memória, E/S, nuvem e VMware a partir de Sistemas Operacionais Modernos 4a. Edição.</description><pubDate>Thu, 09 Jul 2026 03:20:00 GMT</pubDate><content:encoded>&lt;p&gt;Virtualização é uma daquelas ideias que parecem simples até você tentar explicar direito.&lt;/p&gt;
&lt;p&gt;Na versão inocente, é “rodar um sistema operacional dentro de outro”. Na versão um pouco menos enganosa, é “criar uma máquina falsa para um sistema operacional acreditar que manda em alguma coisa”. Na versão Tanenbaum, que é a versão que começa civilizada e termina com você olhando para a MMU como quem encara um bicho mitológico, virtualização é uma camada de abstração que precisa enganar CPU, memória, dispositivos de E/S, sistemas operacionais inteiros e, se possível, o usuário também.&lt;/p&gt;
&lt;p&gt;E o pior é que funciona.&lt;/p&gt;
&lt;p&gt;O capítulo 7 de &lt;em&gt;Sistemas Operacionais Modernos&lt;/em&gt; é uma síntese muito boa porque não trata virtualização como buzzword de cloud, nem como botão mágico do VirtualBox. Ele começa na história, passa por exigências formais, entra em hipervisores, cai no buraco da memória virtual, sofre com E/S, fala de nuvem, licenciamento, migração de máquina virtual e fecha com VMware, que é basicamente o estudo de caso de como transformar uma arquitetura inconveniente em produto bilionário.&lt;/p&gt;
&lt;p&gt;Este post é uma síntese desse trecho. Não é uma substituição do livro, até porque Tanenbaum tem aquela habilidade irritante de explicar um conceito simples, depois revelar que ele só era simples porque você ainda não tinha visto as três camadas escondidas embaixo.&lt;/p&gt;
&lt;h2&gt;Virtualização é uma mentira com contrato&lt;/h2&gt;
&lt;p&gt;A melhor forma de entender virtualização é pensar nela como uma mentira disciplinada.&lt;/p&gt;
&lt;p&gt;Uma máquina virtual recebe CPU virtual, memória virtual, disco virtual, placa de rede virtual, BIOS ou UEFI virtual, interrupções virtuais e, em muitos casos, até dispositivos antigos fingindo estar vivos só para o sistema convidado reconhecer alguma coisa. O sistema operacional dentro da VM olha ao redor e pensa: “essa máquina é minha”.&lt;/p&gt;
&lt;p&gt;Não é.&lt;/p&gt;
&lt;p&gt;Quem manda de verdade é o hipervisor. Ele decide quando a VM executa, quanta memória ela recebe, quais operações são permitidas, quais precisam ser interceptadas e quais serão emuladas. A VM vive numa espécie de teatro computacional, só que com menos aplausos e mais tabela de páginas.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/virtualizacao-tanenbaum-e-um-louco-genial/a-mentira-organizada-da-virtualiza-o-d1b4578e4d.svg&quot; alt=&quot;A mentira organizada da virtualização&quot; /&gt;&lt;p&gt;Essa mentira precisa obedecer a três propriedades clássicas, vindas do trabalho de Popek e Goldberg: equivalência, controle de recursos e eficiência.&lt;/p&gt;
&lt;p&gt;Equivalência significa que o software dentro da VM deve se comportar como se estivesse rodando numa máquina real, com exceções aceitáveis como diferenças de tempo. Controle de recursos significa que o hipervisor precisa continuar no comando. Eficiência significa que a maior parte das instruções deve rodar diretamente no hardware, sem o hipervisor ficar metendo o bedelho em tudo.&lt;/p&gt;
&lt;p&gt;Essa última parte é importante. Se toda instrução precisasse ser interpretada pelo hipervisor, virtualização seria basicamente uma reunião de condomínio: tudo anda, mas num ritmo que faz você questionar suas escolhas de vida.&lt;/p&gt;
&lt;h2&gt;A história é mais velha que o hype&lt;/h2&gt;
&lt;p&gt;Virtualização não nasceu com cloud, Docker, Kubernetes, dev local bonitinho ou aquele tutorial que manda subir uma VM Ubuntu porque “é mais seguro”. A ideia vem dos mainframes.&lt;/p&gt;
&lt;p&gt;Nos anos 1960 e 1970, a IBM já trabalhava com sistemas como CP-40, CP-67 e VM/370. O problema era prático: máquinas grandes eram caras demais para ficarem presas a um único usuário ou carga de trabalho. A virtualização permitia dividir uma máquina física poderosa em várias máquinas aparentes.&lt;/p&gt;
&lt;p&gt;Ou seja, antes de virar produto de nuvem, virtualização era uma resposta econômica para hardware caro. A nuvem moderna apenas pegou essa lógica, colocou API, billing por hora, IAM, dashboard, região, zona de disponibilidade e uma fatura que chega sorrindo no cartão.&lt;/p&gt;
&lt;p&gt;A ideia central continuou parecida: transformar recursos físicos compartilhados em recursos virtuais aparentemente dedicados.&lt;/p&gt;
&lt;p&gt;A parte engraçada é que muita gente fala de cloud como se fosse uma ruptura filosófica completa. Em alguns aspectos, é só o mainframe voltando de jaqueta nova, usando JSON e cobrando por tráfego de saída.&lt;/p&gt;
&lt;h2&gt;O que torna uma arquitetura virtualizável&lt;/h2&gt;
&lt;p&gt;O livro entra num ponto essencial: nem toda arquitetura é igualmente fácil de virtualizar.&lt;/p&gt;
&lt;p&gt;Para uma CPU ser virtualizável de forma elegante, instruções sensíveis precisam causar uma armadilha quando executadas sem privilégio. Instruções sensíveis são aquelas que leem ou alteram estado privilegiado da máquina. Instruções privilegiadas são aquelas que só podem ser executadas no modo mais poderoso da CPU.&lt;/p&gt;
&lt;p&gt;O modelo ideal é simples:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;o sistema convidado executa normalmente;&lt;/li&gt;
&lt;li&gt;quando tenta fazer algo perigoso, a CPU gera uma exceção;&lt;/li&gt;
&lt;li&gt;o hipervisor assume;&lt;/li&gt;
&lt;li&gt;o hipervisor simula o efeito correto;&lt;/li&gt;
&lt;li&gt;a VM continua, fingindo que nada aconteceu.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Esse modelo é chamado de &lt;em&gt;trap and emulate&lt;/em&gt;. Bonito, limpo, quase pedagógico. O tipo de coisa que faz parecer que engenharia de sistemas é uma área habitada por pessoas razoáveis.&lt;/p&gt;
&lt;p&gt;Aí entra o x86 antigo e estraga a festa.&lt;/p&gt;
&lt;p&gt;O problema do x86 clássico era que algumas instruções sensíveis não geravam trap quando executadas sem privilégio. Algumas simplesmente falhavam silenciosamente ou se comportavam de forma diferente. Para um programa comum, isso já seria desagradável. Para um hipervisor, é uma pegadinha arquitetural.&lt;/p&gt;
&lt;p&gt;O hipervisor precisa saber quando o convidado tentou fazer algo que afeta o estado da máquina. Se a CPU não avisa, o convidado pode perceber que não está numa máquina real ou, pior, alterar expectativas internas sem o hipervisor conseguir manter a ilusão.&lt;/p&gt;
&lt;p&gt;A síntese grosseira é esta: o x86 não era “invirtualizável” porque era impossível. Era invirtualizável do jeito bonito.&lt;/p&gt;
&lt;p&gt;E, naturalmente, a indústria olhou para isso e respondeu com a solução mais computacional possível: mais camadas.&lt;/p&gt;
&lt;h2&gt;Hipervisores tipo 1 e tipo 2&lt;/h2&gt;
&lt;p&gt;O Tanenbaum separa hipervisores em dois tipos principais.&lt;/p&gt;
&lt;p&gt;Hipervisor tipo 1 roda diretamente sobre o hardware. Ele é a camada privilegiada principal da máquina. Controla CPU, memória e dispositivos, e hospeda os sistemas convidados acima dele. Exemplos clássicos incluem VMware ESX/ESXi, Xen e Hyper-V.&lt;/p&gt;
&lt;p&gt;Hipervisor tipo 2 roda sobre um sistema operacional hospedeiro. Nesse modelo, existe um sistema operacional normal controlando a máquina física, e o hipervisor funciona como uma aplicação especial acima dele. Exemplos tradicionais incluem VMware Workstation, VirtualBox, Parallels e QEMU em alguns usos.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/virtualizacao-tanenbaum-e-um-louco-genial/hipervisor-tipo-1-e-tipo-2-7e6eb8838a.svg&quot; alt=&quot;Hipervisor tipo 1 e tipo 2&quot; /&gt;&lt;p&gt;A classificação é útil, mas não deve virar religião.&lt;/p&gt;
&lt;p&gt;KVM, por exemplo, embaralha a conversa. Ele transforma o Linux em uma infraestrutura de virtualização usando suporte do kernel e extensões de hardware. QEMU pode fornecer emulação de dispositivos e orquestração em espaço de usuário. libvirt pode gerenciar a bagunça. Virt-manager pode colocar uma interface simpática por cima, porque em algum momento alguém precisa clicar em alguma coisa sem decorar quinze flags.&lt;/p&gt;
&lt;p&gt;Então sim, tipo 1 e tipo 2 são bons conceitos. Mas, na prática, virtualização moderna frequentemente é uma pilha de componentes cooperando. O mundo real raramente respeita as caixinhas perfeitas dos slides. É uma falta de educação, mas acontece bastante.&lt;/p&gt;
&lt;h2&gt;Trap, emulação, tradução binária e paravirtualização&lt;/h2&gt;
&lt;p&gt;Quando o hardware ajuda, o hipervisor pode deixar o sistema convidado executar diretamente e interceptar apenas operações sensíveis. Esse é o mundo bonito do &lt;em&gt;trap and emulate&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Quando o hardware não ajuda, você precisa ser mais criativo. Foi aí que técnicas como tradução binária ficaram importantes.&lt;/p&gt;
&lt;p&gt;Na tradução binária, o hipervisor analisa blocos de código do sistema convidado e substitui instruções problemáticas por sequências seguras. Em vez de esperar a CPU gerar uma exceção que talvez nunca venha, o hipervisor reescreve partes perigosas antes que elas causem problemas.&lt;/p&gt;
&lt;p&gt;É uma ideia meio absurda e brilhante: se o processador não entrega a armadilha que você precisa, você modifica o caminho antes dele chegar lá. É aquele tipo de engenharia que parece gambiarra até virar produto, paper e empresa gigante.&lt;/p&gt;
&lt;p&gt;Outra técnica é a paravirtualização. Nela, o sistema operacional convidado sabe que está virtualizado. Em vez de fingir que está numa máquina real o tempo todo, ele coopera com o hipervisor usando chamadas explícitas, chamadas de &lt;em&gt;hypercalls&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Isso reduz parte do custo de emulação, mas cobra outro preço: o sistema convidado precisa ser adaptado ou ter suporte específico. É mais honesto, mas menos mágico. E, como todo mundo sabe, software honesto demais às vezes perde para software que mente com uma interface melhor.&lt;/p&gt;
&lt;p&gt;Com o tempo, Intel VT-x e AMD-V trouxeram suporte de virtualização por hardware para o x86. Isso permitiu que o processador tivesse modos e estruturas voltadas especificamente para executar convidados de forma mais eficiente e segura. Depois vieram recursos como EPT e NPT para ajudar na virtualização de memória.&lt;/p&gt;
&lt;p&gt;A moral é simples: virtualização começou como uma técnica de software tentando contornar hardware inadequado. Depois o hardware aprendeu o truque e fingiu que sempre esteve tudo sob controle.&lt;/p&gt;
&lt;h2&gt;O custo da virtualização&lt;/h2&gt;
&lt;p&gt;Toda abstração cobra aluguel.&lt;/p&gt;
&lt;p&gt;No caso da virtualização, o custo aparece sempre que o hipervisor precisa intervir. Quando uma VM roda instruções comuns diretamente na CPU, ótimo. Quando acontece uma operação sensível, uma interrupção, uma falha de página, uma operação de E/S ou uma troca de contexto mais complicada, o hipervisor pode precisar assumir.&lt;/p&gt;
&lt;p&gt;Esse evento costuma ser chamado de &lt;em&gt;VM exit&lt;/em&gt;. A CPU sai do modo de execução do convidado e volta para o hipervisor. O hipervisor entende o que aconteceu, decide o que fazer, emula ou autoriza a operação e devolve o controle para a VM.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/virtualizacao-tanenbaum-e-um-louco-genial/o-ped-gio-de-uma-opera-o-sens-vel-aaa5091eef.svg&quot; alt=&quot;O pedágio de uma operação sensível&quot; /&gt;&lt;p&gt;O objetivo de uma virtualização eficiente é reduzir esses pedágios.&lt;/p&gt;
&lt;p&gt;CPU costuma ser a parte menos problemática quando há suporte de hardware. Memória é mais chata. E/S costuma ser a festa do sofrimento.&lt;/p&gt;
&lt;p&gt;A regra prática é: quanto mais o convidado puder executar sem interrupção, melhor. O hipervisor ideal é aquele que quase nunca aparece. É tipo infraestrutura boa: ninguém elogia, mas todo mundo percebe quando fica no caminho.&lt;/p&gt;
&lt;h2&gt;Memória virtual em cima de memória virtual&lt;/h2&gt;
&lt;p&gt;A parte de memória é onde o Tanenbaum começa a parecer um louco genial.&lt;/p&gt;
&lt;p&gt;Em um sistema operacional normal, processos usam endereços virtuais. O kernel mantém tabelas de páginas que traduzem esses endereços virtuais para endereços físicos na RAM. A MMU faz parte dessa tradução em hardware.&lt;/p&gt;
&lt;p&gt;Com virtualização, o sistema convidado também acha que controla a memória física. Só que a “memória física” da VM não é a memória física real. É memória física convidada, que precisa ser mapeada para memória física da máquina hospedeira.&lt;/p&gt;
&lt;p&gt;Então temos uma pilha de traduções:&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/virtualizacao-tanenbaum-e-um-louco-genial/tradu-o-de-mem-ria-em-uma-vm-7ef7eddb38.svg&quot; alt=&quot;Tradução de memória em uma VM&quot; /&gt;&lt;p&gt;Sem suporte especial, uma técnica comum era usar &lt;em&gt;shadow page tables&lt;/em&gt;. O hipervisor mantinha tabelas de páginas sombra que refletiam as intenções do sistema convidado, mas apontavam para a memória real correta. Funcionava, mas era trabalhoso. Sempre que o convidado mudava suas tabelas, o hipervisor precisava acompanhar.&lt;/p&gt;
&lt;p&gt;Depois vieram as tabelas de páginas aninhadas, como EPT no mundo Intel e NPT no mundo AMD. A ideia é deixar o hardware ajudar nas duas traduções: do endereço virtual do processo para o endereço físico do convidado, e do endereço físico do convidado para o endereço físico real.&lt;/p&gt;
&lt;p&gt;Isso reduz bastante o trabalho do hipervisor, mas não elimina todos os custos. TLB, invalidações, caches, páginas grandes, NUMA e overcommit continuam existindo para lembrar que abstração é linda até bater em hardware.&lt;/p&gt;
&lt;p&gt;A frase mais importante dessa seção é: dentro de uma VM, até a memória física é uma abstração.&lt;/p&gt;
&lt;p&gt;Bonito, né? Horrível também.&lt;/p&gt;
&lt;h2&gt;Virtualização de E/S: onde a fantasia apanha&lt;/h2&gt;
&lt;p&gt;Se CPU é relativamente elegante e memória é conceitualmente diabólica, E/S é o setor de achados e perdidos da virtualização.&lt;/p&gt;
&lt;p&gt;Dispositivos são complicados. Placas de rede, discos, controladoras, GPUs, interrupções, DMA, filas, buffers, drivers e firmware entram na conversa. Um sistema operacional espera conversar com hardware real, mas a VM está conversando com uma representação virtual.&lt;/p&gt;
&lt;p&gt;Existem três caminhos principais.&lt;/p&gt;
&lt;p&gt;O primeiro é emular um dispositivo conhecido. O hipervisor apresenta uma placa de rede, uma controladora de disco ou outro dispositivo que o convidado já sabe usar. A vantagem é compatibilidade. A desvantagem é custo. Emular hardware antigo para enganar um sistema moderno é o equivalente computacional de contratar um ator para fingir ser impressora matricial.&lt;/p&gt;
&lt;p&gt;O segundo caminho é usar drivers paravirtualizados. Em vez de fingir um hardware real, o convidado usa um driver feito para conversar com o ambiente virtualizado. VirtIO é o exemplo clássico no ecossistema KVM/QEMU. Isso reduz overhead porque o convidado e o hipervisor param de fingir tanto.&lt;/p&gt;
&lt;p&gt;O terceiro caminho é passthrough. Nesse modelo, um dispositivo real, ou parte dele, é entregue diretamente a uma VM. Tecnologias como IOMMU e SR-IOV ajudam nisso. SR-IOV, por exemplo, permite que um dispositivo PCIe exponha funções virtuais para diferentes VMs.&lt;/p&gt;
&lt;p&gt;O desempenho melhora, mas a flexibilidade piora. Migração fica mais difícil. Isolamento exige mais cuidado. A VM fica mais presa ao hardware real.&lt;/p&gt;
&lt;p&gt;É sempre o mesmo acordo: quanto mais perto do hardware, melhor o desempenho e pior a magia. Quanto mais abstrato, mais portátil e mais caro.&lt;/p&gt;
&lt;h2&gt;Hipervisores são micronúcleos feitos certo?&lt;/h2&gt;
&lt;p&gt;O capítulo levanta uma provocação ótima: hipervisores seriam micronúcleos feitos do jeito certo?&lt;/p&gt;
&lt;p&gt;A comparação faz sentido. Um micronúcleo tenta manter no núcleo apenas o mínimo necessário, movendo serviços para fora da camada privilegiada. Um hipervisor também tenta ser uma camada pequena e poderosa, responsável por isolamento, comunicação e controle de recursos.&lt;/p&gt;
&lt;p&gt;Na paravirtualização, essa semelhança fica ainda mais evidente. O sistema convidado faz &lt;em&gt;hypercalls&lt;/em&gt; para pedir serviços ao hipervisor, um pouco como processos poderiam pedir serviços a servidores em uma arquitetura de micronúcleo.&lt;/p&gt;
&lt;p&gt;Mas a comparação tem limite.&lt;/p&gt;
&lt;p&gt;Micronúcleo é uma proposta de arquitetura de sistema operacional. Hipervisor é uma camada para executar e isolar sistemas operacionais, muitas vezes sem que eles tenham sido projetados para isso. O hipervisor não venceu porque era filosoficamente mais puro. Ele venceu porque rodava sistemas existentes.&lt;/p&gt;
&lt;p&gt;E essa é uma lição brutal de engenharia: compatibilidade frequentemente derrota elegância.&lt;/p&gt;
&lt;p&gt;Você pode ter a arquitetura mais bonita do mundo. Se ela exige reescrever tudo, boa sorte convencendo o mercado. VMware não precisou convencer todo mundo a reescrever seus sistemas. Ele deixou os sistemas acharem que ainda estavam sozinhos na máquina.&lt;/p&gt;
&lt;p&gt;Isso é quase poesia. Poesia com instrução privilegiada e emulação de E/S, mas poesia.&lt;/p&gt;
&lt;h2&gt;Aplicações virtuais e a pré-história do “funciona na minha máquina”&lt;/h2&gt;
&lt;p&gt;O livro também fala de aplicações virtuais: imagens completas contendo sistema operacional, bibliotecas, dependências e aplicação. A ideia é empacotar tudo que uma aplicação precisa para rodar em um ambiente previsível.&lt;/p&gt;
&lt;p&gt;Isso resolve uma dor antiga: dependências.&lt;/p&gt;
&lt;p&gt;Antes de containers dominarem o vocabulário, VMs já eram usadas para distribuir ambientes completos. Em vez de pedir para o usuário instalar biblioteca, runtime, driver, versão específica de compilador e rezar para não quebrar o sistema, você entrega uma imagem.&lt;/p&gt;
&lt;p&gt;É pesado? Sim. Mas funciona.&lt;/p&gt;
&lt;p&gt;Containers mudaram parte dessa conversa porque oferecem um modelo mais leve de empacotamento e isolamento. Só que é importante não confundir as coisas: container não é VM leve. Container compartilha o kernel do host. VM executa seu próprio kernel convidado.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/virtualizacao-tanenbaum-e-um-louco-genial/vm-e-container-n-o-s-o-a-mesma-gambiarra-bbf6cd2e80.svg&quot; alt=&quot;VM e container não são a mesma gambiarra&quot; /&gt;&lt;p&gt;É por isso que microVMs como Firecracker são interessantes: elas tentam ocupar o meio do caminho. Mais isolamento que container tradicional, menos peso que VM convencional. Em outras palavras, porque aparentemente a indústria olhou para duas abstrações e pensou: “faltou uma terceira para confundir melhor”.&lt;/p&gt;
&lt;h2&gt;VMs em CPUs multinúcleo&lt;/h2&gt;
&lt;p&gt;Virtualização fica mais interessante quando entram múltiplos núcleos.&lt;/p&gt;
&lt;p&gt;Uma VM pode ter várias vCPUs. O hipervisor precisa mapear essas vCPUs para CPUs físicas. Isso parece simples até lembrar que sistemas operacionais convidados também têm seus próprios escalonadores. Então existe um escalonador dentro da VM e outro fora dela.&lt;/p&gt;
&lt;p&gt;O convidado acha que está escalonando threads em CPUs disponíveis. O hipervisor está escalonando vCPUs em CPUs reais. Se o host está carregado, uma vCPU pode ser pausada enquanto outra continua. Para o convidado, isso pode parecer uma máquina estranha, meio bêbada, onde CPUs somem temporalmente sem pedir desculpas.&lt;/p&gt;
&lt;p&gt;Isso afeta locks, temporização, desempenho e previsibilidade. Sistemas que assumem controle fino do tempo podem sofrer bastante quando estão virtualizados.&lt;/p&gt;
&lt;p&gt;Na prática, isso explica por que dimensionar VM não é apenas “colocar mais vCPU”. Às vezes mais vCPU piora o desempenho, especialmente se aumenta contenção ou dificulta escalonamento no host. Infraestrutura adora punir soluções intuitivas.&lt;/p&gt;
&lt;h2&gt;Licenciamento: a parte burocrática também morde&lt;/h2&gt;
&lt;p&gt;Tanenbaum dedica uma seção a licenciamento porque virtualização não cria apenas problemas técnicos. Ela também cria perguntas jurídicas e comerciais.&lt;/p&gt;
&lt;p&gt;Se você roda dez VMs com o mesmo sistema operacional, quantas licenças precisa? Se migra uma VM entre hosts, a licença acompanha? Se faz snapshot, clone ou checkpoint, isso conta como nova instância? Se o software licencia por CPU, ele fala de CPU física, socket, core, vCPU ou algum conceito inventado pelo departamento comercial depois de três cafés e um trimestre ruim?&lt;/p&gt;
&lt;p&gt;Virtualização torna cópia e movimentação de ambientes muito mais fáceis. Modelos de licenciamento antigos nem sempre acompanham isso bem.&lt;/p&gt;
&lt;p&gt;Essa parte é menos glamourosa, mas essencial. Em datacenter, muitas decisões de arquitetura são afetadas não apenas por desempenho ou segurança, mas por licença. Sim, às vezes a tabela comercial manda mais que o kernel. É triste, mas pelo menos não é surpreendente.&lt;/p&gt;
&lt;h2&gt;Nuvem: virtualização com API, datacenter e boleto&lt;/h2&gt;
&lt;p&gt;A nuvem entra no capítulo como consequência natural da virtualização.&lt;/p&gt;
&lt;p&gt;Se é possível dividir uma máquina física em várias máquinas virtuais isoladas, também é possível vender essas máquinas sob demanda. O provedor opera o datacenter, compra hardware, gerencia energia, rede, refrigeração, falhas e capacidade. O usuário recebe uma interface para criar recursos quando precisa.&lt;/p&gt;
&lt;p&gt;A definição clássica do NIST descreve cloud computing como acesso sob demanda, via rede, a um conjunto compartilhado de recursos configuráveis que podem ser provisionados e liberados rapidamente. Essa definição é menos sexy que um keynote, mas bem mais útil.&lt;/p&gt;
&lt;p&gt;Modelos comuns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IaaS, infraestrutura como serviço, quando você aluga VMs, redes, discos e recursos básicos;&lt;/li&gt;
&lt;li&gt;PaaS, plataforma como serviço, quando a infraestrutura fica mais escondida e você entrega aplicação;&lt;/li&gt;
&lt;li&gt;SaaS, software como serviço, quando você usa o produto pronto.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Na prática, cloud é virtualização mais automação, rede virtual, armazenamento distribuído, IAM, observabilidade, billing, APIs, regiões, zonas, SLAs e uma quantidade saudável de siglas que parecem criadas para manter consultorias vivas.&lt;/p&gt;
&lt;p&gt;A VM não é a nuvem inteira. Mas sem a ideia de virtualização, a nuvem moderna seria muito menos flexível.&lt;/p&gt;
&lt;h2&gt;Migração de VM: mover a mentira sem acordar o convidado&lt;/h2&gt;
&lt;p&gt;Uma das partes mais elegantes do capítulo é a migração de máquina virtual.&lt;/p&gt;
&lt;p&gt;A ideia é mover uma VM de uma máquina física para outra mantendo a execução. Isso permite manutenção, balanceamento de carga e tolerância a falhas com menos interrupção. Parece mágica, mas é engenharia com cópia de memória, estado de CPU, dispositivos e armazenamento.&lt;/p&gt;
&lt;p&gt;O desafio é que a VM continua modificando memória enquanto você tenta copiá-la. Uma estratégia comum é copiar páginas de memória enquanto a VM ainda roda, rastrear páginas alteradas, copiar de novo as páginas sujas e, no final, pausar brevemente a VM para transferir o estado restante.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/virtualizacao-tanenbaum-e-um-louco-genial/migra-o-viva-de-uma-vm-a00da09fb2.svg&quot; alt=&quot;Migração viva de uma VM&quot; /&gt;&lt;p&gt;A migração viva é um bom exemplo da beleza meio absurda da virtualização: se a máquina já é uma abstração, talvez dê para mover a abstração enquanto ela ainda está sonhando que é hardware.&lt;/p&gt;
&lt;p&gt;Claro, isso exige compatibilidade de CPU, rede, armazenamento e dispositivos. Nada é gratuito. Mas a ideia é poderosa.&lt;/p&gt;
&lt;h2&gt;Checkpointing: salvar o videogame da infraestrutura&lt;/h2&gt;
&lt;p&gt;Checkpointing é o ato de salvar o estado de uma VM para retomar depois.&lt;/p&gt;
&lt;p&gt;Pense em “save state” de emulador, só que para sistemas operacionais inteiros e com implicações muito mais chatas. Um checkpoint pode incluir memória, estado de CPU, dispositivos virtuais e disco, dependendo da implementação.&lt;/p&gt;
&lt;p&gt;Isso é útil para tolerância a falhas, testes, depuração, rollback e manutenção. Também cria problemas interessantes: estado externo pode mudar. Conexões de rede podem expirar. Sistemas distribuídos podem não gostar de descobrir que uma máquina voltou no tempo.&lt;/p&gt;
&lt;p&gt;Snapshot parece simples no painel. Conceitualmente, é uma pequena viagem temporal. E viagem temporal em sistemas distribuídos costuma terminar em bug com cara de possessão demoníaca.&lt;/p&gt;
&lt;h2&gt;VMware: quando o x86 virou um problema de negócios&lt;/h2&gt;
&lt;p&gt;O estudo de caso de VMware é um dos melhores trechos porque mostra a diferença entre teoria e produto.&lt;/p&gt;
&lt;p&gt;Virtualização já existia em mainframes. O problema era fazer isso funcionar bem no x86, uma arquitetura popular, barata e cheia de software existente, mas que não era elegantemente virtualizável no modelo clássico.&lt;/p&gt;
&lt;p&gt;A VMware atacou esse problema com uma combinação de técnicas. O VMware Workstation rodava como aplicação sobre um sistema operacional hospedeiro, aproveitando drivers e suporte do host. Ao mesmo tempo, usava um monitor de máquina virtual para executar o convidado com controle e eficiência.&lt;/p&gt;
&lt;p&gt;A parte genial foi lidar com as instruções problemáticas do x86 usando tradução binária e outras técnicas. Em vez de esperar a arquitetura ficar perfeita, a VMware construiu uma camada capaz de contornar suas falhas práticas.&lt;/p&gt;
&lt;p&gt;Depois, com ESX Server, a VMware levou a ideia para o datacenter. Em vez de rodar uma aplicação por servidor físico, empresas podiam consolidar múltiplas VMs no mesmo hardware. Isso reduzia subutilização, simplificava provisionamento e permitia recursos como migração viva.&lt;/p&gt;
&lt;p&gt;Essa mudança parece óbvia hoje, mas era enorme. Antes, comprar servidor físico para cada aplicação era comum. Com virtualização, servidor virou pool de recursos.&lt;/p&gt;
&lt;p&gt;É uma das grandes viradas da infraestrutura moderna: o hardware deixou de ser o lugar fixo onde o sistema mora e virou capacidade alocável.&lt;/p&gt;
&lt;h2&gt;O que o capítulo ainda ensina muito bem&lt;/h2&gt;
&lt;p&gt;Mesmo sendo uma edição de 2015/2016, a base conceitual do capítulo continua excelente.&lt;/p&gt;
&lt;p&gt;KVM, QEMU, Firecracker, Nitro, containers, Kubernetes, confidential computing e afins mudaram o cenário, mas não invalidaram os conceitos. Pelo contrário: eles ficam mais fáceis de entender quando você já compreende hipervisor, trap, emulação, memória virtual, E/S e isolamento.&lt;/p&gt;
&lt;p&gt;O que mudou foi a pilha ao redor.&lt;/p&gt;
&lt;p&gt;Hoje, virtualização está em clouds públicas, clusters privados, desktops de desenvolvimento, CI, sandboxes, plataformas serverless, ambientes de segurança e até em runtimes que tentam parecer containers. A ideia saiu do mainframe, passou pelo desktop, dominou o datacenter e voltou disfarçada em microVM.&lt;/p&gt;
&lt;p&gt;O vocabulário mudou. A mentira continuou.&lt;/p&gt;
&lt;h2&gt;O ponto central&lt;/h2&gt;
&lt;p&gt;Virtualização não é apenas rodar um sistema dentro de outro. É uma técnica para transformar recursos físicos em interfaces controladas, isoladas e multiplexadas.&lt;/p&gt;
&lt;p&gt;Ela depende de uma negociação constante entre ilusão e controle. O convidado precisa acreditar que manda. O hipervisor precisa garantir que ele não manda demais. O hardware precisa ajudar. A memória precisa ser traduzida duas vezes sem virar uma tragédia. A E/S precisa funcionar sem transformar cada pacote de rede em uma novela. O licenciamento precisa não arruinar a arquitetura. A nuvem precisa vender tudo isso como se fosse simples.&lt;/p&gt;
&lt;p&gt;E, de alguma forma, tudo isso funciona bem o suficiente para sustentar boa parte da computação moderna.&lt;/p&gt;
&lt;p&gt;Essa é a genialidade do capítulo do Tanenbaum: ele pega um termo que muita gente usa de forma rasa e mostra a pilha inteira de problemas escondida por baixo. CPU, memória, E/S, hipervisor, nuvem, VMware, migração, checkpointing. Tudo conectado.&lt;/p&gt;
&lt;p&gt;No fim, virtualização é uma mentira bem implementada. E como toda boa mentira em computação, quando funciona direito, vira abstração.&lt;/p&gt;
&lt;h2&gt;Referências e leituras recomendadas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pearson.com/&quot;&gt;Sistemas Operacionais Modernos, Andrew S. Tanenbaum e Herbert Bos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cs.cornell.edu/courses/cs6411/2018sp/papers/popek-goldberg.pdf&quot;&gt;Formal Requirements for Virtualizable Third Generation Architectures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.kernel.org/virt/kvm/index.html&quot;&gt;Documentação de virtualização KVM no kernel Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.qemu.org/&quot;&gt;QEMU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://csrc.nist.gov/pubs/sp/800/145/final&quot;&gt;NIST SP 800-145, definição de cloud computing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://firecracker-microvm.github.io/&quot;&gt;Firecracker MicroVM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://aws.amazon.com/ec2/nitro/&quot;&gt;AWS Nitro System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://katacontainers.io/&quot;&gt;Kata Containers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Rust: o culto da ferrugem</title><link>https://blog.kristyan.dev/posts/rust-o-culto-da-ferrugem</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/rust-o-culto-da-ferrugem</guid><description>Rust resolve problemas reais de segurança de memória, mas transformar a linguagem em religião técnica é só trocar uma classe de bug por uma classe nova de ilusão.</description><pubDate>Tue, 07 Jul 2026 02:50:00 GMT</pubDate><content:encoded>&lt;p&gt;Rust é uma ótima linguagem. O problema é que parte da comunidade fala dela como se fosse uma intervenção divina no desenvolvimento de software.&lt;/p&gt;
&lt;p&gt;Você menciona C, alguém responde Rust. Você menciona C++, alguém responde Rust. Você menciona Go, GC, kernel, CLI, banco de dados, proxy reverso, terminal, torradeira, air fryer ou sistema de votação de condomínio, alguém aparece com a mesma liturgia: reescreve em Rust.&lt;/p&gt;
&lt;p&gt;E aí mora o problema.&lt;/p&gt;
&lt;p&gt;Não porque Rust seja ruim. Pelo contrário. Rust é uma das linguagens mais interessantes que surgiram nas últimas décadas para programação de sistemas. O modelo de ownership, borrowing e lifetimes resolve problemas reais. A ausência de garbage collector abre espaço para aplicações onde latência previsível importa. O ecossistema tem tooling excelente, uma comunidade ativa e adoção crescente em projetos grandes.&lt;/p&gt;
&lt;p&gt;Mas linguagem nenhuma transforma código ruim em código bom por osmose. Trocar C, C++, Go ou qualquer outra coisa por Rust não elimina arquitetura ruim, domínio mal entendido, API mal desenhada, dependência demais, abstração demais, benchmark mentiroso, build quebrado, maintainer cansado ou time que não sabe por que está migrando.&lt;/p&gt;
&lt;p&gt;Rust é ferramenta. O culto em volta dela é outra coisa.&lt;/p&gt;
&lt;h2&gt;O problema não é Rust, é a fé no compilador&lt;/h2&gt;
&lt;p&gt;O grande trunfo de Rust está no modelo de ownership. Cada valor tem um dono, referências precisam obedecer regras de empréstimo e o compilador tenta impedir acessos inválidos em tempo de compilação. A própria documentação oficial descreve ownership como o recurso mais característico da linguagem, justamente porque permite garantias de segurança de memória sem depender de garbage collector.&lt;/p&gt;
&lt;p&gt;Isso é enorme.&lt;/p&gt;
&lt;p&gt;Use-after-free, double free, data races e vários erros comuns de C e C++ deixam de ser algo que você precisa caçar no escuro depois que o processo explode em produção. O compilador vira uma espécie de colega chato, só que útil. Ele reclama cedo, reclama bastante e, em muitos casos, impede que uma classe inteira de bugs chegue ao binário.&lt;/p&gt;
&lt;p&gt;Só que isso não é a mesma coisa que dizer que o programa está correto.&lt;/p&gt;
&lt;p&gt;Rust não valida sua regra de negócio. Rust não sabe se seu cache invalida no momento certo. Rust não sabe se sua query está matando o banco. Rust não sabe se seu protocolo foi desenhado por alguém que confundiu simplicidade com ausência de requisitos. Rust não sabe se sua arquitetura virou um prato de macarrão com generics.&lt;/p&gt;
&lt;p&gt;O compilador impede muita besteira. Ele não impede todas as besteiras. Infelizmente, programador é uma fonte renovável de criatividade destrutiva.&lt;/p&gt;
&lt;h2&gt;Borrowing e ownership não são magia, são trade-offs&lt;/h2&gt;
&lt;p&gt;Uma parte do discurso pró-Rust costuma vender ownership como se fosse apenas benefício. E sim, existe um benefício claro: a linguagem força você a pensar em quem possui um dado, quem pode modificar esse dado e por quanto tempo uma referência pode existir.&lt;/p&gt;
&lt;p&gt;Isso é muito melhor do que sair passando ponteiro mutável para todo lado e rezar para ninguém pisar no mesmo terreno ao mesmo tempo.&lt;/p&gt;
&lt;p&gt;Mas essa segurança não vem de graça. O custo muda de lugar.&lt;/p&gt;
&lt;p&gt;Em linguagens com garbage collector, parte do custo vai para o runtime. Você aceita pausas, overhead de memória, comportamento do coletor e uma relação diferente com alocação. Em C e C++, parte do custo vai para disciplina manual, tooling, sanitizers, revisão e experiência. Em Rust, uma parte relevante do custo vai para o modelo mental.&lt;/p&gt;
&lt;p&gt;Você precisa entender ownership. Precisa entender borrowing. Precisa entender lifetimes, mesmo quando eles são inferidos. Precisa entender quando usar &lt;code&gt;Box&lt;/code&gt;, &lt;code&gt;Rc&lt;/code&gt;, &lt;code&gt;Arc&lt;/code&gt;, &lt;code&gt;RefCell&lt;/code&gt;, &lt;code&gt;Mutex&lt;/code&gt;, &lt;code&gt;Cow&lt;/code&gt;, slices, iteradores, traits, generics e aquele tipo com assinatura que parece ter sido produzido por uma impressora com raiva.&lt;/p&gt;
&lt;p&gt;E, claro, você precisa aceitar que às vezes o compilador está certo, mas sua vontade de terminar a task na sexta-feira às 17h também parecia muito convincente.&lt;/p&gt;
&lt;p&gt;Essa é a parte que o culto ignora: Rust não remove complexidade. Ele explicita complexidade. Em muitos casos isso é ótimo. Em outros, isso transforma uma operação simples em uma negociação diplomática com o borrow checker.&lt;/p&gt;
&lt;h2&gt;Sem garbage collector não significa automaticamente rápido&lt;/h2&gt;
&lt;p&gt;Outra confusão comum: Rust não tem garbage collector, logo Rust é rápido, logo qualquer coisa em Rust é melhor.&lt;/p&gt;
&lt;p&gt;Não é bem assim.&lt;/p&gt;
&lt;p&gt;Ausência de GC remove uma fonte específica de custo e imprevisibilidade. Isso pode ser decisivo em software de baixa latência, sistemas embarcados, componentes de infraestrutura, engines, parsers, proxies, kernels, drivers e bibliotecas que precisam ser chamadas de outros ambientes sem carregar um runtime junto.&lt;/p&gt;
&lt;p&gt;Mas performance não nasce apenas da linguagem. Performance nasce de dados, acesso à memória, algoritmo, contenção, I/O, alocação, layout, concorrência, cache locality, syscalls, protocolo, serialização, banco de dados e de uma longa lista de coisas que não cabem num post sem virar punição judicial.&lt;/p&gt;
&lt;p&gt;Um algoritmo ruim em Rust continua sendo ruim. Uma estrutura de dados mal escolhida continua custando caro. Um serviço dominado por latência de rede não vira um foguete só porque a função que monta JSON agora compila para binário nativo. Um sistema que passa 80% do tempo esperando o banco não vai ganhar iluminação espiritual porque o backend foi ungido com &lt;code&gt;cargo build --release&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Rust pode ajudar muito. Mas se o gargalo está em outro lugar, a linguagem vira cosmético caro.&lt;/p&gt;
&lt;p&gt;Bonito no README, triste no Grafana.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;unsafe&lt;/code&gt; é o lembrete de que o mundo real existe&lt;/h2&gt;
&lt;p&gt;Outro ponto importante: Rust tem &lt;code&gt;unsafe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Isso não invalida Rust. Muito pelo contrário. Sem &lt;code&gt;unsafe&lt;/code&gt;, Rust não conseguiria fazer várias coisas que uma linguagem de sistemas precisa fazer: interagir com C, lidar com ponteiros crus, acessar hardware, implementar certas estruturas de baixo nível e construir abstrações que o compilador não consegue provar sozinho.&lt;/p&gt;
&lt;p&gt;A documentação oficial é clara: &lt;code&gt;unsafe&lt;/code&gt; dá poderes extras, mas também coloca responsabilidade extra no programador. Ele não desliga todo o borrow checker, mas permite operações que o compilador não consegue garantir como memory safe.&lt;/p&gt;
&lt;p&gt;Na prática, isso significa que Rust seguro é uma coisa. Rust com blocos &lt;code&gt;unsafe&lt;/code&gt;, FFI, dependências nativas e abstrações mal auditadas é outra.&lt;/p&gt;
&lt;p&gt;Além disso, Rust também permite vazamento de memória em safe Rust. Ciclos com &lt;code&gt;Rc&lt;/code&gt; e &lt;code&gt;RefCell&lt;/code&gt;, por exemplo, podem manter objetos vivos para sempre se o grafo de referências for desenhado errado. Isso é memory safe, mas ainda é bug. O programa não acessa memória inválida, apenas carrega lixo vivo com muita segurança e educação.&lt;/p&gt;
&lt;p&gt;Rust reduz brutalmente o espaço de erro em memória. Mas não torna o programador imune à física, ao domínio ou à própria arrogância.&lt;/p&gt;
&lt;h2&gt;Os casos reais são mais interessantes que o hype&lt;/h2&gt;
&lt;p&gt;O jeito mais honesto de defender Rust não é falar “reescreva tudo”. É olhar para como projetos grandes realmente adotaram Rust.&lt;/p&gt;
&lt;p&gt;O Discord reescreveu o serviço Read States de Go para Rust porque tinha um problema concreto: picos de latência associados ao comportamento do garbage collector em um serviço de hot path. A troca funcionou bem, reduziu picos e melhorou métricas. Mas o detalhe mais importante do próprio post do Discord é outro: eles dizem que consideram Rust quando faz sentido. Não como mandamento universal.&lt;/p&gt;
&lt;p&gt;A Cloudflare criou o Pingora em Rust para substituir uma arquitetura baseada em NGINX e Lua em um ponto crítico da infraestrutura. O resultado divulgado foi forte: menos CPU, menos memória e mais controle sobre o proxy. Mas de novo, não foi “pegamos qualquer serviço aleatório e colocamos Rust porque sim”. Era um componente específico, com requisitos específicos, em uma empresa que sabe medir carga real.&lt;/p&gt;
&lt;p&gt;O Dropbox reescreveu o núcleo do mecanismo de sync no projeto Nucleus usando Rust. Só que o próprio relato deixa claro que a decisão não foi leviana. O problema era complexo, antigo, cheio de invariantes difíceis, e Rust ajudou tanto pela performance quanto pela capacidade de expressar correção e controlar estado.&lt;/p&gt;
&lt;p&gt;O Android introduziu Rust em partes novas e sensíveis à segurança. O Chromium passou a suportar bibliotecas Rust de terceiros a partir de C++, mas com limitações bem explícitas: APIs estreitas, interoperabilidade controlada e nada de deixar Rust entrar de qualquer jeito no meio de um grafo gigante de ponteiros C++.&lt;/p&gt;
&lt;p&gt;O kernel Linux também abriu espaço para Rust, mas de forma incremental. Não existe um plano sério de acordar amanhã e descobrir que o kernel virou um projeto Rust com uma pasta &lt;code&gt;legacy_c&lt;/code&gt; escondida no canto. A adoção é gradual, discutida, politicamente difícil e tecnicamente cheia de implicações.&lt;/p&gt;
&lt;p&gt;Esses casos mostram o contrário do culto.&lt;/p&gt;
&lt;p&gt;Mostram que Rust funciona muito bem quando existe um motivo técnico forte, uma fronteira clara, métricas reais, equipe capaz e integração cuidadosa com o legado.&lt;/p&gt;
&lt;h2&gt;Reescrever tudo é a fantasia favorita de quem nunca manteve o &quot;tudo&quot;&lt;/h2&gt;
&lt;p&gt;A frase “reescreve em Rust” é sedutora porque reescrita é a forma mais socialmente aceitável de procrastinar manutenção.&lt;/p&gt;
&lt;p&gt;Todo sistema legado parece horroroso por dentro. E quase sempre ele é mesmo. Tem camada esquecida, decisão histórica, comportamento não documentado, função que ninguém apaga porque uma integração misteriosa depende dela, bug que virou feature e feature que deveria ser crime.&lt;/p&gt;
&lt;p&gt;A tentação é olhar para isso e pensar: agora faremos direito.&lt;/p&gt;
&lt;p&gt;Só que “fazer direito” raramente sobrevive ao primeiro contato com o domínio real.&lt;/p&gt;
&lt;p&gt;O código antigo carrega conhecimento acumulado. Nem todo conhecimento está bonito, testado ou documentado. Muitas vezes ele está codificado em ifs constrangedores, nomes ruins e comentários que começam com “não remover”. Uma reescrita completa joga fora bugs antigos, mas também joga fora correções antigas. Troca dívida técnica conhecida por dívida técnica nova, só que com camiseta bonita e mascote de caranguejo.&lt;/p&gt;
&lt;p&gt;Rust ajuda quando o problema é segurança de memória, concorrência difícil, performance crítica ou necessidade de integração nativa sem runtime pesado. Rust atrapalha quando a equipe não domina a linguagem, quando o build vira um inferno, quando a fronteira com o legado é larga demais ou quando o projeto está apenas tentando resolver crise existencial com ferramenta nova.&lt;/p&gt;
&lt;p&gt;A pergunta não deveria ser “dá para escrever em Rust?”. Quase sempre dá.&lt;/p&gt;
&lt;p&gt;A pergunta deveria ser: “qual problema real isso resolve, qual custo adiciona e quem vai manter isso daqui a três anos?”.&lt;/p&gt;
&lt;p&gt;Essa pergunta é menos divertida. Por isso aparece menos em thread.&lt;/p&gt;
&lt;h2&gt;WD-40 e o outro culto&lt;/h2&gt;
&lt;p&gt;Do outro lado da ferrugem também existe teatro.&lt;/p&gt;
&lt;p&gt;As iniciativas e forks que se vendem como “sem Rust”, às vezes embalados na piada do WD-40, são uma reação previsível. A brincadeira funciona porque Rust significa ferrugem, WD-40 remove ferrugem e a internet nunca perdeu uma oportunidade de transformar discordância técnica em adesivo de notebook.&lt;/p&gt;
&lt;p&gt;Mas existe um ponto legítimo no meio da piada.&lt;/p&gt;
&lt;p&gt;Adicionar Rust a um projeto grande não é apenas adicionar uma linguagem. É adicionar uma toolchain, um gerenciador de pacotes, um modelo de build, uma política de dependências, uma história de bootstrap, compatibilidade com arquiteturas, empacotamento em distribuições, suporte para sistemas antigos e uma camada nova de conhecimento para maintainers.&lt;/p&gt;
&lt;p&gt;Para quem mantém distribuição, sistema legado, plataforma exótica ou projeto com política conservadora de dependências, isso importa. Não é só birra.&lt;/p&gt;
&lt;p&gt;Ao mesmo tempo, “remover Rust porque Rust” pode virar o mesmo tipo de culto invertido. Se um componente em Rust resolve uma classe real de bug, tem interface pequena, build reprodutível e manutenção ativa, arrancar aquilo só para preservar pureza ideológica também é engenharia ruim.&lt;/p&gt;
&lt;p&gt;O culto pró-Rust e o culto anti-Rust têm mais em comum do que gostariam de admitir. Os dois começam pela identidade e só depois procuram argumento técnico.&lt;/p&gt;
&lt;h2&gt;Segurança de memória importa, mas segurança não termina nela&lt;/h2&gt;
&lt;p&gt;É impossível falar de Rust sem falar de segurança de memória. E aqui os defensores da linguagem têm um argumento forte.&lt;/p&gt;
&lt;p&gt;Uma quantidade absurda de vulnerabilidades históricas em sistemas escritos em C e C++ vem de problemas como out-of-bounds read, out-of-bounds write, use-after-free e outros erros de acesso à memória. Rust ataca exatamente esse território. Não é marketing vazio.&lt;/p&gt;
&lt;p&gt;Mas segurança não é uma coluna booleana chamada &lt;code&gt;memory_safe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Você ainda pode ter autenticação quebrada. Autorização ruim. Injeção. SSRF. Race condition lógica. Criptografia mal usada. Dependência comprometida. Build pipeline frágil. Segredo vazado. Configuração aberta. Política de atualização inexistente. Maintainer burnout. Supply chain com quinhentos crates que ninguém auditou.&lt;/p&gt;
&lt;p&gt;Rust reduz uma classe de problema. Uma classe importante, mas uma classe.&lt;/p&gt;
&lt;p&gt;Transformar isso em “Rust é seguro” é preguiça técnica. O correto é dizer: Rust oferece garantias fortes contra várias falhas de memória em código seguro, mas o sistema final ainda depende de arquitetura, revisão, testes, dependências, deploy, observabilidade e manutenção.&lt;/p&gt;
&lt;p&gt;Menos slogan, mais engenharia.&lt;/p&gt;
&lt;h2&gt;O ecossistema também tem custo&lt;/h2&gt;
&lt;p&gt;Cargo é excelente. Talvez uma das melhores experiências de tooling que uma linguagem moderna oferece. Criar projeto, rodar teste, formatar, publicar pacote e gerenciar dependências é muito melhor em Rust do que em muito ecossistema mais antigo.&lt;/p&gt;
&lt;p&gt;Mas todo ecossistema com dependências fáceis também cria o risco de dependências fáceis demais.&lt;/p&gt;
&lt;p&gt;Crates pequenos resolvem problemas pequenos. Crates demais criam árvores grandes. Árvores grandes criam superfície de supply chain, custo de auditoria, risco de abandono, conflitos de versão e aquele momento bonito em que uma biblioteca simples para lidar com string puxa metade da civilização ocidental.&lt;/p&gt;
&lt;p&gt;Isso não é exclusivo de Rust. Digo com propriedade: JavaScript já mostrou esse filme em versão estendida, com cenas pós-créditos e trauma coletivo.&lt;/p&gt;
&lt;p&gt;Mas Rust não está imune.&lt;/p&gt;
&lt;p&gt;Se o argumento para sair de C ou C++ é segurança, faz pouco sentido entrar em Rust ignorando procedência, manutenção e auditoria das dependências. Trocar buffer overflow por pacote abandonado não é exatamente evolução da espécie.&lt;/p&gt;
&lt;h2&gt;Go, Java, C# e C++ não desapareceram porque Rust existe&lt;/h2&gt;
&lt;p&gt;Outra coisa que o culto costuma ignorar: outras linguagens também fazem escolhas coerentes.&lt;/p&gt;
&lt;p&gt;Go aceita um runtime simples, garbage collector e uma linguagem menos expressiva para ganhar produtividade, build rápido, deploy fácil e simplicidade operacional. Para muita API, serviço interno, ferramenta de infraestrutura e sistema de rede, isso é uma troca excelente.&lt;/p&gt;
&lt;p&gt;Java e C# têm runtimes pesados, mas também têm ecossistemas maduros, tooling absurdo, GCs sofisticados, observabilidade excelente e décadas de batalha em produção. Dá para fazer software horrível nelas, obviamente. Também dá para sustentar sistemas gigantes com produtividade alta.&lt;/p&gt;
&lt;p&gt;C++ continua sendo uma monstruosidade poderosa. É fácil criticar C++, e muitas críticas são merecidas, mas a quantidade de software crítico, rápido e sofisticado escrito nele não desaparece porque Rust tem um compilador mais protetor.&lt;/p&gt;
&lt;p&gt;Rust entra muito bem onde você quer controle baixo nível, segurança de memória sem GC, binário nativo e possibilidade de expressar invariantes fortes no tipo. Isso não torna todas as outras escolhas burras. Torna Rust uma escolha boa para certos problemas.&lt;/p&gt;
&lt;p&gt;O nome disso é trade-off. Uma palavra que fanboy normalmente trata como ofensa pessoal.&lt;/p&gt;
&lt;h2&gt;A pergunta certa para adotar Rust&lt;/h2&gt;
&lt;p&gt;Antes de colocar Rust em uma codebase existente, algumas perguntas valem mais do que qualquer benchmark de blog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;O problema real é segurança de memória, latência, consumo de memória ou concorrência?&lt;/li&gt;
&lt;li&gt;O componente pode ser isolado por uma interface pequena?&lt;/li&gt;
&lt;li&gt;A equipe sabe Rust o suficiente para manter o código depois da empolgação inicial?&lt;/li&gt;
&lt;li&gt;O build, empacotamento e CI suportam essa toolchain sem virar gambiarra permanente?&lt;/li&gt;
&lt;li&gt;As dependências serão auditadas?&lt;/li&gt;
&lt;li&gt;Existe teste suficiente para provar que a versão nova preserva comportamento antigo?&lt;/li&gt;
&lt;li&gt;O ganho esperado foi medido ou só imaginado?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Se a resposta for boa, Rust pode ser uma excelente escolha.&lt;/p&gt;
&lt;p&gt;Se a resposta for “porque Rust é mais seguro”, “porque está todo mundo usando” ou “porque C++ é feio”, talvez o problema não esteja na linguagem antiga. Talvez esteja na falta de critério.&lt;/p&gt;
&lt;p&gt;E falta de critério compila em qualquer linguagem.&lt;/p&gt;
&lt;h2&gt;Rust não precisa de culto&lt;/h2&gt;
&lt;p&gt;O mais irônico é que Rust não precisa desse culto.&lt;/p&gt;
&lt;p&gt;A linguagem já tem méritos técnicos suficientes. Ela não precisa ser vendida como bala de prata, substituta universal, purificação de codebase ou caminho espiritual para transcender o garbage collector.&lt;/p&gt;
&lt;p&gt;Rust é boa porque força clareza sobre propriedade, reduz riscos de memória, permite performance previsível, entrega tooling decente e torna certas classes de erro muito mais difíceis. Isso já é bastante coisa.&lt;/p&gt;
&lt;p&gt;Quando alguém exagera e diz que tudo deveria ser Rust, enfraquece o próprio argumento. Porque quem mantém software de verdade sabe que tecnologia boa também tem custo. Sabe que migração dói. Sabe que build importa. Sabe que equipe importa. Sabe que legado não é só código velho, é conhecimento acumulado em estado bruto.&lt;/p&gt;
&lt;p&gt;O culto da ferrugem tenta transformar uma linguagem excelente em religião técnica.&lt;/p&gt;
&lt;p&gt;Eu prefiro tratar Rust como ferramenta. Uma ferramenta muito boa, muitas vezes melhor que as alternativas, mas ainda uma ferramenta.&lt;/p&gt;
&lt;p&gt;Porque no fim, código ruim em Rust continua sendo código ruim.&lt;/p&gt;
&lt;p&gt;Só que agora ele compila com mais dignidade.&lt;/p&gt;
&lt;h2&gt;Referências&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html&quot;&gt;The Rust Programming Language: Understanding Ownership&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html&quot;&gt;The Rust Programming Language: Unsafe Rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doc.rust-lang.org/book/ch15-06-reference-cycles.html&quot;&gt;The Rust Programming Language: Reference Cycles Can Leak Memory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://discord.com/blog/why-discord-is-switching-from-go-to-rust&quot;&gt;Discord: Why Discord is switching from Go to Rust&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.cloudflare.com/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet/&quot;&gt;Cloudflare: How we built Pingora&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dropbox.tech/infrastructure/rewriting-the-heart-of-our-sync-engine&quot;&gt;Dropbox: Rewriting the heart of our sync engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://security.googleblog.com/2022/12/memory-safe-languages-in-android-13.html&quot;&gt;Google Security Blog: Memory Safe Languages in Android 13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://security.googleblog.com/2023/01/supporting-use-of-rust-in-chromium.html&quot;&gt;Google Security Blog: Supporting the Use of Rust in the Chromium Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.kernel.org/rust/&quot;&gt;Linux Kernel Documentation: Rust&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Unixnomicon: um glossário do kernel aos containers</title><link>https://blog.kristyan.dev/posts/unixnomicon-um-glossario-do-kernel-aos-containers</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/unixnomicon-um-glossario-do-kernel-aos-containers</guid><description>Um glossário sobre Unix e sistemas Unix-like &apos;feito nas coxa&apos;, com foco em Linux, para entender os termos que aparecem em tutoriais, logs, man pages e discussões técnicas.</description><pubDate>Sun, 05 Jul 2026 02:30:00 GMT</pubDate><content:encoded>&lt;p&gt;O primeiro problema de aprender Linux não é o terminal. É o vocabulário.&lt;/p&gt;
&lt;p&gt;Você instala uma distribuição, alguém chama tudo de Linux, outra pessoa corrige dizendo que Linux é só o kernel, um tutorial manda montar um filesystem, o log reclama de uma unit, o Docker fala de namespaces e, quando você percebe, está tentando entender cinco camadas diferentes com palavras que parecem ter sido escolhidas para confundir iniciantes.&lt;/p&gt;
&lt;p&gt;Este texto é um glossário para consultar quando algum termo aparecer num tutorial, numa mensagem de erro, numa discussão técnica ou naquela configuração copiada às duas da manhã que “funciona até parar de funcionar”. Não é uma enciclopédia de todos os comandos existentes. A ideia é explicar os conceitos que realmente conectam as peças do sistema.&lt;/p&gt;
&lt;p&gt;A ordem não é alfabética. Ela acompanha a forma como o Linux é montado: hardware, kernel, userspace, processos, arquivos, shell, pacotes, rede, segurança e isolamento. Os termos mais básicos aparecem primeiro; os avançados vêm quando já existe contexto suficiente para não parecer magia negra.&lt;/p&gt;
&lt;h2&gt;Linux não é uma coisa só&lt;/h2&gt;
&lt;p&gt;Quando alguém diz “Linux”, pode estar falando do kernel, de uma distribuição inteira, de um servidor, de um desktop ou de uma família de sistemas. Tecnicamente são coisas diferentes. Na conversa cotidiana, quase ninguém para para especificar, e tudo bem, desde que você saiba qual camada está sendo discutida.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/unixnomicon-um-glossario-do-kernel-aos-containers/as-camadas-de-um-sistema-linux-92bf9143f1.svg&quot; alt=&quot;As camadas de um sistema Linux&quot; /&gt;&lt;h3&gt;Linux&lt;/h3&gt;
&lt;p&gt;Em sentido estrito, Linux é o kernel iniciado por Linus Torvalds em 1991. Ele gerencia CPU, memória, processos, dispositivos, rede, sistemas de arquivos e a comunicação entre programas e hardware.&lt;/p&gt;
&lt;p&gt;No uso cotidiano, “Linux” também virou o nome informal dos sistemas construídos ao redor desse kernel. A precisão importa quando a discussão é técnica; em conversa normal, corrigir toda pessoa que fala “Linux” costuma produzir mais barulho do que conhecimento.&lt;/p&gt;
&lt;h3&gt;GNU/Linux&lt;/h3&gt;
&lt;p&gt;GNU/Linux é o nome usado para destacar que muitas distribuições combinam o kernel Linux com ferramentas e bibliotecas do projeto GNU, como Bash, glibc e Coreutils.&lt;/p&gt;
&lt;p&gt;A ressalva importante é que nem todo sistema baseado no kernel Linux usa esse conjunto. Alpine Linux, por exemplo, é conhecido por usar musl e BusyBox; Android usa o kernel Linux, mas tem um userspace bastante diferente de uma distribuição tradicional. “GNU/Linux” é correto para muitos sistemas, não uma fórmula universal para qualquer coisa que inicialize o kernel.&lt;/p&gt;
&lt;h3&gt;Distribuição ou distro&lt;/h3&gt;
&lt;p&gt;Uma distribuição combina o kernel com instalador, gerenciador de pacotes, repositórios, bibliotecas, serviços, configurações padrão e políticas de manutenção.&lt;/p&gt;
&lt;p&gt;Debian, Fedora, Ubuntu, Arch Linux, openSUSE e Alpine não são apenas “temas diferentes”. Elas tomam decisões diferentes sobre atualização, empacotamento, estabilidade, segurança, init, versões de bibliotecas e responsabilidade do usuário.&lt;/p&gt;
&lt;h3&gt;Kernel&lt;/h3&gt;
&lt;p&gt;O kernel é o núcleo privilegiado do sistema. Aplicações comuns não acessam hardware diretamente; elas pedem ao kernel operações como abrir arquivos, criar processos, reservar memória ou enviar dados pela rede.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://docs.kernel.org/&quot;&gt;documentação oficial do kernel&lt;/a&gt; é enorme porque “o kernel” não é um bloco simples. Ele reúne subsistemas de escalonamento, memória virtual, rede, drivers, VFS, segurança, virtualização e muito mais.&lt;/p&gt;
&lt;h3&gt;Userspace&lt;/h3&gt;
&lt;p&gt;Userspace é tudo que roda fora do espaço privilegiado do kernel: shells, serviços, bibliotecas, servidores, ambientes gráficos e aplicações.&lt;/p&gt;
&lt;p&gt;Essa separação é uma das fronteiras mais importantes do sistema. Um navegador travando normalmente derruba o navegador. Um erro grave dentro do kernel pode comprometer ou parar a máquina inteira.&lt;/p&gt;
&lt;h3&gt;System call ou syscall&lt;/h3&gt;
&lt;p&gt;Uma system call é uma entrada controlada do userspace para o kernel. &lt;code&gt;openat()&lt;/code&gt;, &lt;code&gt;read()&lt;/code&gt;, &lt;code&gt;write()&lt;/code&gt;, &lt;code&gt;fork()&lt;/code&gt;, &lt;code&gt;execve()&lt;/code&gt; e &lt;code&gt;mmap()&lt;/code&gt; são exemplos.&lt;/p&gt;
&lt;p&gt;Quando você executa &lt;code&gt;cat arquivo.txt&lt;/code&gt;, o &lt;code&gt;cat&lt;/code&gt; não “lê o disco” sozinho. Ele solicita ao kernel que abra e leia o arquivo. Ferramentas como &lt;code&gt;strace&lt;/code&gt; permitem observar essa conversa, o que é extremamente útil quando um programa falha sem explicar direito o motivo.&lt;/p&gt;
&lt;h3&gt;Módulo do kernel&lt;/h3&gt;
&lt;p&gt;Um módulo é um trecho de código que pode ser carregado ou removido do kernel em tempo de execução. Muitos drivers, filesystems e recursos opcionais são distribuídos dessa forma.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lsmod&lt;/code&gt; lista módulos carregados e &lt;code&gt;modprobe&lt;/code&gt; carrega ou remove módulos respeitando dependências. Módulo não é sinônimo de driver, embora muitos drivers sejam módulos.&lt;/p&gt;
&lt;h3&gt;Driver&lt;/h3&gt;
&lt;p&gt;Driver é o código que permite ao sistema controlar um dispositivo ou uma classe de dispositivos. Ele pode estar compilado diretamente no kernel, carregado como módulo ou, em alguns casos, ter partes no userspace.&lt;/p&gt;
&lt;p&gt;Quando uma placa “não funciona no Linux”, o problema real pode estar no driver, no firmware, na versão do kernel, na configuração do dispositivo ou no suporte incompleto do fabricante. “Linux não reconheceu” é apenas o resumo menos útil da história.&lt;/p&gt;
&lt;h3&gt;Firmware&lt;/h3&gt;
&lt;p&gt;Firmware é software executado pelo próprio dispositivo ou por controladores próximos ao hardware. Placas Wi-Fi, GPUs, SSDs e outros componentes frequentemente precisam de blobs de firmware carregados durante a inicialização.&lt;/p&gt;
&lt;p&gt;O driver ensina o kernel a conversar com o dispositivo; o firmware ajuda o dispositivo a saber o que fazer. São peças relacionadas, mas diferentes.&lt;/p&gt;
&lt;h2&gt;Do botão de ligar até o seu shell&lt;/h2&gt;
&lt;p&gt;O boot parece simples enquanto funciona. Quando quebra, aparecem UEFI, GRUB, initramfs, kernel parameters, root filesystem, PID 1 e emergency shell no mesmo minuto. O fluxo abaixo reduz isso ao essencial.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/unixnomicon-um-glossario-do-kernel-aos-containers/fluxo-simplificado-de-boot-no-linux-a7c2f9b8fc.svg&quot; alt=&quot;Fluxo simplificado de boot no Linux&quot; /&gt;&lt;h3&gt;BIOS e UEFI&lt;/h3&gt;
&lt;p&gt;BIOS e UEFI são firmwares da plataforma responsáveis pelas primeiras etapas da inicialização. Eles testam hardware, inicializam componentes básicos e localizam algo capaz de continuar o boot.&lt;/p&gt;
&lt;p&gt;UEFI é o modelo moderno e trabalha com recursos como a EFI System Partition e Secure Boot. Ele não é “parte do Linux”; existe antes de qualquer kernel ser carregado.&lt;/p&gt;
&lt;h3&gt;Bootloader&lt;/h3&gt;
&lt;p&gt;O bootloader localiza e carrega o kernel, normalmente junto com o initramfs e parâmetros de inicialização. GRUB, systemd-boot e Limine são exemplos.&lt;/p&gt;
&lt;p&gt;Em dual boot, o menu visível costuma ser responsabilidade do bootloader. Depois que o kernel assume o controle, o bootloader praticamente sai de cena.&lt;/p&gt;
&lt;h3&gt;Initramfs&lt;/h3&gt;
&lt;p&gt;Initramfs é um pequeno filesystem temporário carregado em RAM no início do boot. Ele contém ferramentas e módulos necessários para encontrar e montar o root filesystem real.&lt;/p&gt;
&lt;p&gt;Criptografia de disco, LVM, RAID ou drivers que não estão embutidos no kernel podem depender dele. Um initramfs quebrado é uma forma eficiente de descobrir que a inicialização tinha muito mais etapas do que parecia.&lt;/p&gt;
&lt;h3&gt;Parâmetros do kernel&lt;/h3&gt;
&lt;p&gt;São opções entregues ao kernel pelo bootloader, como &lt;code&gt;root=&lt;/code&gt;, &lt;code&gt;quiet&lt;/code&gt;, &lt;code&gt;loglevel=&lt;/code&gt;, &lt;code&gt;nomodeset&lt;/code&gt; ou parâmetros específicos de drivers.&lt;/p&gt;
&lt;p&gt;Eles alteram o comportamento do kernel desde o início. Por isso aparecem tanto em procedimentos de diagnóstico: algumas decisões precisam ser tomadas antes que o userspace exista.&lt;/p&gt;
&lt;h3&gt;Init e PID 1&lt;/h3&gt;
&lt;p&gt;Depois de preparar o sistema, o kernel inicia o primeiro processo do userspace. Esse processo recebe o PID 1 e tem responsabilidades especiais, como iniciar o restante do sistema e adotar processos órfãos.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;init&lt;/code&gt; é o nome genérico desse papel. systemd é uma implementação; SysVinit, OpenRC e runit são outras. Tratar &lt;code&gt;init&lt;/code&gt; e &lt;code&gt;systemd&lt;/code&gt; como sinônimos apaga justamente a diferença mais importante entre eles.&lt;/p&gt;
&lt;h3&gt;systemd&lt;/h3&gt;
&lt;p&gt;systemd é um conjunto de componentes para inicialização e gerenciamento do sistema. Seu processo principal costuma ocupar o PID 1 e gerenciar units, dependências, serviços, sockets, mounts, timers, sessões e integração com cgroups.&lt;/p&gt;
&lt;p&gt;Ele é mais do que “o programa que inicia serviços”, o que explica tanto sua utilidade quanto a quantidade de discussões que consegue produzir.&lt;/p&gt;
&lt;h3&gt;Unit&lt;/h3&gt;
&lt;p&gt;Unit é a unidade de configuração gerenciada pelo systemd. Existem units de serviço (&lt;code&gt;.service&lt;/code&gt;), socket (&lt;code&gt;.socket&lt;/code&gt;), montagem (&lt;code&gt;.mount&lt;/code&gt;), timer (&lt;code&gt;.timer&lt;/code&gt;), alvo (&lt;code&gt;.target&lt;/code&gt;) e outros tipos.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;systemctl status sshd.service&lt;/code&gt; consulta uma unit. O serviço executado por ela é outra coisa: a unit descreve como o systemd deve gerenciá-lo.&lt;/p&gt;
&lt;h3&gt;Serviço e daemon&lt;/h3&gt;
&lt;p&gt;Daemon é um processo que permanece em segundo plano oferecendo alguma função, como &lt;code&gt;sshd&lt;/code&gt;, um servidor web ou um banco de dados. Serviço é um conceito de gerenciamento: algo que o sistema inicia, supervisiona e interrompe.&lt;/p&gt;
&lt;p&gt;Muitos serviços executam daemons, mas os termos não são perfeitamente equivalentes. Uma unit pode rodar uma tarefa curta e terminar; um daemon também pode existir sem ser controlado pelo systemd.&lt;/p&gt;
&lt;h2&gt;Arquivos, diretórios e armazenamento&lt;/h2&gt;
&lt;p&gt;No Linux, quase tudo aparece dentro de uma única árvore iniciada em &lt;code&gt;/&lt;/code&gt;. Discos diferentes, pseudo-filesystems do kernel, dispositivos e compartilhamentos de rede podem ser encaixados nessa árvore por montagem.&lt;/p&gt;
&lt;h3&gt;Diretório raiz &lt;code&gt;/&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/&lt;/code&gt; é o topo da árvore de diretórios. Todo caminho absoluto começa nele.&lt;/p&gt;
&lt;p&gt;Não confunda &lt;code&gt;/&lt;/code&gt; com &lt;code&gt;/root&lt;/code&gt;. O primeiro é a raiz do filesystem; o segundo é, por convenção, o diretório pessoal do usuário root. Uma barra muda bastante coisa.&lt;/p&gt;
&lt;h3&gt;FHS&lt;/h3&gt;
&lt;p&gt;O Filesystem Hierarchy Standard descreve a finalidade esperada de diretórios como &lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/usr&lt;/code&gt;, &lt;code&gt;/var&lt;/code&gt;, &lt;code&gt;/bin&lt;/code&gt; e &lt;code&gt;/sbin&lt;/code&gt;. Distribuições modernas nem sempre seguem cada detalhe da mesma forma, especialmente com a unificação de &lt;code&gt;/usr&lt;/code&gt;, mas o padrão continua sendo um mapa útil.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html&quot;&gt;especificação do FHS&lt;/a&gt; ajuda a entender por que configurações ficam em &lt;code&gt;/etc&lt;/code&gt;, dados variáveis em &lt;code&gt;/var&lt;/code&gt; e interfaces do kernel aparecem em outros pontos.&lt;/p&gt;
&lt;h3&gt;Filesystem&lt;/h3&gt;
&lt;p&gt;Filesystem é a estrutura usada para organizar arquivos, diretórios e metadados em um dispositivo ou volume. ext4, XFS, Btrfs, FAT32 e tmpfs são exemplos.&lt;/p&gt;
&lt;p&gt;O termo também pode se referir à árvore montada e visível pelo sistema. O contexto diz se a conversa é sobre o formato de armazenamento, a implementação ou o conjunto de arquivos acessível.&lt;/p&gt;
&lt;h3&gt;VFS&lt;/h3&gt;
&lt;p&gt;Virtual Filesystem é a camada do kernel que oferece uma interface comum para diferentes filesystems. Graças ao VFS, programas usam operações parecidas para trabalhar com ext4, XFS, tmpfs, NFS ou procfs.&lt;/p&gt;
&lt;p&gt;A aplicação pede “abra este caminho”; o VFS encaminha a operação para a implementação correta. É uma abstração extremamente importante e quase invisível quando tudo funciona.&lt;/p&gt;
&lt;h3&gt;Partição, volume e dispositivo de bloco&lt;/h3&gt;
&lt;p&gt;Partição é uma divisão lógica de um dispositivo de armazenamento. Volume é um termo mais amplo e pode representar uma partição, um volume lógico do LVM, um array RAID ou outro dispositivo composto.&lt;/p&gt;
&lt;p&gt;Dispositivo de bloco é a interface usada para armazenamento acessado em blocos, como &lt;code&gt;/dev/nvme0n1&lt;/code&gt; ou &lt;code&gt;/dev/sda&lt;/code&gt;. Um filesystem normalmente é criado sobre um dispositivo de bloco ou volume, não “diretamente numa pasta”.&lt;/p&gt;
&lt;h3&gt;Montagem e ponto de montagem&lt;/h3&gt;
&lt;p&gt;Montar é anexar um filesystem à árvore de diretórios. O diretório onde ele aparece é o ponto de montagem.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mount /dev/sdb1 /mnt/dados
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois desse comando, o conteúdo do filesystem em &lt;code&gt;/dev/sdb1&lt;/code&gt; fica acessível por &lt;code&gt;/mnt/dados&lt;/code&gt;. A pasta não “vira o disco”; ela passa a ser a porta de entrada para aquele filesystem.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;/etc/fstab&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/etc/fstab&lt;/code&gt; descreve filesystems que podem ser montados automaticamente ou por regras predefinidas. É comum identificar volumes por UUID para evitar depender de nomes como &lt;code&gt;/dev/sdb1&lt;/code&gt;, que podem mudar.&lt;/p&gt;
&lt;p&gt;Um erro nesse arquivo pode atrasar ou interromper o boot. A velha tradição de editar configuração como root e descobrir o erro só na reinicialização continua firme.&lt;/p&gt;
&lt;h3&gt;Inode&lt;/h3&gt;
&lt;p&gt;Inode é uma estrutura de metadados usada por filesystems Unix-like. Ele registra informações como tipo, permissões, proprietário, timestamps e referências aos blocos de dados.&lt;/p&gt;
&lt;p&gt;O nome do arquivo não fica “dentro do inode” da forma que muita gente imagina. Diretórios associam nomes a números de inode. Isso ajuda a entender hard links e por que um arquivo pode continuar existindo mesmo após um nome ser removido.&lt;/p&gt;
&lt;h3&gt;Hard link e link simbólico&lt;/h3&gt;
&lt;p&gt;Hard link é outro nome apontando para o mesmo inode. Link simbólico é um arquivo especial que guarda um caminho para outro arquivo ou diretório.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/unixnomicon-um-glossario-do-kernel-aos-containers/hard-link-e-link-simb-lico-e6ae30b456.svg&quot; alt=&quot;Hard link e link simbólico&quot; /&gt;&lt;p&gt;O comando &lt;code&gt;ln arquivo copia&lt;/code&gt; cria um hard link. &lt;code&gt;ln -s alvo link&lt;/code&gt; cria um link simbólico.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;/dev&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/dev&lt;/code&gt; contém device nodes: arquivos especiais que representam interfaces para dispositivos e alguns recursos do kernel.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/dev/null&lt;/code&gt;, &lt;code&gt;/dev/zero&lt;/code&gt;, &lt;code&gt;/dev/random&lt;/code&gt;, discos e terminais aparecem ali. Ler ou escrever nesses arquivos pode significar interagir com um driver, não com dados armazenados como num arquivo comum.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;/proc&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/proc&lt;/code&gt; é um pseudo-filesystem que expõe informações sobre processos e o estado do kernel. Diretórios como &lt;code&gt;/proc/1234&lt;/code&gt; representam processos, e arquivos como &lt;code&gt;/proc/cpuinfo&lt;/code&gt; ou &lt;code&gt;/proc/meminfo&lt;/code&gt; apresentam dados do sistema.&lt;/p&gt;
&lt;p&gt;Ele não ocupa um “diretório real no disco” da forma tradicional. É uma interface gerada pelo kernel, documentada na &lt;a href=&quot;https://docs.kernel.org/filesystems/proc.html&quot;&gt;documentação do procfs&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;/sys&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/sys&lt;/code&gt; normalmente monta o sysfs, uma interface estruturada para dispositivos, drivers, classes e objetos internos do kernel.&lt;/p&gt;
&lt;p&gt;Ferramentas de gerenciamento de hardware e o udev usam essas informações. &lt;code&gt;/proc&lt;/code&gt; e &lt;code&gt;/sys&lt;/code&gt; às vezes parecem semelhantes, mas &lt;code&gt;/sys&lt;/code&gt; foi projetado com uma organização mais explícita dos objetos do kernel.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;/etc&lt;/code&gt;, &lt;code&gt;/var&lt;/code&gt;, &lt;code&gt;/run&lt;/code&gt; e &lt;code&gt;/tmp&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/etc&lt;/code&gt; guarda configuração do sistema. &lt;code&gt;/var&lt;/code&gt; guarda dados variáveis e persistentes, como logs, filas e bancos de estado. &lt;code&gt;/run&lt;/code&gt; contém estado volátil desde o boot atual. &lt;code&gt;/tmp&lt;/code&gt; é espaço temporário e pode ser limpo automaticamente.&lt;/p&gt;
&lt;p&gt;Saber essa diferença evita colocar dados importantes num diretório temporário ou arquivos mutáveis em locais que deveriam representar configuração estática.&lt;/p&gt;
&lt;h2&gt;Processos, usuários e permissões&lt;/h2&gt;
&lt;p&gt;Um sistema Linux em execução é uma árvore de processos disputando recursos sob regras do kernel. Usuários e grupos ajudam a definir identidade; permissões, capabilities e políticas adicionais limitam o que cada processo pode fazer.&lt;/p&gt;
&lt;h3&gt;Processo&lt;/h3&gt;
&lt;p&gt;Processo é uma instância de um programa em execução, com memória, descritores de arquivo, credenciais, estado e recursos associados.&lt;/p&gt;
&lt;p&gt;O arquivo executável no disco não é o processo. O mesmo binário pode originar vários processos independentes, cada um com PID e estado próprios.&lt;/p&gt;
&lt;h3&gt;Thread&lt;/h3&gt;
&lt;p&gt;Thread é uma linha de execução dentro de um processo. Threads do mesmo processo normalmente compartilham memória e vários outros recursos, mas possuem estado de execução individual.&lt;/p&gt;
&lt;p&gt;A distinção importa para desempenho, concorrência, depuração e sinais. Ferramentas podem mostrar apenas processos ou detalhar threads, dependendo das opções usadas.&lt;/p&gt;
&lt;h3&gt;PID, PPID e árvore de processos&lt;/h3&gt;
&lt;p&gt;PID é o identificador de um processo. PPID é o PID do processo pai.&lt;/p&gt;
&lt;p&gt;Processos formam uma árvore porque novos processos geralmente nascem de outros. &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;pstree&lt;/code&gt; e &lt;code&gt;/proc&lt;/code&gt; ajudam a visualizar essa relação. O PID é reutilizável: ele identifica um processo naquele momento, não uma entidade eterna.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;fork()&lt;/code&gt; e &lt;code&gt;exec()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Em sistemas Unix-like, um padrão clássico é criar um novo processo com &lt;code&gt;fork()&lt;/code&gt; e substituir seu programa com &lt;code&gt;execve()&lt;/code&gt; ou outra função da família &lt;code&gt;exec&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Quando um shell executa um comando externo, normalmente prepara redirecionamentos, cria o processo e carrega o executável. É por isso que criação de processos, pipes e descritores de arquivo aparecem juntos em explicações mais profundas sobre shells.&lt;/p&gt;
&lt;h3&gt;Sinal&lt;/h3&gt;
&lt;p&gt;Sinal é uma notificação assíncrona enviada a um processo ou thread. &lt;code&gt;SIGTERM&lt;/code&gt; pede encerramento; &lt;code&gt;SIGKILL&lt;/code&gt; força o kernel a terminar o processo; &lt;code&gt;SIGHUP&lt;/code&gt;, &lt;code&gt;SIGINT&lt;/code&gt;, &lt;code&gt;SIGSTOP&lt;/code&gt; e outros têm semânticas próprias.&lt;/p&gt;
&lt;p&gt;O comando &lt;code&gt;kill&lt;/code&gt; envia sinais. Apesar do nome, &lt;code&gt;kill PID&lt;/code&gt; normalmente envia &lt;code&gt;SIGTERM&lt;/code&gt;, não uma execução sumária. &lt;code&gt;kill -9&lt;/code&gt; virou martelo universal porque ignora qualquer chance de limpeza. Justamente por isso, não deveria ser a primeira tentativa.&lt;/p&gt;
&lt;h3&gt;Usuário root&lt;/h3&gt;
&lt;p&gt;root é o superusuário tradicional, normalmente com UID 0. Ele pode ultrapassar grande parte das verificações normais de permissão.&lt;/p&gt;
&lt;p&gt;Isso não significa onipotência absoluta: políticas de segurança, namespaces, capabilities, mounts somente leitura e mecanismos do kernel ainda podem impor limites. Mesmo assim, executar tudo como root continua sendo uma ótima forma de transformar um erro pequeno em incidente.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;sudo&lt;/code&gt; e &lt;code&gt;su&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sudo&lt;/code&gt; executa um comando com credenciais definidas por política, frequentemente como root. &lt;code&gt;su&lt;/code&gt; inicia uma sessão ou shell como outro usuário.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo&lt;/code&gt; não é “virar root por alguns segundos” de forma mágica; é uma ferramenta de delegação e auditoria. A configuração vive em &lt;code&gt;sudoers&lt;/code&gt;, e editar esse arquivo sem &lt;code&gt;visudo&lt;/code&gt; é uma aposta desnecessária.&lt;/p&gt;
&lt;h3&gt;UID, GID e grupos&lt;/h3&gt;
&lt;p&gt;UID identifica um usuário; GID identifica um grupo. Para o kernel, nomes como &lt;code&gt;kristyan&lt;/code&gt; são representações amigáveis de identificadores numéricos.&lt;/p&gt;
&lt;p&gt;Um processo carrega credenciais de usuário e grupos, usadas nas decisões de acesso. Arquivos também armazenam proprietário e grupo por identificadores.&lt;/p&gt;
&lt;h3&gt;Permissões &lt;code&gt;rwx&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;As permissões tradicionais definem leitura (&lt;code&gt;r&lt;/code&gt;), escrita (&lt;code&gt;w&lt;/code&gt;) e execução (&lt;code&gt;x&lt;/code&gt;) para proprietário, grupo e outros.&lt;/p&gt;
&lt;p&gt;Em diretórios, os significados mudam um pouco: leitura permite listar nomes, escrita permite alterar entradas e execução permite atravessar o diretório. Decorar &lt;code&gt;chmod 777&lt;/code&gt; sem entender isso é o equivalente Unix de remover a porta porque a chave emperrou.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;umask&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;umask&lt;/code&gt; define quais bits de permissão devem ser removidos das permissões solicitadas na criação de arquivos e diretórios.&lt;/p&gt;
&lt;p&gt;Ela não “atribui a permissão final” diretamente. A aplicação solicita um modo inicial e a máscara retira bits. Por isso a conta parece estranha até você entender que é uma máscara, não um valor de permissão comum.&lt;/p&gt;
&lt;h3&gt;ACL&lt;/h3&gt;
&lt;p&gt;Access Control Lists permitem regras de acesso mais específicas que o modelo simples de proprietário, grupo e outros.&lt;/p&gt;
&lt;p&gt;Com ACLs, é possível conceder permissões a usuários ou grupos adicionais sem mudar o grupo principal do arquivo. &lt;code&gt;getfacl&lt;/code&gt; e &lt;code&gt;setfacl&lt;/code&gt; são as ferramentas mais comuns.&lt;/p&gt;
&lt;h3&gt;Capabilities&lt;/h3&gt;
&lt;p&gt;Linux capabilities dividem parte dos poderes tradicionalmente concentrados no root em permissões menores, como abrir portas privilegiadas ou administrar interfaces de rede.&lt;/p&gt;
&lt;p&gt;Isso permite que um processo receba apenas o privilégio necessário, em vez de acesso irrestrito. A &lt;a href=&quot;https://man7.org/linux/man-pages/man7/capabilities.7.html&quot;&gt;man page de capabilities&lt;/a&gt; mostra o tamanho real desse mecanismo e também por que “rodar como não-root” não encerra sozinho uma análise de privilégio.&lt;/p&gt;
&lt;h3&gt;Namespace&lt;/h3&gt;
&lt;p&gt;Namespace isola a visão que um grupo de processos tem de algum recurso do sistema. Existem namespaces de processos, mounts, rede, usuários, hostname, IPC, cgroups e tempo.&lt;/p&gt;
&lt;p&gt;Eles são uma das bases dos containers: processos podem enxergar uma árvore de PIDs, interfaces de rede e pontos de montagem diferentes do host. A &lt;a href=&quot;https://man7.org/linux/man-pages/man7/namespaces.7.html&quot;&gt;visão geral de namespaces&lt;/a&gt; conecta os diferentes tipos.&lt;/p&gt;
&lt;h3&gt;cgroup&lt;/h3&gt;
&lt;p&gt;Control groups organizam processos hierarquicamente e controlam ou contabilizam recursos como CPU, memória, I/O e quantidade de processos.&lt;/p&gt;
&lt;p&gt;Namespaces mudam o que um processo enxerga; cgroups controlam quanto ele pode consumir. Containers costumam usar ambos. A &lt;a href=&quot;https://docs.kernel.org/admin-guide/cgroup-v2.html&quot;&gt;documentação do cgroup v2&lt;/a&gt; é a referência autoritativa para o modelo atual.&lt;/p&gt;
&lt;h3&gt;OOM killer&lt;/h3&gt;
&lt;p&gt;Quando o sistema não consegue satisfazer demandas de memória, o kernel pode escolher processos para encerrar e recuperar recursos. Esse mecanismo é conhecido como OOM killer.&lt;/p&gt;
&lt;p&gt;Quando um serviço “morreu do nada”, procurar eventos de OOM em &lt;code&gt;dmesg&lt;/code&gt; ou no journal é mais útil do que culpar imediatamente a aplicação. O processo pode ter sido vítima do estado global da máquina ou do limite de um cgroup.&lt;/p&gt;
&lt;h2&gt;Terminal, TTY e shell&lt;/h2&gt;
&lt;p&gt;A tela preta com texto é uma coleção de componentes. Terminal, shell e comando não são três nomes para a mesma coisa.&lt;/p&gt;
&lt;h3&gt;Terminal emulator&lt;/h3&gt;
&lt;p&gt;Um emulador de terminal é a aplicação gráfica que mostra texto, recebe teclado e oferece uma interface compatível com terminais. Alacritty, Kitty, GNOME Terminal, Konsole e WezTerm são exemplos.&lt;/p&gt;
&lt;p&gt;Ele não interpreta &lt;code&gt;cd&lt;/code&gt;, pipes ou variáveis. Quem faz isso é o shell executado dentro dele.&lt;/p&gt;
&lt;h3&gt;TTY e PTY&lt;/h3&gt;
&lt;p&gt;TTY é o nome histórico dado a terminais. PTY, ou pseudo-terminal, é o mecanismo usado para conectar programas modernos a uma interface que se comporta como terminal.&lt;/p&gt;
&lt;p&gt;Multiplexadores como tmux, conexões SSH e emuladores gráficos usam pseudo-terminais. Muitos comportamentos estranhos de programas interativos dependem de eles detectarem ou não que estão ligados a um TTY.&lt;/p&gt;
&lt;h3&gt;Shell&lt;/h3&gt;
&lt;p&gt;Shell é o interpretador de comandos e linguagem de automação que conecta entrada do usuário a programas e recursos do sistema.&lt;/p&gt;
&lt;p&gt;Bash, Zsh, fish, Dash e Nushell são shells diferentes. Eles podem compartilhar ideias e sintaxe, mas não são totalmente compatíveis.&lt;/p&gt;
&lt;h3&gt;Bash, Zsh e fish&lt;/h3&gt;
&lt;p&gt;Bash é amplamente usado e tem forte compatibilidade com o mundo Unix e scripts existentes. Zsh oferece recursos interativos avançados e uma linguagem própria. fish prioriza uma experiência interativa amigável, mas não tenta ser compatível com a sintaxe POSIX.&lt;/p&gt;
&lt;p&gt;Escolher um shell interativo é preferência. Escrever scripts portáveis é outro problema. A &lt;a href=&quot;https://www.gnu.org/software/bash/manual/bash.html&quot;&gt;referência do Bash&lt;/a&gt; é mais confiável do que adivinhar o comportamento por tentativa e erro.&lt;/p&gt;
&lt;h3&gt;Comando, executável e builtin&lt;/h3&gt;
&lt;p&gt;“Comando” é o que você pede ao shell para executar. Ele pode resolver para um executável externo, uma função, um alias, uma palavra reservada ou um builtin do próprio shell.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; geralmente é builtin porque precisa alterar o diretório do processo do shell. Um programa externo não conseguiria mudar permanentemente o diretório do processo pai.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;type -a cd
type -a printf
type -a ls
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;type&lt;/code&gt; ajuda a descobrir o que o shell realmente executará.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;PATH&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;PATH&lt;/code&gt; é uma variável com uma lista ordenada de diretórios onde o shell procura executáveis quando o comando não contém uma barra.&lt;/p&gt;
&lt;p&gt;Se dois diretórios contêm um programa com o mesmo nome, vence o primeiro encontrado. Colocar &lt;code&gt;.&lt;/code&gt; no início do &lt;code&gt;PATH&lt;/code&gt; é conveniente até um arquivo malicioso com nome inocente aparecer no diretório atual.&lt;/p&gt;
&lt;h3&gt;Variável de ambiente&lt;/h3&gt;
&lt;p&gt;Variável de ambiente é um par nome-valor herdado por processos filhos. &lt;code&gt;HOME&lt;/code&gt;, &lt;code&gt;LANG&lt;/code&gt;, &lt;code&gt;PATH&lt;/code&gt;, &lt;code&gt;EDITOR&lt;/code&gt; e &lt;code&gt;XDG_CONFIG_HOME&lt;/code&gt; são exemplos comuns.&lt;/p&gt;
&lt;p&gt;Variáveis do shell nem sempre estão exportadas para o ambiente. &lt;code&gt;export NOME=valor&lt;/code&gt; torna a variável disponível aos processos iniciados depois.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;stdin&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt; e &lt;code&gt;stderr&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Processos Unix normalmente começam com três fluxos: entrada padrão (&lt;code&gt;stdin&lt;/code&gt;, descritor 0), saída padrão (&lt;code&gt;stdout&lt;/code&gt;, descritor 1) e saída de erro (&lt;code&gt;stderr&lt;/code&gt;, descritor 2).&lt;/p&gt;
&lt;p&gt;Essa convenção permite compor ferramentas sem cada programa precisar conhecer o próximo. É uma das ideias mais simples e produtivas do ambiente Unix.&lt;/p&gt;
&lt;h3&gt;Pipe&lt;/h3&gt;
&lt;p&gt;O pipe &lt;code&gt;|&lt;/code&gt; conecta o &lt;code&gt;stdout&lt;/code&gt; de um comando ao &lt;code&gt;stdin&lt;/code&gt; do próximo.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/unixnomicon-um-glossario-do-kernel-aos-containers/composi-o-de-comandos-com-pipes-8069c68c6b.svg&quot; alt=&quot;Composição de comandos com pipes&quot; /&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat arquivo.log | grep &apos;ERROR&apos; | wc -l
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O exemplo funciona, embora &lt;code&gt;grep &apos;ERROR&apos; arquivo.log | wc -l&lt;/code&gt; seja mais simples. Pipes são composição, não um concurso para usar o maior número de processos possível.&lt;/p&gt;
&lt;h3&gt;Redirecionamento&lt;/h3&gt;
&lt;p&gt;Redirecionamento muda a origem ou o destino dos descritores de arquivo.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;comando &amp;gt;saida.log 2&amp;gt;erros.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&amp;gt;&lt;/code&gt; sobrescreve, &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; acrescenta, &lt;code&gt;&amp;lt;&lt;/code&gt; fornece entrada e &lt;code&gt;2&amp;gt;&amp;amp;1&lt;/code&gt; faz o descritor 2 apontar para o mesmo destino atual do descritor 1. A ordem importa porque o shell aplica redirecionamentos da esquerda para a direita.&lt;/p&gt;
&lt;h3&gt;Exit status&lt;/h3&gt;
&lt;p&gt;Todo processo termina com um código de saída. Por convenção, &lt;code&gt;0&lt;/code&gt; indica sucesso e valores diferentes indicam falha ou condição especial.&lt;/p&gt;
&lt;p&gt;O shell expõe o último código em &lt;code&gt;$?&lt;/code&gt;. Operadores como &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; e &lt;code&gt;||&lt;/code&gt; usam esse resultado para decidir se executam o próximo comando.&lt;/p&gt;
&lt;h3&gt;Glob e expressão regular&lt;/h3&gt;
&lt;p&gt;Glob é o padrão expandido pelo shell para nomes de arquivo, como &lt;code&gt;*.log&lt;/code&gt;. Expressão regular é uma linguagem de padrões interpretada por ferramentas como &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt; e várias linguagens de programação.&lt;/p&gt;
&lt;p&gt;Eles se parecem, mas têm regras diferentes. &lt;code&gt;*.log&lt;/code&gt; num shell não significa a mesma coisa que &lt;code&gt;*.log&lt;/code&gt; numa regex. Misturar os dois é uma fonte inesgotável de comandos “quase certos”.&lt;/p&gt;
&lt;h3&gt;Coreutils&lt;/h3&gt;
&lt;p&gt;GNU Coreutils é um conjunto de utilitários fundamentais como &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;chmod&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;cut&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, &lt;code&gt;tail&lt;/code&gt; e &lt;code&gt;wc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Esses comandos não fazem parte do kernel. Em outros sistemas ou userspaces, podem vir de implementações diferentes, como BusyBox ou uutils, com diferenças de opções e comportamento.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt; e &lt;code&gt;awk&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;grep&lt;/code&gt; seleciona linhas por padrões. &lt;code&gt;sed&lt;/code&gt; transforma fluxos de texto. &lt;code&gt;awk&lt;/code&gt; é uma linguagem voltada a registros e campos.&lt;/p&gt;
&lt;p&gt;Eles não são três versões do mesmo comando. Para buscas, comece com &lt;code&gt;grep&lt;/code&gt;; para substituições e edições de fluxo, use &lt;code&gt;sed&lt;/code&gt;; para lógica por colunas, cálculos e relatórios, &lt;code&gt;awk&lt;/code&gt; costuma ser mais adequado.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;find&lt;/code&gt; e &lt;code&gt;xargs&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;find&lt;/code&gt; percorre árvores de diretórios e seleciona entradas por nome, tipo, data, tamanho e outros critérios. &lt;code&gt;xargs&lt;/code&gt; transforma entrada em argumentos para outro comando.&lt;/p&gt;
&lt;p&gt;Para nomes arbitrários, prefira interfaces seguras contra espaços e quebras de linha, como &lt;code&gt;find ... -exec ... {} +&lt;/code&gt; ou a combinação &lt;code&gt;-print0&lt;/code&gt; com &lt;code&gt;xargs -0&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Pacotes, repositórios e distribuições&lt;/h2&gt;
&lt;p&gt;Instalar software numa distribuição não é apenas baixar um executável. O sistema precisa saber de onde ele veio, quais arquivos pertencem ao pacote, quais dependências são necessárias e como atualizar ou remover tudo depois.&lt;/p&gt;
&lt;h3&gt;Pacote&lt;/h3&gt;
&lt;p&gt;Pacote é uma unidade de distribuição de software acompanhada de metadados. Ele pode conter binários, bibliotecas, configuração padrão, scripts de instalação e informações de dependência.&lt;/p&gt;
&lt;p&gt;Um pacote não é necessariamente um único programa. Também pode representar biblioteca, documentação, headers, firmware ou metapacote.&lt;/p&gt;
&lt;h3&gt;Repositório&lt;/h3&gt;
&lt;p&gt;Repositório é uma fonte organizada de pacotes e metadados, normalmente assinada e mantida segundo as políticas da distribuição ou de um terceiro.&lt;/p&gt;
&lt;p&gt;Adicionar um repositório concede confiança operacional a quem o mantém. O gerenciador de pacotes fará o trabalho com eficiência; ele não avaliará se a sua decisão foi sensata.&lt;/p&gt;
&lt;h3&gt;Gerenciador de pacotes&lt;/h3&gt;
&lt;p&gt;Gerenciador de pacotes instala, remove, consulta e atualiza pacotes. &lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;dnf&lt;/code&gt;, &lt;code&gt;pacman&lt;/code&gt;, &lt;code&gt;zypper&lt;/code&gt; e &lt;code&gt;apk&lt;/code&gt; são exemplos de interfaces de alto nível ou ferramentas centrais de suas distribuições.&lt;/p&gt;
&lt;p&gt;Cada família tem camadas próprias. No Debian, por exemplo, &lt;code&gt;apt&lt;/code&gt; e &lt;code&gt;dpkg&lt;/code&gt; não ocupam exatamente o mesmo papel. No Arch, &lt;code&gt;pacman&lt;/code&gt; gerencia pacotes oficiais e locais; o AUR envolve outro fluxo.&lt;/p&gt;
&lt;h3&gt;Dependência&lt;/h3&gt;
&lt;p&gt;Dependência é outro componente necessário para instalar, compilar ou executar um pacote. Ela pode ser obrigatória, opcional, de build, de runtime ou entrar em conflito com outra.&lt;/p&gt;
&lt;p&gt;O trabalho mais valioso do gerenciador não é copiar arquivos. É manter um grafo coerente de versões e dependências sem transformar o sistema numa coleção artesanal de binários esquecidos.&lt;/p&gt;
&lt;h3&gt;Pacote binário e pacote-fonte&lt;/h3&gt;
&lt;p&gt;Pacote binário entrega arquivos já compilados para uma arquitetura e ambiente específicos. Pacote-fonte contém código e instruções para produzir os binários.&lt;/p&gt;
&lt;p&gt;Distribuições podem aplicar patches, flags de compilação e políticas próprias. Por isso “a mesma versão upstream” não garante que dois pacotes de distribuições diferentes sejam idênticos.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;.deb&lt;/code&gt; e &lt;code&gt;.rpm&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.deb&lt;/code&gt; e &lt;code&gt;.rpm&lt;/code&gt; são formatos de pacote associados a famílias diferentes de distribuições. O formato do arquivo não define sozinho toda a experiência de gerenciamento.&lt;/p&gt;
&lt;p&gt;APT, DNF e outras ferramentas trabalham com repositórios, resolução de dependências e políticas acima do formato básico. Instalar um arquivo isolado é apenas uma parte do sistema.&lt;/p&gt;
&lt;h3&gt;Rolling release e lançamento fixo&lt;/h3&gt;
&lt;p&gt;Rolling release atualiza continuamente os componentes da distribuição. Lançamentos fixos congelam uma base por versão e recebem correções ou atualizações controladas.&lt;/p&gt;
&lt;p&gt;Rolling não significa automaticamente instável; fixed não significa automaticamente antigo ou seguro. A diferença real está na cadência, integração, testes, compatibilidade esperada e trabalho de manutenção transferido para o usuário.&lt;/p&gt;
&lt;h3&gt;AUR&lt;/h3&gt;
&lt;p&gt;O Arch User Repository é um repositório comunitário de receitas de build, principalmente arquivos &lt;code&gt;PKGBUILD&lt;/code&gt;. Ele não é um repositório oficial de pacotes binários do Arch.&lt;/p&gt;
&lt;p&gt;Helpers facilitam o processo, mas não transformam código da comunidade em software auditado pela distribuição. Eu já discuti esse risco no post sobre &lt;a href=&quot;https://blog.kristyan.dev/posts/mais-de-400-pacotes-aur-foram-comprometidos-com-infostealer-e-rootkit&quot;&gt;pacotes comprometidos no AUR&lt;/a&gt;. Conveniência continua não sendo uma cadeia de confiança.&lt;/p&gt;
&lt;h3&gt;Flatpak, Snap e AppImage&lt;/h3&gt;
&lt;p&gt;São modelos alternativos de distribuição de aplicações, com propostas diferentes.&lt;/p&gt;
&lt;p&gt;Flatpak usa runtimes e sandboxing, com forte presença em aplicações desktop. Snap combina empacotamento, atualização e confinamento sob a infraestrutura da Canonical. AppImage prioriza executáveis portáteis e autocontidos, com menos integração central obrigatória.&lt;/p&gt;
&lt;p&gt;Chamar os três de “pacote universal” ajuda numa conversa rápida, mas esconde diferenças importantes de atualização, permissões, distribuição, integração e confiança.&lt;/p&gt;
&lt;h2&gt;Rede e segurança&lt;/h2&gt;
&lt;p&gt;Rede em Linux também aparece como arquivos, processos, sockets, namespaces e regras do kernel. Segurança, por sua vez, não é uma opção isolada chamada “modo seguro”; é a soma de identidades, privilégios, políticas, atualizações e desenho operacional.&lt;/p&gt;
&lt;h3&gt;Interface de rede&lt;/h3&gt;
&lt;p&gt;Interface é o ponto lógico por onde o sistema envia e recebe pacotes. Pode representar hardware físico, loopback, bridge, túnel, VLAN ou interface virtual.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ip link&lt;/code&gt; lista interfaces. Nomes como &lt;code&gt;eth0&lt;/code&gt;, &lt;code&gt;enp4s0&lt;/code&gt;, &lt;code&gt;wlan0&lt;/code&gt;, &lt;code&gt;lo&lt;/code&gt;, &lt;code&gt;docker0&lt;/code&gt; e &lt;code&gt;wg0&lt;/code&gt; indicam origens e funções diferentes.&lt;/p&gt;
&lt;h3&gt;Endereço IP, rota e gateway&lt;/h3&gt;
&lt;p&gt;O endereço IP identifica uma interface dentro de uma rede. A tabela de rotas decide para onde enviar pacotes. O gateway é um próximo salto usado para alcançar outras redes.&lt;/p&gt;
&lt;p&gt;Ter IP não garante acesso à internet. Ainda podem faltar rota, DNS, conectividade no gateway, regras de firewall ou resposta do destino.&lt;/p&gt;
&lt;h3&gt;DNS&lt;/h3&gt;
&lt;p&gt;DNS traduz nomes como &lt;code&gt;example.com&lt;/code&gt; em registros, frequentemente endereços IP. Resolver um nome envolve bibliotecas, configuração local, caches e servidores recursivos.&lt;/p&gt;
&lt;p&gt;Quando “a internet caiu”, testar um IP e depois um nome ajuda a separar conectividade de resolução. Culpar o DNS virou meme porque, com frequência irritante, o DNS realmente está envolvido.&lt;/p&gt;
&lt;h3&gt;Porta e socket&lt;/h3&gt;
&lt;p&gt;Porta é um número usado pelos protocolos de transporte para distinguir serviços num endereço. Socket é um endpoint de comunicação mantido pelo kernel.&lt;/p&gt;
&lt;p&gt;Um processo “escuta na porta 8080” porque possui um socket associado àquele endereço e porta. Sockets também podem ser locais, como Unix domain sockets, sem usar IP.&lt;/p&gt;
&lt;h3&gt;SSH&lt;/h3&gt;
&lt;p&gt;SSH é um protocolo para acesso remoto seguro, execução de comandos, túneis e transferência de dados. OpenSSH é a implementação mais comum em sistemas Linux.&lt;/p&gt;
&lt;p&gt;Autenticação por chave usa uma chave privada mantida pelo cliente e uma chave pública autorizada no servidor. A chave privada não deve ser enviada ao servidor nem compartilhada como se fosse senha de Wi-Fi.&lt;/p&gt;
&lt;h3&gt;Firewall e nftables&lt;/h3&gt;
&lt;p&gt;Firewall filtra ou transforma tráfego segundo regras. No Linux moderno, nftables é a infraestrutura principal para esse trabalho, embora ferramentas de alto nível como firewalld e UFW ofereçam interfaces mais amigáveis.&lt;/p&gt;
&lt;p&gt;Abrir uma porta no firewall não inicia o serviço; iniciar o serviço não garante que a porta esteja acessível. São camadas distintas e a depuração precisa verificar ambas.&lt;/p&gt;
&lt;h3&gt;LSM&lt;/h3&gt;
&lt;p&gt;Linux Security Modules é a infraestrutura do kernel que permite implementar políticas adicionais de segurança. SELinux, AppArmor, Smack e Landlock se relacionam a esse mecanismo em níveis e usos diferentes.&lt;/p&gt;
&lt;p&gt;Permissões Unix respondem “quem é o usuário e quais bits existem?”. Um LSM pode impor regras extras mesmo quando as permissões tradicionais permitiriam a ação.&lt;/p&gt;
&lt;h3&gt;SELinux e AppArmor&lt;/h3&gt;
&lt;p&gt;SELinux trabalha com rótulos, tipos e políticas de controle de acesso mandatório. AppArmor é conhecido por perfis fortemente baseados em caminhos.&lt;/p&gt;
&lt;p&gt;Desativar o mecanismo porque uma aplicação foi bloqueada resolve o sintoma removendo a proteção inteira. O caminho correto é entender a negação, ajustar contexto ou perfil e preservar a política.&lt;/p&gt;
&lt;h3&gt;Hash, criptografia e assinatura&lt;/h3&gt;
&lt;p&gt;Hash produz um resumo de tamanho fixo e é usado para integridade, identificação e construção de outros mecanismos. Criptografia transforma dados para que apenas quem possui a chave adequada consiga lê-los. Assinatura digital permite verificar autoria e integridade.&lt;/p&gt;
&lt;p&gt;Um checksum não torna um download confiável se o arquivo e o checksum vieram do mesmo servidor comprometido. Assinaturas e uma cadeia de confiança independente existem justamente para melhorar esse cenário.&lt;/p&gt;
&lt;h3&gt;Chave pública e chave privada&lt;/h3&gt;
&lt;p&gt;Criptografia assimétrica usa um par relacionado. A chave privada deve permanecer secreta; a chave pública pode ser distribuída.&lt;/p&gt;
&lt;p&gt;Dependendo do algoritmo e protocolo, o par pode servir para assinatura, autenticação ou estabelecimento de segredo. “Criptografar com a chave privada” é uma simplificação ruim para explicar assinaturas e costuma gerar mais confusão depois.&lt;/p&gt;
&lt;h2&gt;Máquinas virtuais, containers e isolamento&lt;/h2&gt;
&lt;p&gt;Containers não são máquinas virtuais leves. Eles podem parecer semelhantes do ponto de vista operacional, mas o isolamento acontece em camadas diferentes.&lt;/p&gt;
&lt;img src=&quot;/images/posts/msvg/unixnomicon-um-glossario-do-kernel-aos-containers/m-quina-virtual-e-container-d1f4fb820d.svg&quot; alt=&quot;Máquina virtual e container&quot; /&gt;&lt;h3&gt;Máquina virtual&lt;/h3&gt;
&lt;p&gt;Máquina virtual apresenta hardware virtual a um sistema operacional convidado. Esse convidado executa seu próprio kernel e userspace.&lt;/p&gt;
&lt;p&gt;Ela oferece uma fronteira diferente da oferecida por containers e permite executar kernels distintos no mesmo host. O custo costuma ser maior em inicialização, memória e armazenamento.&lt;/p&gt;
&lt;h3&gt;Hipervisor, KVM e QEMU&lt;/h3&gt;
&lt;p&gt;Hipervisor é a camada que executa e isola máquinas virtuais. KVM adiciona suporte de virtualização ao kernel Linux. QEMU emula ou virtualiza hardware e frequentemente trabalha com KVM para acelerar execução próxima do hardware nativo.&lt;/p&gt;
&lt;p&gt;Dizer apenas “uso QEMU” ou “uso KVM” pode esconder uma pilha com libvirt, virt-manager, firmware virtual, dispositivos paravirtualizados e redes virtuais.&lt;/p&gt;
&lt;h3&gt;Container&lt;/h3&gt;
&lt;p&gt;Container é um conjunto de processos isolados por recursos do kernel, normalmente com filesystem, rede, PIDs e limites próprios. Ele compartilha o kernel do host.&lt;/p&gt;
&lt;p&gt;A imagem pode parecer uma instalação completa de uma distribuição, mas não existe um segundo kernel ali dentro. Essa diferença explica por que um container Linux precisa de um kernel Linux compatível no host.&lt;/p&gt;
&lt;h3&gt;Imagem e container&lt;/h3&gt;
&lt;p&gt;Imagem é um artefato imutável organizado em camadas, usado como base para criar containers. Container é a instância em execução, com estado adicional gravável e recursos associados.&lt;/p&gt;
&lt;p&gt;A imagem é receita e conteúdo; o container é processo e estado. Apagar um container não deveria apagar dados importantes se esses dados foram colocados corretamente em volumes ou armazenamento externo.&lt;/p&gt;
&lt;h3&gt;Runtime&lt;/h3&gt;
&lt;p&gt;Runtime de container é o software que prepara e inicia o ambiente isolado. &lt;code&gt;runc&lt;/code&gt;, &lt;code&gt;crun&lt;/code&gt;, containerd, CRI-O, Docker e Podman aparecem em camadas diferentes dessa pilha.&lt;/p&gt;
&lt;p&gt;“Docker” virou sinônimo popular de container, mas a implementação moderna envolve vários componentes e padrões. A marca é só uma parte da arquitetura.&lt;/p&gt;
&lt;h3&gt;OCI&lt;/h3&gt;
&lt;p&gt;Open Container Initiative mantém especificações para formatos de imagem e execução de containers. Isso permite interoperabilidade entre ferramentas e runtimes.&lt;/p&gt;
&lt;p&gt;Compatibilidade OCI não significa que todas as ferramentas tenham o mesmo modelo operacional, interface, segurança padrão ou experiência de uso.&lt;/p&gt;
&lt;h3&gt;Docker e Podman&lt;/h3&gt;
&lt;p&gt;Docker oferece uma plataforma com daemon, API, CLI, build e distribuição de imagens. Podman prioriza um modelo sem daemon central obrigatório e suporta uso rootless de forma nativa.&lt;/p&gt;
&lt;p&gt;A sintaxe parecida facilita migração, mas os detalhes de rede, compose, integração, sockets e ciclo de vida ainda merecem verificação. “É igual, só trocar o comando” funciona até atingir justamente a parte que não é igual.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;chroot&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;chroot&lt;/code&gt; altera o diretório raiz aparente de um processo e seus filhos. É útil em recuperação de sistemas, instalação e ambientes de build.&lt;/p&gt;
&lt;p&gt;Ele não é uma fronteira de segurança completa. Não oferece sozinho o conjunto de isolamento de namespaces, cgroups, capabilities e políticas usado por containers modernos.&lt;/p&gt;
&lt;h2&gt;Logs, diagnóstico e falhas&lt;/h2&gt;
&lt;p&gt;Conhecer os termos do sistema ajuda, mas o Linux fica realmente útil quando você consegue observar o que está acontecendo em vez de reiniciar e torcer.&lt;/p&gt;
&lt;h3&gt;Journal e &lt;code&gt;journalctl&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;O systemd-journald coleta logs estruturados de serviços, kernel e outras fontes. &lt;code&gt;journalctl&lt;/code&gt; consulta esses dados por unit, período, prioridade, boot e vários outros filtros.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;journalctl -u sshd.service -b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esse comando mostra mensagens da unit &lt;code&gt;sshd.service&lt;/code&gt; no boot atual. É mais produtivo do que abrir arquivos aleatórios em &lt;code&gt;/var/log&lt;/code&gt; esperando encontrar a pista certa.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;dmesg&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;dmesg&lt;/code&gt; exibe mensagens do ring buffer do kernel. Ele é útil para drivers, dispositivos, boot, OOM, filesystems e eventos de baixo nível.&lt;/p&gt;
&lt;p&gt;Em sistemas com journal, mensagens do kernel também podem ser consultadas com &lt;code&gt;journalctl -k&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt; e &lt;code&gt;htop&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;ps&lt;/code&gt; produz snapshots de processos. &lt;code&gt;top&lt;/code&gt; mostra uma visão dinâmica de processos e recursos. &lt;code&gt;htop&lt;/code&gt; oferece uma interface interativa mais amigável.&lt;/p&gt;
&lt;p&gt;Nenhuma dessas ferramentas explica sozinha a causa de um problema. CPU alta, memória residente, espera de I/O e quantidade de threads são sinais que precisam de contexto.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;lsof&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;lsof&lt;/code&gt; lista arquivos abertos por processos. Como sockets, pipes e dispositivos também são representados por descritores, ele ajuda a investigar portas, mounts ocupados e arquivos que continuam consumindo espaço após serem removidos.&lt;/p&gt;
&lt;p&gt;O nome “list open files” parece modesto para uma ferramenta que resolve tantos mistérios operacionais.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;strace&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;strace&lt;/code&gt; rastreia system calls e sinais. Ele mostra arquivos procurados, conexões tentadas, permissões negadas e operações que falharam.&lt;/p&gt;
&lt;p&gt;É excelente para responder “o que esse programa está tentando fazer?”. Também gera muito ruído; filtrar chamadas e entender o contexto é melhor do que colar milhares de linhas num chat e esperar iluminação divina.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;perf&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;perf&lt;/code&gt; é um conjunto de ferramentas de análise de desempenho integrado ao ecossistema do kernel. Ele pode coletar contadores de hardware, amostras de CPU, eventos e stacks.&lt;/p&gt;
&lt;p&gt;É uma ferramenta de profiling, não apenas um monitor de uso. Quando o problema é “onde o tempo está sendo gasto?”, &lt;code&gt;perf&lt;/code&gt; pode ir muito além de &lt;code&gt;top&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Core dump&lt;/h3&gt;
&lt;p&gt;Core dump é um snapshot do estado de memória de um processo no momento de uma falha. Ele pode ser analisado com depuradores como GDB.&lt;/p&gt;
&lt;p&gt;Em sistemas com systemd, &lt;code&gt;coredumpctl&lt;/code&gt; ajuda a localizar e abrir dumps coletados. Naturalmente, dumps podem conter dados sensíveis e ocupar bastante espaço.&lt;/p&gt;
&lt;h3&gt;Kernel panic&lt;/h3&gt;
&lt;p&gt;Kernel panic acontece quando o kernel encontra uma condição fatal da qual não consegue se recuperar com segurança.&lt;/p&gt;
&lt;p&gt;É diferente de uma aplicação travar. O kernel é a base comum do sistema; se ele perde a capacidade de manter invariantes fundamentais, parar pode ser menos perigoso do que continuar corrompendo estado.&lt;/p&gt;
&lt;h2&gt;Como consultar sem decorar tudo&lt;/h2&gt;
&lt;p&gt;Ninguém precisa memorizar este glossário inteiro. O objetivo é reconhecer as fronteiras: kernel não é distribuição, terminal não é shell, serviço não é necessariamente daemon, container não é VM, filesystem não é partição e root pode significar usuário, diretório ou privilégio dependendo da frase.&lt;/p&gt;
&lt;p&gt;Quando um termo aparecer, comece pelas man pages:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;man 1 comando
man 2 syscall
man 5 formato-de-arquivo
man 7 conceito
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As seções também carregam informação. &lt;code&gt;printf(1)&lt;/code&gt; é um comando; &lt;code&gt;printf(3)&lt;/code&gt; é uma função de biblioteca. &lt;code&gt;systemd.service(5)&lt;/code&gt; documenta o formato das units de serviço. A &lt;a href=&quot;https://man7.org/linux/man-pages/&quot;&gt;coleção Linux man-pages&lt;/a&gt; é uma das melhores portas de entrada para interfaces do kernel e da libc.&lt;/p&gt;
&lt;p&gt;Depois, procure a documentação do projeto ou da distribuição. Arch Wiki é excelente, mas não substitui toda documentação upstream. Um tutorial pode ensinar o procedimento; a documentação costuma explicar o contrato, as limitações e o que acontece quando você sai do caminho feliz.&lt;/p&gt;
&lt;h2&gt;O vocabulário é parte da ferramenta&lt;/h2&gt;
&lt;p&gt;Aprender Linux não é decorar cinquenta comandos para parecer confortável diante de um terminal. É construir um modelo mental que permita prever onde cada problema pode estar.&lt;/p&gt;
&lt;p&gt;Quando você entende as camadas, uma mensagem deixa de ser “o Linux quebrou”. Pode ser o bootloader não encontrando o kernel, o initramfs sem o módulo necessário, uma unit falhando, um processo bloqueado por permissões, um cgroup encerrando a aplicação por memória ou o DNS fazendo o que ele faz de melhor: virar suspeito antes mesmo de você terminar o café.&lt;/p&gt;
&lt;p&gt;O sistema não fica menos complexo. Ele fica menos misterioso. E essa diferença é o que separa copiar comandos de realmente administrar uma máquina.&lt;/p&gt;
&lt;h2&gt;Referências e leituras recomendadas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.kernel.org/&quot;&gt;Documentação oficial do kernel Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/&quot;&gt;Linux man-pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/bash/manual/bash.html&quot;&gt;Bash Reference Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/coreutils/manual/coreutils.html&quot;&gt;GNU Coreutils Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html&quot;&gt;Filesystem Hierarchy Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/&quot;&gt;Documentação do systemd&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9799919799/&quot;&gt;POSIX.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://opencontainers.org/&quot;&gt;Open Container Initiative&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.nftables.org/&quot;&gt;Documentação do nftables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://man.openbsd.org/ssh&quot;&gt;OpenSSH manual pages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Window Managers: quando o desktop para de tentar pensar por você</title><link>https://blog.kristyan.dev/posts/window-managers-quando-o-desktop-para-de-tentar-pensar-por-voce</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/window-managers-quando-o-desktop-para-de-tentar-pensar-por-voce</guid><description>Uma introdução histórica e técnica aos Window Managers no Linux, do X11 aos compositores Wayland, com comparações reais contra Desktop Environments e recomendações pessoais.</description><pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Eu entendo quem olha para GNOME, KDE Plasma ou Cinnamon e pensa: “pronto, é isso, esse é o desktop Linux”. Faz sentido. Tem painel, menu, configurações, notificações, gerenciador de arquivos, tema, wallpaper, login bonito e aquela sensação maravilhosa de que alguém já tomou várias decisões por você.&lt;/p&gt;
&lt;p&gt;O problema é justamente esse: alguém já tomou várias decisões por você.&lt;/p&gt;
&lt;p&gt;Um Window Manager nasce quase como uma resposta mal-humorada a essa ideia. Ele não tenta ser “a experiência completa”. Ele não quer ser seu centro de controle, sua loja de extensões, seu painel de clima, sua dock, sua central de contas online e seu assistente espiritual. Um WM quer resolver uma pergunta muito mais específica:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;onde as janelas ficam, como elas se comportam e como você interage com elas?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Parece pouco. Até você perceber que boa parte da sua experiência no computador é exatamente isso.&lt;/p&gt;
&lt;h2&gt;WM não é Desktop Environment, e essa confusão importa&lt;/h2&gt;
&lt;p&gt;Um Desktop Environment, ou DE, é um pacote inteiro de experiência gráfica. GNOME, KDE Plasma, XFCE, Cinnamon e LXQt não são apenas “jeitos de mostrar janela”. Eles normalmente entregam um conjunto completo: gerenciador de janelas ou compositor, painel, launcher, configurações gráficas, integração com rede, áudio, energia, temas, sessão, portal de permissões, aplicativos padrão e um monte de serviço que você só lembra que existe quando quebra.&lt;/p&gt;
&lt;p&gt;Um Window Manager é bem mais específico. No X11, ele é o componente que decide o posicionamento, foco, decoração, empilhamento e comportamento das janelas. A aplicação pede para aparecer. O servidor X fornece o sistema gráfico. O WM entra no meio e diz: “calma, amigo, você vai abrir aqui, com esse tamanho, nessa área de trabalho e talvez sem essa borda horrorosa”.&lt;/p&gt;
&lt;p&gt;No Wayland, a conversa muda um pouco. A figura tradicional do “WM separado” deixa de existir do mesmo jeito, porque o compositor Wayland é o próprio display server. A arquitetura oficial do Wayland descreve justamente essa mudança: no X, o servidor X fica no meio de clientes, compositor e hardware; no Wayland, o compositor recebe eventos do kernel, decide qual superfície deve receber entrada e compõe a tela diretamente. Ou seja: em Wayland, Hyprland, Sway, Niri e Mango não são apenas “window managers” no sentido clássico do X11. Eles são compositores Wayland.&lt;/p&gt;
&lt;p&gt;Na prática, a comunidade continua chamando tudo de WM porque linguagem técnica também tem suas preguiças históricas. Mas o detalhe importa. No X11 você podia trocar Openbox por i3, manter Xorg e ainda colocar um compositor como picom por cima. No Wayland, o compositor é a sessão gráfica. Você não “mistura” compositores Wayland como misturava peças no X11. Escolher Hyprland ou Niri é escolher o servidor gráfico daquela sessão.&lt;/p&gt;
&lt;p&gt;Isso explica muita coisa: por que suporte a captura de tela, screen sharing, input method, fractional scaling, tablets, NVIDIA e XWayland varia tanto entre compositores Wayland. Não é só “o WM ainda não implementou um detalhe”. Muitas vezes é parte da pilha gráfica inteira.&lt;/p&gt;
&lt;h2&gt;O X11 venceu porque não tentou ser uma opinião fechada&lt;/h2&gt;
&lt;p&gt;A história dos WMs no Unix/Linux passa obrigatoriamente pelo X Window System. O X nasceu no MIT em 1984, dentro do contexto do Project Athena, com uma ideia forte: criar um sistema gráfico independente de hardware, rede e fornecedor. A grande sacada do X11 não era ser bonito. Era ser um protocolo.&lt;/p&gt;
&lt;p&gt;E como todo protocolo que sobrevive tempo demais, ele virou infraestrutura, legado, piada e milagre ao mesmo tempo.
&lt;a href=&quot;https://blog.kristyan.dev/posts/x11-xorg-wayland-desktop-linux&quot;&gt;Já comentei sobre.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Um dos princípios mais importantes do X11 era “mechanism, not policy”. A especificação entregava mecanismos para janelas, eventos, desenho, entrada e comunicação, mas não impunha uma política de interface. O X não dizia se uma janela deveria flutuar, ocupar metade da tela, ter borda azul, foco por clique, foco seguindo mouse, barra de título ou botão de minimizar.&lt;/p&gt;
&lt;p&gt;Isso abriu espaço para uma explosão de Window Managers. twm, fvwm, Window Maker, Enlightenment, Blackbox, Fluxbox, Openbox, IceWM, AfterStep, Sawfish, Metacity, KWin, Mutter, AwesomeWM, xmonad, dwm, i3, bspwm, herbstluftwm e por aí vai.&lt;/p&gt;
&lt;p&gt;O X11 era modular a ponto de permitir combinações absurdas. Às vezes bonitas. Às vezes uma instalação do Arch às 3h da manhã sem áudio, sem barra, sem wallpaper e com um terminal ocupando a tela inteira. Liberdade tem dessas coisas.&lt;/p&gt;
&lt;p&gt;Essa flexibilidade também exigiu convenções. O ICCCM, por exemplo, surgiu para definir como clientes X, Window Managers e outros componentes deveriam se comportar entre si. Ele trata de detalhes como foco, estado da janela, ícones, reparenting e comunicação entre clientes. Depois vieram convenções como EWMH/NetWM, usadas para recursos mais modernos de desktop, como áreas de trabalho, painéis, fullscreen, janela urgente e integração com pagers.&lt;/p&gt;
&lt;p&gt;Esse é o tipo de detalhe invisível que separa “um programa desenhou uma janela” de “um desktop minimamente utilizável”. O usuário não pensa em ICCCM quando abre um terminal. Ainda bem. Mas o WM pensa, ou pelo menos deveria.&lt;/p&gt;
&lt;h2&gt;Stacking, tiling e a guerra santa do espaço na tela&lt;/h2&gt;
&lt;p&gt;O modelo mais familiar é o stacking, ou floating. É o modelo das janelas sobrepostas: você abre um navegador, arrasta para o lado, redimensiona, joga o terminal por cima, perde uma janela atrás de outra, minimiza, maximiza, clica na dock, se arrepende. É o paradigma do desktop como mesa física: janelas como papéis empilhados.&lt;/p&gt;
&lt;p&gt;Esse modelo é ótimo para uso geral. Ele é intuitivo, combina com mouse e funciona bem para pessoas que não querem transformar o ato de abrir um programa em uma filosofia de vida.&lt;/p&gt;
&lt;p&gt;O tiling parte de outra ideia: janelas não deveriam se sobrepor por padrão. Se você abriu duas janelas, cada uma recebe uma parte da tela. Abriu três, o layout se reorganiza. Abriu dez, talvez você já tenha perdido o controle da sua vida, mas pelo menos o WM tentou manter tudo visível.&lt;/p&gt;
&lt;p&gt;Existem variações importantes aqui.&lt;/p&gt;
&lt;p&gt;O &lt;strong&gt;tiling manual&lt;/strong&gt;, como no i3, dá bastante controle ao usuário. Você decide dividir horizontalmente, verticalmente, empilhar, tabular, mover para outro workspace. É previsível, mas exige intenção.&lt;/p&gt;
&lt;p&gt;O &lt;strong&gt;tiling dinâmico&lt;/strong&gt;, como em dwm, AwesomeWM e Hyprland, trabalha mais com layouts predefinidos. O WM aplica uma estrutura: master/stack, monocle, dwindle, spiral, grid, scrolling e outras invenções que parecem nome de magia em RPG.&lt;/p&gt;
&lt;p&gt;O &lt;strong&gt;scrolling tiling&lt;/strong&gt;, como no Niri, é uma ideia mais recente e interessante: em vez de espremer tudo na tela, ele cria uma faixa “infinita” de colunas. Novas janelas entram à direita e as antigas não precisam ser redimensionadas toda vez. É menos “mosaico fixo” e mais “linha do tempo de janelas”.&lt;/p&gt;
&lt;p&gt;Essa diferença parece pequena até você usar por alguns dias. Um WM tiling muda seu hábito. Você para de “procurar janela” e começa a organizar contexto. Um workspace para navegador. Outro para código. Outro para terminal. Outro para comunicação. Outro para aquele PDF que você abriu para ler e claramente nunca vai terminar.&lt;/p&gt;
&lt;h2&gt;O tiling não é novo, só voltou com estética de dotfiles&lt;/h2&gt;
&lt;p&gt;Existe uma tendência engraçada de tratar tiling WM como coisa moderna, minimalista, de usuário Arch com wallpaper de anime e terminal translúcido. Mas a ideia de janelas em mosaico é antiga.&lt;/p&gt;
&lt;p&gt;Interfaces de janelas lado a lado aparecem desde sistemas gráficos dos anos 1980. No mundo X, já havia experimentos de tiling no fim da década de 1980, como o Siemens RTL Tiled Window Manager. Depois vieram décadas de WMs empilhados, ambientes completos e uma certa padronização em torno do desktop “normal”.&lt;/p&gt;
&lt;p&gt;A onda moderna dos tiling WMs tem outro gosto. Ela vem da cultura Unix, da preferência por teclado, de configuração textual, de composição com ferramentas pequenas e de um certo cansaço com desktops que tentam resolver tudo com um painel de preferências.&lt;/p&gt;
&lt;p&gt;O i3, lançado em 2009, é talvez o melhor exemplo dessa virada para muita gente. Ele não foi o primeiro, nem o mais minimalista, nem o mais academicamente elegante. Mas acertou algo importante: documentação boa, configuração compreensível, árvore de containers, suporte decente a múltiplos monitores e um fluxo que dá para aprender sem compilar o próprio sofrimento.&lt;/p&gt;
&lt;p&gt;O dwm foi para outro lado: minimalismo radical, configuração em C, patch em cima de patch e aquela filosofia suckless de “menos é mais”, desde que você aceite recompilar o programa para mudar comportamento. O xmonad trouxe Haskell para a festa, porque aparentemente alguém achou que configurar janelas também precisava de pureza funcional. O AwesomeWM apostou em Lua e extensibilidade. O bspwm separou o WM de forma bem Unix: ele gerencia janelas, você controla via comandos. O herbstluftwm também foi para esse lado de scriptabilidade forte.&lt;/p&gt;
&lt;p&gt;Cada um desses WMs é quase uma opinião sobre como o usuário deveria pensar o desktop.&lt;/p&gt;
&lt;h2&gt;O que muda com Wayland&lt;/h2&gt;
&lt;p&gt;Wayland não é apenas “o X11 moderno”. Essa frase é confortável, mas incompleta.&lt;/p&gt;
&lt;p&gt;No X11, muita coisa era aberta demais. Qualquer cliente podia observar eventos demais, capturar informações demais, interferir demais. Isso era útil para automação, captura, ferramentas de acessibilidade e gambiarras legítimas. Também era ruim para isolamento, segurança e previsibilidade.&lt;/p&gt;
&lt;p&gt;Wayland muda a arquitetura. O compositor vira o centro da sessão. Ele recebe entrada, decide foco, gerencia superfícies, compõe buffers e fala diretamente com KMS/DRM no kernel para exibir a tela. Aplicações renderizam em buffers e entregam esses buffers ao compositor.&lt;/p&gt;
&lt;p&gt;Isso traz ganhos reais: menos caminhos tortos, melhor modelo de segurança, composição obrigatória, suporte moderno a DPI, frames, tearing control, gestos e uma base mais coerente para o desktop Linux atual.&lt;/p&gt;
&lt;p&gt;Mas também traz custo. Coisas que eram “fáceis” no X11 viraram dependentes de protocolos específicos. Screen sharing precisa de xdg-desktop-portal. Captura global de teclado é restrita. Ferramentas de automação precisam de interfaces explícitas. Clipboard, input methods, fractional scaling e color management dependem de maturidade do compositor e dos protocolos.&lt;/p&gt;
&lt;p&gt;É mais correto? Sim. É mais chato? Também.&lt;/p&gt;
&lt;p&gt;A parte boa é que a nova geração de compositores Wayland está ficando madura. Sway trouxe a proposta de ser um substituto compatível com i3 no Wayland. Hyprland tornou o tiling Wayland visualmente atraente sem pedir desculpa por gostar de animação. Niri está explorando um paradigma diferente com scrolling tiling. Mango tenta pegar a filosofia do dwl/dwm e torná-la mais prática para uso diário.&lt;/p&gt;
&lt;p&gt;O Linux desktop sempre foi um laboratório. A diferença é que agora o laboratório tem blur, fractional scaling e bug de portal.&lt;/p&gt;
&lt;h2&gt;Por que usar um WM em vez de um DE?&lt;/h2&gt;
&lt;p&gt;A resposta ruim seria: “porque é mais leve”.&lt;/p&gt;
&lt;p&gt;É verdade, mas é uma meia verdade meio preguiçosa. Sim, um WM puro costuma consumir menos recursos do que um DE completo. Mas se você instala compositor, barra, launcher, daemon de notificações, polkit agent, wallpaper daemon, applet de rede, gerenciador de clipboard, portal, lockscreen, idle daemon e meia dúzia de scripts, você acabou de montar um DE artesanal. Parabéns, agora o problema é seu.&lt;/p&gt;
&lt;p&gt;A razão melhor é controle.&lt;/p&gt;
&lt;p&gt;Um WM permite construir um fluxo de trabalho em vez de aceitar um fluxo pronto. Você decide como alternar janelas, como criar workspaces, como mover aplicações entre monitores, qual launcher usar, qual barra exibir, quais atalhos existem, quais janelas flutuam, quais abrem em fullscreen, quais vão para um workspace específico e qual pedaço do sistema deve simplesmente não existir.&lt;/p&gt;
&lt;p&gt;Isso é excelente para desenvolvedores, administradores de sistema, usuários de terminal, pessoas com múltiplos monitores, quem trabalha com logs, editores, documentação, navegador e terminal o dia inteiro.&lt;/p&gt;
&lt;p&gt;Também é péssimo para quem só quer instalar o sistema e usar.&lt;/p&gt;
&lt;p&gt;Essa é a honestidade que muita introdução a WM evita: um WM não é necessariamente “melhor”. Ele é mais explícito. Ele troca conveniência por controle. E controle tem custo.&lt;/p&gt;
&lt;p&gt;Você vai configurar coisa boba. Vai descobrir que seu tema GTK não aplica no seletor de arquivos. Vai precisar entender portal. Vai configurar screen sharing. Vai escolher um launcher. Vai se irritar com Electron rodando em XWayland. Vai descobrir que “abrir app no monitor certo” é uma pequena tese de doutorado dependendo do compositor.&lt;/p&gt;
&lt;p&gt;Mas quando fica bom, fica muito bom.&lt;/p&gt;
&lt;h2&gt;Minha ordem atual: Hyprland, Mango, Niri e i3&lt;/h2&gt;
&lt;p&gt;Eu colocaria minha preferência pessoal hoje nessa ordem: &lt;strong&gt;Hyprland, Mango, Niri e i3&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Não é uma lista universal. É uma lista de uso, gosto e tolerância pessoal à gambiarra.&lt;/p&gt;
&lt;h3&gt;Hyprland: o tiling Wayland que entendeu que estética também importa&lt;/h3&gt;
&lt;p&gt;Hyprland é provavelmente o compositor Wayland tiling mais chamativo dos últimos anos. E sim, parte disso vem da estética: animações, blur, bordas arredondadas, transições, layouts modernos, screenshots bonitas e aquele apelo de “meu desktop parece uma demo”.&lt;/p&gt;
&lt;p&gt;Mas reduzir Hyprland a rice de unixporn é injusto. Ele tem uma combinação forte: tiling dinâmico, configuração rica, regras por janela, IPC via &lt;code&gt;hyprctl&lt;/code&gt;, ecossistema próprio e boa integração com utilitários modernos de Wayland. A documentação oficial inclusive deixa claro um ponto que muita gente vindo do X11 ignora: compositor Wayland não deve ser confundido com WM de Xorg. Ele é a sessão gráfica.&lt;/p&gt;
&lt;p&gt;O lado ruim é o mesmo de quase todo projeto popular e em movimento rápido: você precisa acompanhar mudanças, ler documentação e aceitar que algumas coisas podem quebrar em atualizações. Hyprland não é a opção mais conservadora. É a opção que eu escolheria para uma máquina pessoal moderna, especialmente se o objetivo for um desktop bonito, rápido e altamente configurável.&lt;/p&gt;
&lt;p&gt;É bonito no README e, surpreendentemente, não é triste no dia a dia — desde que você aceite cuidar da própria casa.&lt;/p&gt;
&lt;h3&gt;Mango: dwm/dwl com mais vontade de ser usável&lt;/h3&gt;
&lt;p&gt;Mango me interessa por outro motivo. Ele se apresenta como um compositor Wayland rápido e rico em recursos, construído em cima do dwl, com a proposta de manter leveza e adicionar o que torna o compositor utilizável no dia a dia: XWayland, tags, layouts flexíveis, animações, scratchpad, IPC, hot reload de configuração e efeitos.&lt;/p&gt;
&lt;p&gt;A ideia é boa porque toca em uma dor real. Projetos minimalistas são lindos até você precisar trabalhar com eles oito horas por dia. A filosofia “faça uma coisa bem feita” vira “faça você mesmo todo o resto” muito rápido.&lt;/p&gt;
&lt;p&gt;O Mango tenta ficar num meio-termo: ainda tem cheiro de dwm/dwl, mas não parece tão interessado em transformar cada ajuste em prova de iniciação. Tags em vez de workspaces fixos também são interessantes para quem gosta de um modelo mais flexível de organização.&lt;/p&gt;
&lt;p&gt;Eu ainda trataria Mango como uma escolha para quem gosta de mexer. Não é o caminho que eu recomendaria para alguém que acabou de descobrir tiling. Mas para quem já passou por i3, Sway, dwm ou Hyprland e quer algo mais enxuto, com ideias boas e ritmo de projeto novo, faz sentido.&lt;/p&gt;
&lt;h3&gt;Niri: estranho do jeito certo&lt;/h3&gt;
&lt;p&gt;Niri é o tipo de projeto que eu respeito porque não está apenas copiando o fluxo de outro WM no Wayland. Ele tenta uma ideia diferente: scrollable tiling.&lt;/p&gt;
&lt;p&gt;No Niri, janelas são organizadas em colunas numa faixa horizontal que cresce para a direita. Abrir uma nova janela não força as antigas a encolherem. Cada monitor tem sua própria faixa de janelas, e os workspaces são dinâmicos e organizados verticalmente. Isso muda o modelo mental.&lt;/p&gt;
&lt;p&gt;No começo, parece esquisito. Depois você entende a intenção: preservar contexto. Em vez de transformar cada workspace numa competição por pixels, o Niri deixa você navegar por uma sequência de janelas. Para alguns fluxos — logs, documentação, navegador, editor, terminal, múltiplos projetos — isso pode ser excelente.&lt;/p&gt;
&lt;p&gt;O custo é reaprender. Se você vem de i3, Hyprland ou Sway, sua memória muscular vai reclamar. O Niri não quer ser só “i3 com scroll”. Ele quer que você pense em janelas como uma faixa contínua. É uma escolha forte, e escolha forte sempre divide opinião.&lt;/p&gt;
&lt;p&gt;Eu gosto dele como ideia e como projeto. Talvez não seja meu compositor principal para tudo, mas é um dos WMs/compositores mais interessantes para observar agora. Ele mostra que Wayland não precisa ser apenas “vamos recriar o X11 com nomes novos”.&lt;/p&gt;
&lt;h3&gt;i3: velho, maduro e ainda difícil de bater como porta de entrada&lt;/h3&gt;
&lt;p&gt;O i3 continua sendo a recomendação mais fácil para quem quer entender tiling de verdade.&lt;/p&gt;
&lt;p&gt;Ele é X11, escrito em C, bem documentado, configurável por arquivo de texto e baseado em uma árvore de containers. O guia oficial explica o básico sem mistério: &lt;code&gt;$mod+Enter&lt;/code&gt; abre um terminal, novas janelas dividem o espaço, layouts podem ser split, stacking ou tabbed, workspaces agrupam contextos e tudo pode ser controlado pelo teclado.&lt;/p&gt;
&lt;p&gt;O i3 é menos “uau” do que Hyprland. Não tem o mesmo apelo visual. Não é Wayland. Não é novidade. Mas isso também é uma qualidade. Ele é previsível, estável, pesquisável e cheio de exemplos. Se você quer aprender o conceito sem brigar com metade da stack Wayland, i3 ainda é excelente.&lt;/p&gt;
&lt;p&gt;Eu não colocaria i3 como minha primeira escolha hoje para uma instalação nova em hardware moderno, principalmente porque Wayland já faz mais sentido para muita coisa. Mas como escola de tiling WM, ele continua ótimo. É o tipo de ferramenta que talvez você substitua depois, mas dificilmente se arrepende de ter aprendido.&lt;/p&gt;
&lt;h2&gt;O que um DE ainda faz melhor&lt;/h2&gt;
&lt;p&gt;Existe um certo teatro em comunidades Linux de fingir que usar WM puro é uma forma superior de existência. Não é.&lt;/p&gt;
&lt;p&gt;DEs resolvem problemas reais. GNOME e KDE Plasma entregam integração. Eles cuidam de portal, sessão, configurações, acessibilidade, temas, input methods, notificações, energia, Bluetooth, rede, monitores, touchpad, permissões e aplicativos padrão. Você perde controle fino, mas ganha coerência.&lt;/p&gt;
&lt;p&gt;Para notebook, usuário comum, ambiente corporativo, máquina compartilhada ou pessoa que não quer transformar o desktop em hobby, um DE é muitas vezes a escolha correta.&lt;/p&gt;
&lt;p&gt;WMs brilham quando o computador é ferramenta de trabalho técnico e você quer moldar a interface ao seu fluxo. DEs brilham quando o ambiente precisa simplesmente funcionar com menos manutenção manual.&lt;/p&gt;
&lt;p&gt;A diferença não é “leve versus pesado”. A diferença é &lt;strong&gt;produto versus kit&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Um DE é um produto. Um WM é uma caixa de peças. Quem gosta de montar a própria bancada vai amar. Quem só queria uma mesa para colocar o notebook vai achar uma doença.&lt;/p&gt;
&lt;h2&gt;O mínimo que você precisa saber antes de migrar&lt;/h2&gt;
&lt;p&gt;Se você vai sair de um DE para um WM, vá com a expectativa certa. O WM não vai trazer tudo.&lt;/p&gt;
&lt;p&gt;Você provavelmente vai precisar escolher:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;uma barra, como Waybar, i3bar, polybar ou similar;&lt;/li&gt;
&lt;li&gt;um launcher, como rofi, wofi, fuzzel ou dmenu;&lt;/li&gt;
&lt;li&gt;um terminal;&lt;/li&gt;
&lt;li&gt;um daemon de notificações;&lt;/li&gt;
&lt;li&gt;um gerenciador de wallpaper;&lt;/li&gt;
&lt;li&gt;um lockscreen;&lt;/li&gt;
&lt;li&gt;um polkit agent;&lt;/li&gt;
&lt;li&gt;um clipboard manager;&lt;/li&gt;
&lt;li&gt;ferramentas para screenshot e gravação;&lt;/li&gt;
&lt;li&gt;portal para screen sharing, especialmente em Wayland.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Isso parece uma lista chata porque é uma lista chata. Mas ela revela algo importante: um desktop não é só janela. Desktop é integração.&lt;/p&gt;
&lt;p&gt;Quando alguém mostra um setup lindo de Hyprland, Niri ou i3, aquilo não é só o WM. É um conjunto de escolhas: tema GTK, fonte, terminal, shell, barra, launcher, atalhos, scripts, wallpaper, compositor, portal, clipboard, notificações e provavelmente umas três gambiarras que o autor esqueceu que fez.&lt;/p&gt;
&lt;p&gt;Por isso, a pergunta certa não é “qual WM é melhor?”. A pergunta certa é:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;qual quantidade de controle eu quero assumir?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Se a resposta for “pouca”, use KDE ou GNOME e seja feliz. Se a resposta for “muita”, bem-vindo. Tem um arquivo de configuração esperando para estragar sua noite.&lt;/p&gt;
&lt;h2&gt;WMs são uma aula prática de arquitetura&lt;/h2&gt;
&lt;p&gt;A melhor parte de usar Window Managers não é ganhar 200 MB de RAM. Isso é troféu de benchmark de fórum.&lt;/p&gt;
&lt;p&gt;A melhor parte é entender a arquitetura do desktop.&lt;/p&gt;
&lt;p&gt;Você aprende que janela não é só janela. Existe display server, compositor, protocolo, buffer, evento de input, foco, workspace, regra, portal, XWayland, clipboard, sessão, monitor, scaling, renderização e um monte de contrato implícito entre aplicação e ambiente gráfico.&lt;/p&gt;
&lt;p&gt;Você começa a entender por que screen sharing quebra. Por que Electron às vezes abre em XWayland. Por que tema não aplica em todo lugar. Por que Wayland é mais seguro, mas às vezes mais irritante. Por que X11 era flexível, mas flexível daquele jeito que também permite amarrar tomada com fita isolante.&lt;/p&gt;
&lt;p&gt;Um WM te força a olhar para a pilha. E isso, para quem gosta de Linux, é quase inevitável. Usar Linux por tempo suficiente é descobrir que “interface gráfica” não é uma coisa. É um acordo de paz temporário entre vários programas que discordam em silêncio.&lt;/p&gt;
&lt;h2&gt;Então, por onde começar?&lt;/h2&gt;
&lt;p&gt;Se você nunca usou tiling WM, eu começaria pelo i3 ou pelo Sway. O i3 ensina o modelo clássico no X11. O Sway te dá uma experiência parecida no Wayland. Ambos têm documentação boa e comportamento previsível.&lt;/p&gt;
&lt;p&gt;Se você já entende o básico e quer um desktop moderno, eu iria de Hyprland. É o que eu recomendo para quem quer Wayland, tiling dinâmico, visual forte e bastante material de comunidade.&lt;/p&gt;
&lt;p&gt;Se você gosta de projetos mais enxutos e quer algo com cara de dwm/dwl, mas mais prático, Mango é uma opção interessante para testar.&lt;/p&gt;
&lt;p&gt;Se você quer experimentar um paradigma diferente de verdade, Niri é o nome. Talvez você ame. Talvez odeie. Mas pelo menos vai sair com uma opinião, e isso já é mais do que muito software genérico consegue provocar.&lt;/p&gt;
&lt;p&gt;O importante é não tratar WM como religião. Use o que melhora seu fluxo. Troque quando parar de fazer sentido. Copie dotfiles com vergonha moderada. Leia documentação. Faça backup da config. E lembre que um desktop bonito não vale muita coisa se você precisa lutar com ele toda manhã.&lt;/p&gt;
&lt;p&gt;Window Managers não são melhores por definição. Eles só são mais honestos sobre o custo da liberdade.&lt;/p&gt;
&lt;p&gt;Um DE te entrega uma casa mobiliada. Um WM te entrega o terreno, umas ferramentas e a liberdade de colocar a porta no teto.&lt;/p&gt;
&lt;p&gt;Às vezes é exatamente isso que você queria.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Licença de software não é rodapé</title><link>https://blog.kristyan.dev/posts/licenca-de-software-nao-e-rodape</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/licenca-de-software-nao-e-rodape</guid><description>Como GPL, MIT, Apache, BSD, CC0 e licenças source-available definem poder, colaboração, apropriação e sustentabilidade no software.</description><pubDate>Thu, 25 Jun 2026 19:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Licença de software é aquele arquivo que muita gente ignora até o jurídico aparecer na sala, até uma dependência virar risco de distribuição, até um fornecedor mudar as regras no meio do jogo, ou até uma empresa descobrir que “estava no GitHub” não significa “posso enfiar no produto e fingir que nasceu aqui”.&lt;/p&gt;
&lt;p&gt;O problema é que licença parece burocracia porque fica no lugar mais sem graça possível do repositório: &lt;code&gt;LICENSE&lt;/code&gt;, &lt;code&gt;COPYING&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;Cargo.toml&lt;/code&gt;, rodapé de documentação. Um canto morto. Um detalhe administrativo. Um texto com cara de contrato que ninguém quer ler porque a vida já é curta o suficiente sem precisar decifrar parágrafo sobre redistribuição, sublicenciamento, patente e ausência de garantia.&lt;/p&gt;
&lt;p&gt;Só que esse arquivo pequeno define coisas grandes. Ele define quem pode usar o código. Quem pode vender. Quem pode modificar. Quem precisa devolver mudanças. Quem pode empacotar em uma distribuição Linux. Quem pode transformar aquilo em SaaS. Quem pode fechar o código depois. Quem pode criar um fork sem pedir benção. Quem carrega o custo real de manter a infraestrutura digital que todo mundo usa, inclusive quem aparece depois para capturar valor com a serenidade de quem descobriu fogo.&lt;/p&gt;
&lt;p&gt;Licença não é só um rodapé jurídico. É arquitetura social.&lt;/p&gt;
&lt;p&gt;E, como toda arquitetura, ela embute política.&lt;/p&gt;
&lt;h2&gt;Antes de licença virar guerra santa&lt;/h2&gt;
&lt;p&gt;No começo, software não era exatamente um produto separado. Durante décadas, especialmente no ambiente de universidades, laboratórios, mainframes e centros de pesquisa, código circulava de forma muito mais informal. O valor comercial estava no hardware, no serviço, no acesso à máquina, no contrato de suporte. Software era frequentemente distribuído junto, compartilhado entre pesquisadores e adaptado por quem precisava fazer a máquina trabalhar. A cultura hacker nasceu nesse caldo: pessoas mexendo, corrigindo, melhorando e passando adiante porque era assim que o trabalho avançava.&lt;/p&gt;
&lt;p&gt;Isso não quer dizer que o passado era um paraíso comunal de bytes puros e boas intenções. Nunca foi. Empresas sempre tiveram interesses, universidades sempre tiveram regras, e o direito autoral nunca tirou férias. Mas o software ainda não estava tão consolidado como mercadoria autônoma, fechada, empacotada e vendida como unidade central de poder.&lt;/p&gt;
&lt;p&gt;Quando o software começou a se separar do hardware e virar produto por si só, a relação mudou. O acesso ao código-fonte deixou de ser algo presumido e passou a ser uma concessão rara. A possibilidade de estudar e modificar um programa saiu do campo da prática cotidiana e entrou no campo da permissão. A máquina continuava sua, mas o comportamento dela passava a ser controlado por alguém que não estava na sala.&lt;/p&gt;
&lt;p&gt;É nesse contexto que o movimento do software livre aparece não como uma birra acadêmica contra empresas, mas como reação a uma mudança material na relação entre usuário e computador. A &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html&quot;&gt;Free Software Foundation define software livre&lt;/a&gt; a partir de liberdades: executar o programa para qualquer finalidade, estudar como ele funciona, redistribuir cópias e distribuir versões modificadas. O detalhe importante, que muita tradução ruim enterra, é que “free” ali é liberdade, não preço. Software livre pode ser vendido. O ponto não é “grátis”. O ponto é controle.&lt;/p&gt;
&lt;p&gt;Richard Stallman, GNU e a FSF colocaram uma tese forte na mesa: se o usuário não pode estudar, modificar e compartilhar o programa que executa, ele está subordinado ao fornecedor. Pode parecer exagerado quando estamos falando de um utilitário bobo, mas fica menos engraçado quando o software controla seu telefone, seu carro, sua comunicação, seu roteador, sua infraestrutura de produção ou o sistema que decide se você pode trabalhar hoje.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GPL&lt;/a&gt; foi a materialização jurídica dessa tese. Ela usa copyright contra o fechamento do código. Em vez de simplesmente dizer “faça qualquer coisa”, ela diz algo mais específico: você pode usar, estudar, modificar e redistribuir, mas se distribuir uma versão derivada, precisa preservar essas mesmas liberdades para os próximos. Copyleft é isso: reciprocidade forçada por licença. Não é só generosidade; é uma trava arquitetural para impedir que o comum vire insumo gratuito de software proprietário.&lt;/p&gt;
&lt;h2&gt;Software livre e open source não são sinônimos perfeitos&lt;/h2&gt;
&lt;p&gt;Em 1998, parte da comunidade passou a usar “open source” como uma forma mais palatável de vender a ideia para empresas. A &lt;a href=&quot;https://opensource.org/osd&quot;&gt;Open Source Initiative&lt;/a&gt; define open source por critérios de licença: redistribuição livre, acesso a código-fonte, permissão para trabalhos derivados, ausência de discriminação contra pessoas, grupos ou campos de atuação, neutralidade tecnológica e por aí vai. É uma definição prática, operacional, muito útil para saber se uma licença permite colaboração real ou se só colocou o código na vitrine.&lt;/p&gt;
&lt;p&gt;Mas a troca de nome também foi uma troca de ênfase. O próprio GNU critica essa mudança no texto &lt;a href=&quot;https://www.gnu.org/philosophy/open-source-misses-the-point.html&quot;&gt;“Why Open Source Misses the Point of Free Software”&lt;/a&gt;: software livre fala de liberdade do usuário; open source tende a falar de eficiência, qualidade, colaboração e vantagem prática. Um discurso pergunta “quem controla o computador?”. O outro pergunta “esse modelo produz software melhor?”.&lt;/p&gt;
&lt;p&gt;Na prática, muitos projetos cabem nas duas caixas ao mesmo tempo. Linux, Git, PostgreSQL, Python, Firefox, Apache HTTP Server, LLVM, Kubernetes: o mundo real é cheio de projetos que as pessoas chamam de open source e que também respeitam liberdades fundamentais. O problema começa quando os termos viram maquiagem.&lt;/p&gt;
&lt;p&gt;Código disponível não é automaticamente open source. Se você pode ler o código, mas não pode usar comercialmente, modificar livremente, redistribuir ou oferecer em determinados contextos, isso pode ser “source-available”, não open source. A OSI é explícita: open source não significa apenas acesso ao código-fonte. A licença precisa permitir uso, modificação e redistribuição sem discriminar áreas de atuação.&lt;/p&gt;
&lt;p&gt;Esse detalhe virou central nos últimos anos porque várias empresas descobriram que “open source” é ótimo para adoção, comunidade e reputação, mas bem desconfortável quando um provedor de nuvem pega o projeto, empacota como serviço gerenciado, ganha dinheiro e devolve pouco. A reação foi uma onda de licenças source-available, como SSPL, BSL e licenças próprias com restrições de oferta como serviço.&lt;/p&gt;
&lt;p&gt;Dá para entender a motivação. Também dá para entender a crítica. O fato de uma empresa ter um problema real de captura de valor não transforma automaticamente sua nova licença em open source.&lt;/p&gt;
&lt;h2&gt;A pergunta certa não é “qual licença é melhor?”&lt;/h2&gt;
&lt;p&gt;A pergunta “qual licença devo escolher?” parece técnica, mas quase sempre é uma pergunta sobre futuro. Você não está escolhendo apenas como o código pode ser copiado hoje. Você está escolhendo o que pode acontecer se o projeto crescer, se uma empresa usar, se alguém criar um fork, se uma distribuição Linux empacotar, se um provedor de nuvem transformar em serviço, se você perder interesse, se a comunidade discordar da direção, se o projeto virar dependência de gente que você nunca vai conhecer.&lt;/p&gt;
&lt;p&gt;Por isso, a resposta honesta começa com outra pergunta: o que você quer proteger?&lt;/p&gt;
&lt;p&gt;Se você quer proteger adoção máxima, licenças permissivas costumam ser melhores. Se quer proteger reciprocidade, copyleft faz mais sentido. Se quer proteger uma biblioteca para que ela possa ser usada em produtos fechados sem abrir o produto inteiro, copyleft fraco pode ser o meio-termo. Se quer proteger um servidor contra captura por SaaS, AGPL entra na conversa. Se quer abrir mão praticamente de tudo, CC0 ou Unlicense parecem tentadoras, mas carregam sutilezas jurídicas que muita gente ignora porque “domínio público” soa simples demais.&lt;/p&gt;
&lt;p&gt;O erro é escolher por estética. Colocar MIT porque todo mundo coloca. Colocar GPL porque parece mais ideológico. Colocar Apache porque tem cara de empresa séria. Colocar CC-BY porque você já usou em foto. Colocar nada porque “depois eu vejo”. Licença escolhida sem intenção vira arquitetura acidental. E arquitetura acidental é aquele tipo de coisa que só parece barata antes de alguém depender dela.&lt;/p&gt;
&lt;h2&gt;MIT&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://opensource.org/license/mit&quot;&gt;licença MIT&lt;/a&gt; é provavelmente a licença permissiva mais reconhecida por desenvolvedores que só querem publicar código sem transformar o repositório em seminário jurídico. Ela permite usar, copiar, modificar, mesclar, publicar, distribuir, sublicenciar e vender cópias do software, desde que o aviso de copyright e a permissão sejam preservados. Em termos práticos, é curta, compreensível e amigável para adoção.&lt;/p&gt;
&lt;p&gt;Escolher MIT faz sentido quando o objetivo é reduzir atrito ao máximo. Bibliotecas pequenas, utilitários, projetos pessoais, exemplos educacionais, ferramentas que você quer ver espalhadas pelo mundo, pacotes npm, crates Rust, libs Go e componentes que devem ser incorporados em contextos variados costumam se beneficiar dessa simplicidade. Quem recebe código MIT consegue usar em software livre, open source, proprietário, comercial, interno, embarcado, vendorizado e por aí vai.&lt;/p&gt;
&lt;p&gt;O custo dessa liberdade é a apropriação. MIT permite que uma empresa pegue seu código, modifique, feche, venda e não devolva nada além do aviso de copyright. Isso não é abuso da licença. É a licença funcionando exatamente como foi desenhada. Se você escolhe MIT, precisa estar confortável com a possibilidade de o seu trabalho virar parte de um produto fechado sem que melhorias retornem para você ou para a comunidade.&lt;/p&gt;
&lt;p&gt;MIT é uma boa escolha quando você prefere adoção a reciprocidade. É uma escolha ruim quando você espera que todos que se beneficiem do projeto devolvam modificações. A licença não faz esse acordo. Ela dá permissão ampla e pede pouco. Reclamar depois que alguém usou amplamente é como publicar “pegue à vontade” e ficar surpreso quando aparece alguém com uma empilhadeira.&lt;/p&gt;
&lt;h2&gt;BSD&lt;/h2&gt;
&lt;p&gt;A família BSD tem uma história importante porque vem de um ambiente em que o compartilhamento universitário e a portabilidade Unix moldaram muito do que hoje chamamos de infraestrutura. As versões mais comuns hoje são a &lt;a href=&quot;https://opensource.org/license/bsd-2-clause&quot;&gt;BSD 2-Clause&lt;/a&gt; e a &lt;a href=&quot;https://opensource.org/license/bsd-3-clause&quot;&gt;BSD 3-Clause&lt;/a&gt;. A diferença prática mais lembrada é que a BSD 3-Clause adiciona uma cláusula impedindo usar o nome dos autores ou contribuidores para endossar produtos derivados sem permissão.&lt;/p&gt;
&lt;p&gt;BSD se parece com MIT na filosofia permissiva: use, copie, modifique, redistribua, inclusive em produto proprietário, preservando avisos básicos. A licença não tenta garantir que modificações voltem. Ela tenta garantir que o código possa circular com pouca fricção. Isso explica por que código BSD apareceu em tantos lugares, inclusive em produtos comerciais e sistemas proprietários.&lt;/p&gt;
&lt;p&gt;Escolher BSD faz sentido quando você quer uma licença permissiva clássica, simples e com pedigree forte em sistemas operacionais, redes, ferramentas de baixo nível e infraestrutura. A BSD 3-Clause pode ser preferível quando você quer evitar a interpretação de que sua marca, universidade, empresa ou nome pessoal endossa um derivado. É uma cautela pequena, mas útil. Software não vive só de código; vive também de reputação.&lt;/p&gt;
&lt;p&gt;O risco é o mesmo das permissivas: captura sem retorno. A diferença é mais cultural do que operacional. MIT virou a escolha automática de muita biblioteca moderna. BSD carrega uma tradição mais forte de sistemas, userland, rede e componentes fundacionais. Em ambos os casos, se sua preocupação central é impedir fechamento de derivados, você está olhando para a família errada.&lt;/p&gt;
&lt;h2&gt;Apache 2.0&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.apache.org/licenses/LICENSE-2.0&quot;&gt;Apache License 2.0&lt;/a&gt; também é permissiva, mas não é “MIT com terno e reunião no calendário”. Ela permite uso, modificação, distribuição e sublicenciamento, inclusive em produtos comerciais, mas adiciona uma peça que muda bastante a conversa em ambientes corporativos: concessão explícita de patentes pelos contribuidores, junto com uma cláusula de terminação caso alguém inicie litígio de patente contra o projeto.&lt;/p&gt;
&lt;p&gt;Isso importa porque software grande não vive só de copyright. Vive de patente, marca, contribuição corporativa, aquisição, compliance e medo jurídico. Em projetos com empresas grandes, ecossistemas de infraestrutura, APIs, SDKs, plataformas cloud e fundações, Apache 2.0 costuma ser mais confortável do que MIT justamente porque explicita melhor parte do risco que MIT deixa mais silencioso.&lt;/p&gt;
&lt;p&gt;Escolher Apache 2.0 faz sentido quando você quer permissividade, mas também quer uma base mais robusta para colaboração empresarial. Kubernetes, Android em várias partes do espaço de usuário, Apache HTTP Server e inúmeros projetos de infraestrutura usam Apache 2.0 ou convivem com ela justamente por esse equilíbrio entre liberdade de adoção e governança jurídica mais madura.&lt;/p&gt;
&lt;p&gt;O custo é complexidade. Apache 2.0 é maior, mais formal e tem pontos de compatibilidade que precisam ser verificados. A FSF considera Apache 2.0 compatível com GPLv3, mas não com GPLv2 puro. Esse é o tipo de detalhe que parece irrelevante até você tentar combinar dependências em um produto distribuído. Se o seu projeto é um script de 80 linhas para renomear arquivos, Apache 2.0 talvez seja mais contrato do que problema. Se o projeto tem ambição de virar infraestrutura usada por empresas, ela merece consideração séria.&lt;/p&gt;
&lt;h2&gt;GPL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GNU GPL&lt;/a&gt; é a licença que mais sofre caricatura. Para alguns, ela é a defesa mais importante da liberdade do usuário. Para outros, é um vírus jurídico que sai contaminando tudo como se o linker fosse uma criatura mitológica. A realidade é menos preguiçosa e mais interessante.&lt;/p&gt;
&lt;p&gt;A GPL é uma licença copyleft forte. Ela permite usar, estudar, modificar e redistribuir o software, mas exige que versões derivadas distribuídas preservem as mesmas liberdades. Se você distribui um programa derivado de código GPL, precisa fornecer o código-fonte correspondente sob os termos da GPL. O objetivo não é impedir uso comercial. A própria definição de software livre rejeita restrição de uso comercial. O objetivo é impedir que alguém transforme o trabalho livre em software não livre na distribuição.&lt;/p&gt;
&lt;p&gt;Escolher GPL faz sentido quando o projeto é uma aplicação final, ferramenta, componente de sistema ou infraestrutura que você quer manter livre nos derivados distribuídos. Compiladores, sistemas, ferramentas de linha de comando, editores, programas de usuário e componentes em que reciprocidade importa podem ser bons candidatos. O exemplo simbólico é o próprio ecossistema GNU. O kernel Linux usa GPLv2, e isso moldou profundamente a relação entre fabricantes, distribuidores e comunidade.&lt;/p&gt;
&lt;p&gt;A GPL pode ser problemática quando você quer que o código seja incorporado livremente por software proprietário. Empresas tendem a evitar dependências GPL em produtos fechados distribuídos porque a obrigação de fornecer código-fonte do derivado pode ser incompatível com o modelo de produto. Isso não faz da GPL uma licença ruim. Faz dela uma licença com uma intenção clara: o código pode viajar, mas não deve perder a liberdade no caminho.&lt;/p&gt;
&lt;p&gt;A diferença entre GPLv2 e GPLv3 também não é detalhe decorativo. A &lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.html&quot;&gt;GPLv3&lt;/a&gt; adiciona respostas a problemas como tivoização e patentes, enquanto a &lt;a href=&quot;https://www.gnu.org/licenses/old-licenses/gpl-2.0.html&quot;&gt;GPLv2&lt;/a&gt; continua relevante por projetos enormes, especialmente o Linux. O sufixo “or later” também importa. Código “GPLv2 only” não é automaticamente compatível com GPLv3. Código “GPLv2 or later” abre outro caminho. Uma palavra no cabeçalho muda o mapa de composição.&lt;/p&gt;
&lt;h2&gt;LGPL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.gnu.org/licenses/lgpl-3.0.html&quot;&gt;LGPL&lt;/a&gt;, ou Lesser General Public License, existe para um problema específico: bibliotecas. Ela é copyleft, mas mais fraca que a GPL. A ideia é permitir que uma biblioteca livre seja usada por programas proprietários sem obrigar que o programa inteiro seja licenciado como GPL, preservando obrigações sobre a própria biblioteca e suas modificações.&lt;/p&gt;
&lt;p&gt;Escolher LGPL faz sentido quando você quer que uma biblioteca seja adotada amplamente, inclusive por software fechado, mas não quer que melhorias na biblioteca sejam simplesmente fechadas sem retorno. É um acordo mais pragmático do que a GPL forte. Ele reconhece que uma biblioteca, por natureza, existe para ser chamada por outros programas. Se cada uso exigisse abertura do programa inteiro, muita gente simplesmente não usaria.&lt;/p&gt;
&lt;p&gt;O lado chato é que a LGPL traz mais detalhes técnicos de conformidade. Link dinâmico, link estático, possibilidade de substituir a biblioteca, distribuição de objetos relinkáveis, modificações na biblioteca e documentação de compliance entram no radar. Não é uma licença ruim; é uma licença que exige entender como o software é distribuído. Para uma biblioteca C usada por meio de link dinâmico, o cenário é um. Para uma aplicação mobile empacotada com tudo estático e loja no meio, a conversa fica menos confortável.&lt;/p&gt;
&lt;p&gt;LGPL é uma boa escolha quando você quer proteger uma biblioteca sem transformar cada consumidor em projeto copyleft. É uma escolha ruim quando você quer simplicidade máxima ou reciprocidade forte no produto final. Ela mora justamente no meio do caminho, e meio do caminho é ótimo quando você sabe por que está nele.&lt;/p&gt;
&lt;h2&gt;AGPL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.gnu.org/licenses/agpl-3.0.html&quot;&gt;AGPL&lt;/a&gt; é a licença que aparece quando alguém olha para SaaS e pergunta: “espera, então você pode modificar um software livre, rodar como serviço, nunca distribuir binário e nunca devolver nada?”. A GPL tradicional é acionada principalmente na distribuição. A AGPL adiciona uma obrigação ligada ao uso pela rede: se você modifica o programa e permite que usuários interajam com ele remotamente, precisa oferecer o código-fonte correspondente aos usuários desse serviço.&lt;/p&gt;
&lt;p&gt;Escolher AGPL faz sentido quando o projeto é servidor, plataforma web, banco de dados, sistema multiusuário, ferramenta de colaboração, serviço de rede ou infraestrutura que você teme ver virar oferta SaaS fechada sem retorno. É uma licença pensada para o mundo em que a distribuição deixou de ser “baixar um binário” e passou a ser “chamar uma API”.&lt;/p&gt;
&lt;p&gt;O custo é adoção empresarial. Muitas empresas têm políticas internas que bloqueiam AGPL por padrão, justamente porque o gatilho de rede pode criar obrigações indesejadas em produtos SaaS. Isso pode reduzir contribuições, integrações e uso comercial. De novo: não é bug. É design. A AGPL existe para tornar desconfortável exatamente o tipo de captura que o SaaS tornou conveniente.&lt;/p&gt;
&lt;p&gt;Se você mantém um serviço que depende de comunidade e quer evitar que um competidor pegue tudo, hospede, feche as melhorias e venda como produto gerenciado, AGPL merece estar na mesa. Se você quer que o software seja usado em qualquer empresa sem conversa com jurídico, AGPL provavelmente vai criar atrito. Às vezes esse atrito é o ponto. Às vezes é tiro no pé.&lt;/p&gt;
&lt;h2&gt;MPL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.mozilla.org/en-US/MPL/2.0/&quot;&gt;Mozilla Public License 2.0&lt;/a&gt; é uma das licenças mais interessantes para quem acha MIT permissiva demais e GPL forte demais. Ela é um copyleft fraco baseado em arquivo. Em termos práticos, modificações em arquivos MPL precisam continuar sob MPL, mas você pode combinar esses arquivos com código sob outras licenças no mesmo projeto, inclusive código proprietário, respeitando os limites da licença.&lt;/p&gt;
&lt;p&gt;Escolher MPL faz sentido quando você quer proteger melhorias no núcleo do projeto sem obrigar que tudo ao redor seja aberto. É uma licença boa para bibliotecas, frameworks, componentes reutilizáveis e projetos que precisam conviver com ecossistemas mistos. Ela permite que o código protegido permaneça aberto, mas não tenta transformar cada integração em um derivado copyleft completo.&lt;/p&gt;
&lt;p&gt;O benefício da MPL é que ela conversa bem com a realidade modular do software moderno. Nem todo projeto é um monolito jurídico. Às vezes você quer proteger arquivos específicos, preservar modificações úteis e ainda permitir que empresas integrem o componente em produtos maiores. A MPL oferece essa granularidade.&lt;/p&gt;
&lt;p&gt;O risco é que granularidade exige entendimento. “Copyleft por arquivo” é mais sutil do que “pode tudo” ou “derivou, abre”. Times que não têm maturidade de compliance podem errar por ignorância. Mesmo assim, para muitos projetos, MPL é um meio-termo subestimado. Ela não tem o marketing simples da MIT nem a força simbólica da GPL, mas resolve um problema real.&lt;/p&gt;
&lt;h2&gt;EPL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.eclipse.org/legal/epl-2.0/&quot;&gt;Eclipse Public License 2.0&lt;/a&gt; aparece bastante no universo Eclipse, Java, ferramentas corporativas e projetos que nasceram em ambientes com forte preocupação de governança. Assim como a MPL, ela costuma ser entendida como copyleft fraco, mas sua estrutura e linguagem seguem a tradição da Eclipse Foundation e tratam contribuição, distribuição e patente de forma própria.&lt;/p&gt;
&lt;p&gt;Escolher EPL faz sentido quando você está em ecossistemas que já adotam essa licença, especialmente projetos ligados à Eclipse Foundation ou ambientes Java corporativos. Licença também é compatibilidade social: usar a licença esperada pelo ecossistema reduz surpresa, facilita contribuição e evita que cada consumidor precise reaprender o contrato.&lt;/p&gt;
&lt;p&gt;O risco da EPL é ser menos familiar para muita gente fora desse mundo. Desenvolvedores reconhecem MIT, Apache e GPL quase por reflexo. EPL exige um pouco mais de leitura. Isso não a torna pior, mas aumenta o atrito psicológico. Em projeto que quer adoção ampla fora do ecossistema Eclipse, talvez Apache 2.0 ou MPL sejam mais reconhecíveis. Em projeto que vive naturalmente naquele ambiente, EPL pode ser a escolha óbvia.&lt;/p&gt;
&lt;h2&gt;CDDL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://opensource.org/license/CDDL-1.0&quot;&gt;CDDL&lt;/a&gt; ficou famosa menos por ser moda e mais por um problema específico: ZFS no Linux. A licença nasceu no universo Sun/OpenSolaris e é aprovada pela OSI, mas sua compatibilidade com a GPL é controversa. O caso ZFS/Linux virou exemplo clássico de como duas licenças livres podem não ser combináveis de forma confortável na distribuição de um mesmo trabalho.&lt;/p&gt;
&lt;p&gt;Escolher CDDL hoje provavelmente só faz sentido em contextos muito específicos, especialmente se você está mantendo ou contribuindo para código que já vive sob essa licença. Ela não é uma escolha comum para projeto novo. Não porque seja “não livre”, mas porque carrega uma história de compatibilidade que pode assustar distribuidores e integradores.&lt;/p&gt;
&lt;p&gt;O caso ZFS é didático porque desmonta a fantasia do “é tudo open source, então pode misturar”. O código está aberto. As licenças são abertas. O software é tecnicamente útil. Ainda assim, distribuir certas combinações pode ser juridicamente arriscado. Compatibilidade de licença não é uma nota de rodapé; é parte da arquitetura do pacote.&lt;/p&gt;
&lt;h2&gt;CC0&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://creativecommons.org/public-domain/cc0/&quot;&gt;CC0&lt;/a&gt; é uma tentativa de dedicação ao domínio público, não exatamente uma licença comum. A própria Creative Commons explica que CC0 funciona como uma renúncia de direitos autorais na medida permitida por lei, acompanhada de uma licença fallback quando a renúncia completa não funciona em determinada jurisdição. Em português menos cerimonial: é a tentativa de dizer “não quero reservar direitos autorais sobre isto”.&lt;/p&gt;
&lt;p&gt;CC0 faz sentido para dados, exemplos mínimos, snippets pequenos, fixtures, documentação auxiliar, materiais de teste, especificações simples, ícones genéricos, listas e conteúdos em que você quer reduzir atrito quase a zero. Em software, ela pode ser usada, e a própria &lt;a href=&quot;https://creativecommons.org/faq/#can-i-apply-a-creative-commons-license-to-software&quot;&gt;FAQ da Creative Commons&lt;/a&gt; menciona que CC0 é aceitável para software e compatível com GPL, embora a organização recomende contra o uso das licenças Creative Commons comuns para software. Essa distinção importa: CC-BY, CC-BY-SA e companhia foram desenhadas principalmente para conteúdo, não para código.&lt;/p&gt;
&lt;p&gt;O problema da CC0 é que “domínio público” não funciona igual em todos os países. Em algumas jurisdições, direitos morais podem não ser renunciáveis da mesma forma que direitos patrimoniais. Isso não significa que CC0 é inútil. Significa que ela tenta aproximar o projeto do domínio público, mas não transforma magicamente todos os sistemas jurídicos do planeta em uma única interpretação conveniente para o seu README.&lt;/p&gt;
&lt;p&gt;Escolher CC0 é coerente quando você realmente não quer atribuição obrigatória, reciprocidade, preservação de aviso ou controle sobre derivados. É uma escolha radicalmente permissiva. Justamente por isso, ela é problemática quando você ainda quer algum reconhecimento mínimo, garantia de preservação de aviso, controle de marca ou proteção contra uso que pareça endosso. Se você quer “faça qualquer coisa, inclusive fingir que nunca existi”, CC0 conversa com essa intenção. Se isso te incomoda, não escolha CC0 esperando gratidão espontânea da indústria. Gratidão não é mecanismo de compliance.&lt;/p&gt;
&lt;h2&gt;Unlicense&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://unlicense.org/&quot;&gt;Unlicense&lt;/a&gt; tem uma intenção parecida com CC0: colocar o código no domínio público ou o mais próximo possível disso. Ela é curta, popular em alguns círculos e aparece em projetos de gente que quer explicitamente abrir mão de restrições. A diferença é que CC0 foi produzida por uma organização especializada em ferramentas jurídicas globais para o comum, enquanto a Unlicense é uma formulação mais direta, com menos aparato institucional ao redor.&lt;/p&gt;
&lt;p&gt;Escolher Unlicense pode fazer sentido para projetos muito pequenos, experimentos, snippets e código que você realmente não se importa que seja usado sem atribuição ou retorno. Mas, para projetos maiores, eu teria cautela. Não porque Unlicense seja automaticamente inválida, e sim porque ela tenta resolver de forma muito simples um problema que varia bastante entre jurisdições. Quando a intenção é “quero o mínimo de atrito possível”, MIT às vezes entrega quase a mesma experiência prática com mais familiaridade para empresas, distribuições e scanners.&lt;/p&gt;
&lt;p&gt;Unlicense é o tipo de licença que parece libertária e limpa no README, mas pode gerar mais perguntas do que MIT em uma auditoria corporativa. Se o público do seu projeto é composto por desenvolvedores individuais, talvez ninguém ligue. Se o público inclui empresas grandes, distribuições Linux e departamentos de compliance, familiaridade importa. Chato, mas real.&lt;/p&gt;
&lt;h2&gt;Licenças Creative Commons que não são CC0&lt;/h2&gt;
&lt;p&gt;Creative Commons é excelente para textos, imagens, vídeos, músicas, materiais educacionais e documentação. Para software, a própria Creative Commons &lt;a href=&quot;https://creativecommons.org/faq/#can-i-apply-a-creative-commons-license-to-software&quot;&gt;recomenda contra usar licenças CC comuns em código&lt;/a&gt;, porque elas não tratam de forma adequada temas típicos de software, como distribuição de código-fonte, compatibilidade com licenças de software e patentes.&lt;/p&gt;
&lt;p&gt;Isso não significa que CC-BY ou CC-BY-SA sejam ruins. Significa que são ferramentas para outro material. Um projeto pode perfeitamente usar MIT no código, CC-BY-SA na documentação, CC0 em dados de teste e uma política separada para marca. Na verdade, essa separação costuma ser mais madura do que tentar enfiar tudo em uma licença só como se código, logo, manual, dataset e screenshot fossem o mesmo tipo de obra.&lt;/p&gt;
&lt;p&gt;O ponto é não usar Creative Commons comum em software por preguiça. Se você escreveu código, use licença de software. Se escreveu documentação, aí Creative Commons pode fazer sentido. Se quer abrir mão de direitos de forma radical, CC0 entra na conversa. Cada coisa no seu lugar. Uma revolução conceitual para quem já tentou licenciar logo, manual e backend no mesmo commit.&lt;/p&gt;
&lt;h2&gt;Sem licença&lt;/h2&gt;
&lt;p&gt;Sem licença não significa “liberado geral”. Significa quase o oposto. A página &lt;a href=&quot;https://choosealicense.com/no-permission/&quot;&gt;No License&lt;/a&gt; do Choose a License resume bem: por padrão, uma obra criativa, incluindo código, nasce sob copyright exclusivo. Publicar no GitHub permite certas ações dentro dos termos da plataforma, como visualizar e fazer fork na própria plataforma, mas não dá automaticamente permissão ampla para usar, modificar, distribuir ou incorporar em produto.&lt;/p&gt;
&lt;p&gt;Escolher “sem licença” só faz sentido quando você quer que o código seja público para leitura, mas não quer conceder permissões abertas. Isso pode ser válido para portfólio, demonstração, material de estudo ou código que você ainda não decidiu como licenciar. Mas precisa ser intencional. Se você quer colaboração, adoção ou reuso, não colocar licença é basicamente colocar uma placa invisível dizendo “pergunte ao advogado antes”.&lt;/p&gt;
&lt;p&gt;Para quem consome código, a regra prática é desagradável: repositório público sem licença deve ser tratado como código sem permissão de uso. Pode parecer paranoia, mas é só copyright funcionando. “Estava no GitHub” é uma defesa ruim. E provavelmente também é uma péssima frase para dizer em reunião com jurídico.&lt;/p&gt;
&lt;h2&gt;BSL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://mariadb.com/bsl11/&quot;&gt;Business Source License&lt;/a&gt; é uma licença source-available com atraso programado para abertura. Em geral, o código fica disponível sob restrições por um período, e depois muda para uma licença open source definida. A ideia é permitir transparência e acesso ao código enquanto protege um modelo comercial por alguns anos.&lt;/p&gt;
&lt;p&gt;Escolher BSL pode fazer sentido para empresa que quer desenvolver em público, ganhar confiança técnica, permitir uso limitado, mas impedir concorrência direta durante um período. Foi o caminho adotado pela HashiCorp quando mudou Terraform e outros produtos de MPL 2.0 para BSL, justificando a decisão no comunicado &lt;a href=&quot;https://www.hashicorp.com/en/blog/hashicorp-adopts-business-source-license&quot;&gt;“HashiCorp adopts Business Source License”&lt;/a&gt;. A reação foi o &lt;a href=&quot;https://opentofu.org/blog/opentofu-announces-fork-of-terraform/&quot;&gt;OpenTofu&lt;/a&gt;, justamente porque uma mudança de licença em infraestrutura crítica altera confiança, governança e futuro.&lt;/p&gt;
&lt;p&gt;O ponto delicado é que BSL não deve ser vendida como open source no período em que restringe usos. Ela pode ser uma estratégia comercial legítima. Pode até ser razoável em alguns produtos. Mas é outra coisa. Chamar de open source porque o código está visível é maquiagem. Código visível não é liberdade de uso.&lt;/p&gt;
&lt;h2&gt;SSPL&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.mongodb.com/legal/licensing/server-side-public-license&quot;&gt;Server Side Public License&lt;/a&gt; nasceu no contexto do MongoDB e mira explicitamente o problema de oferecer software como serviço. Sua lógica amplia obrigações para quem disponibiliza o programa como serviço a terceiros, exigindo abertura de componentes necessários para oferecer esse serviço. A OSI não aprovou a SSPL como licença open source, justamente porque ela impõe restrições que entram em conflito com a definição tradicional de open source.&lt;/p&gt;
&lt;p&gt;Escolher SSPL faz sentido se a prioridade é proteger uma empresa ou projeto contra provedores de SaaS que empacotam o software como serviço concorrente. Mas faz pouco sentido se o objetivo é participar do ecossistema open source clássico com distribuição ampla, empacotamento tranquilo e adoção sem susto. SSPL é um recado para cloud vendors. E recados para cloud vendors normalmente assustam também empresas menores, distribuições e comunidades.&lt;/p&gt;
&lt;p&gt;Os casos MongoDB, Elastic e Redis mostram que esse terreno é inflamável. Elastic trocou Apache 2.0 por SSPL/Elastic License em 2021 e depois anunciou AGPL como opção em 2024 no texto &lt;a href=&quot;https://www.elastic.co/blog/elasticsearch-is-open-source-again&quot;&gt;“Elasticsearch Is Open Source. Again!”&lt;/a&gt;. Redis mudou de BSD 3-Clause para RSALv2/SSPLv1 em 2024 no comunicado &lt;a href=&quot;https://redis.io/blog/redis-adopts-dual-source-available-licensing/&quot;&gt;“Redis Adopts Dual Source-Available Licensing”&lt;/a&gt;, o que ajudou a impulsionar o fork &lt;a href=&quot;https://www.linuxfoundation.org/press/linux-foundation-launches-open-source-valkey-community&quot;&gt;Valkey&lt;/a&gt;. Essas mudanças não são só ajustes jurídicos. São terremotos de governança.&lt;/p&gt;
&lt;h2&gt;Licenças próprias e source-available&lt;/h2&gt;
&lt;p&gt;Licenças próprias com restrições de uso aparecem cada vez mais em bancos de dados, ferramentas de infraestrutura, plataformas de IA, produtos de observabilidade e serviços que vivem sob ameaça de captura por nuvem. Algumas dizem “pode usar, menos para competir comigo”. Outras dizem “pode usar, menos como serviço gerenciado”. Outras permitem uso gratuito até certo faturamento, número de usuários ou contexto.&lt;/p&gt;
&lt;p&gt;Essas licenças podem ser razoáveis como estratégia de produto, mas quase nunca são boas para colaboração aberta no sentido clássico. Elas criam incerteza. Distribuições Linux podem evitar. Empresas podem bloquear. Contribuidores podem desconfiar. Forks podem surgir. E o termo “open source” começa a virar embalagem de marketing.&lt;/p&gt;
&lt;p&gt;Se a sua intenção é criar um produto comercial com código visível, talvez source-available seja honesto. Só não chame de software livre. Não chame de open source. Não venda restrição como liberdade porque isso só degrada o vocabulário e faz todo mundo perder tempo discutindo semântica enquanto o problema real é poder.&lt;/p&gt;
&lt;h2&gt;Compatibilidade é onde o README encontra o advogado&lt;/h2&gt;
&lt;p&gt;Licenças não vivem isoladas. Software moderno é uma lasanha de dependências, transpiladores, bibliotecas, plugins, imagens de container, snippets copiados, código gerado, pacotes vendorizados, binários empacotados e coisas que alguém instalou “só para testar” e que misteriosamente foram parar em produção.&lt;/p&gt;
&lt;p&gt;Compatibilidade de licença é a pergunta menos divertida e mais importante: posso combinar esses códigos e distribuir o resultado legalmente?&lt;/p&gt;
&lt;p&gt;Nem toda licença livre é compatível com toda licença livre. A própria FSF mantém documentação sobre &lt;a href=&quot;https://www.gnu.org/licenses/license-compatibility.html&quot;&gt;compatibilidade e relicenciamento&lt;/a&gt;, e um exemplo clássico é que GPLv2 e GPLv3 não são automaticamente compatíveis se o código estiver marcado apenas como “GPLv2 only”. Já “GPLv2 or later” abre caminho para usar uma versão posterior. Parece detalhe burocrático. Não é. Uma palavra muda o grafo de composição do projeto.&lt;/p&gt;
&lt;p&gt;A incompatibilidade entre CDDL e GPL no caso ZFS/Linux é um dos exemplos mais conhecidos. O ZFS foi liberado pela Sun sob CDDL, enquanto o kernel Linux usa GPLv2. A &lt;a href=&quot;https://sfconservancy.org/blog/2016/feb/25/zfs-and-linux/&quot;&gt;Software Freedom Conservancy&lt;/a&gt; argumenta que distribuir binários combinando ZFS e Linux viola as licenças envolvidas. É por isso que ZFS no Linux vive nesse limbo estranho: tecnicamente útil, desejado por muita gente, mas juridicamente desconfortável para distribuição junto ao kernel.&lt;/p&gt;
&lt;p&gt;A parte irritante é que, do ponto de vista do usuário, tudo parece “open source”. O código está lá. As licenças são abertas. O projeto compila. Só que o direito autoral não se importa com sua vontade de montar um NAS bonito no fim de semana.&lt;/p&gt;
&lt;h2&gt;SPDX, SBOM e a tentativa de não enlouquecer&lt;/h2&gt;
&lt;p&gt;Em projetos pequenos, licença parece fácil. Você escolhe MIT, Apache, GPL, MPL, coloca um arquivo no repositório e segue a vida. Em projetos reais, a coisa vira inventário.&lt;/p&gt;
&lt;p&gt;Uma aplicação moderna pode puxar centenas ou milhares de dependências. Cada uma tem licença própria. Algumas têm múltiplas licenças. Algumas usam exceções. Algumas vendorizam código. Algumas trazem arquivos gerados. Algumas mudam de licença entre versões. Algumas não declaram nada direito. Algumas dependências transitivas só aparecem quando você resolve o lockfile, faz build, empacota uma imagem ou gera um binário estático.&lt;/p&gt;
&lt;p&gt;É por isso que identificadores padronizados importam. A &lt;a href=&quot;https://spdx.org/licenses/&quot;&gt;SPDX License List&lt;/a&gt; fornece identificadores curtos, nomes oficiais, textos de licença e URLs canônicas. Em vez de escrever “GPL 3”, “GPLv3”, “GNU GPL versão três ou posterior talvez”, você usa algo como &lt;code&gt;GPL-3.0-or-later&lt;/code&gt;. Em vez de “Apache”, usa &lt;code&gt;Apache-2.0&lt;/code&gt;. Parece detalhe de metadado, mas é o tipo de detalhe que permite ferramentas de auditoria funcionarem sem depender de adivinhação mística.&lt;/p&gt;
&lt;p&gt;SBOM, scanners de licença, política de dependência e revisão de pacote não são glamour. São encanamento. E, como todo encanamento, só viram assunto quando estoura água no teto.&lt;/p&gt;
&lt;h2&gt;Microsoft, Rust Coreutils e o detalhe que não é detalhe&lt;/h2&gt;
&lt;p&gt;O caso Microsoft/Coreutils é interessante justamente porque ele obriga a separar fato, inferência e torcida.&lt;/p&gt;
&lt;p&gt;O fato documentado é que o projeto &lt;a href=&quot;https://github.com/microsoft/coreutils&quot;&gt;Coreutils for Windows&lt;/a&gt; da Microsoft é uma build mantida pela Microsoft de &lt;code&gt;uutils/coreutils&lt;/code&gt;, &lt;code&gt;findutils&lt;/code&gt; e &lt;code&gt;grep&lt;/code&gt;, empacotada para Windows. O repositório diz que o objetivo é tornar comandos, flags e pipelines mais consistentes entre Linux, macOS, WSL, containers e Windows. O projeto &lt;a href=&quot;https://github.com/uutils/coreutils&quot;&gt;uutils/coreutils&lt;/a&gt; é uma reimplementação em Rust das GNU Coreutils, com objetivo de ser um substituto compatível e cross-platform. O próprio repositório da Microsoft aparece com licença MIT. O projeto uutils também está sob MIT. Já as &lt;a href=&quot;https://www.gnu.org/software/coreutils/&quot;&gt;GNU Core Utilities&lt;/a&gt; são parte do ecossistema GNU e usam GPL.&lt;/p&gt;
&lt;p&gt;O que não dá para afirmar, sem fonte primária explícita, é que “a Microsoft escolheu uutils só por causa da licença”. Isso seria chute com roupa de análise. Pode ter sido licença. Pode ter sido portabilidade. Pode ter sido Rust. Pode ter sido integração com Windows. Pode ter sido arquitetura de build. Pode ter sido manutenção. Pode ter sido a soma disso tudo, que é o mais provável.&lt;/p&gt;
&lt;p&gt;Mas a licença certamente muda o espaço de decisão. Usar uma base MIT dá à Microsoft muito mais flexibilidade para empacotar, integrar, redistribuir e modificar dentro de um produto comercial sem acionar as obrigações de copyleft da GPL. Para uma empresa que distribui software proprietário em escala planetária, isso não é detalhe. É custo de produto, risco jurídico, governança de supply chain e liberdade de implementação.&lt;/p&gt;
&lt;p&gt;A parte engraçada é que o usuário final provavelmente só quer que &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt; e companhia funcionem no Windows sem precisar montar uma torre de Babel entre PowerShell, WSL, Git Bash, MSYS2 e trauma. Mas a decisão de qual implementação usar carrega uma camada profunda: a Microsoft não está apenas escolhendo uma linguagem ou um port. Está escolhendo um contrato social mais conveniente para o produto dela.&lt;/p&gt;
&lt;p&gt;E isso não torna uutils “errado”. MIT permite isso. Esse é o ponto.&lt;/p&gt;
&lt;h2&gt;O dev e a fantasia do “está público, então posso usar”&lt;/h2&gt;
&lt;p&gt;Para desenvolvedor, a regra mais prática é simples e desagradável: se não tem licença, você provavelmente não tem permissão.&lt;/p&gt;
&lt;p&gt;Isso vale para dependência sem licença, gist aleatório, snippet de issue, resposta de fórum, código colado de blog, projeto abandonado e aquele pacote npm com três downloads semanais que resolve exatamente seu problema de validação de CPF com suporte a runas astrais. Se você está usando no seu computador para brincar, o risco prático é um. Se você está distribuindo binário, imagem Docker, aplicativo mobile, firmware, SDK ou SaaS para cliente, o risco muda de categoria.&lt;/p&gt;
&lt;p&gt;Uso interno e distribuição também não são a mesma coisa. Em muitas licenças copyleft, a obrigação forte aparece quando há distribuição. Se você modifica um programa GPL e usa internamente, sem distribuir, normalmente não precisa publicar suas mudanças. A AGPL muda parte desse cenário ao tratar interação via rede como gatilho para disponibilização do código modificado. Isso é justamente o motivo de ela incomodar empresas SaaS e interessar comunidades que querem evitar que o software vire serviço fechado com maquiagem aberta.&lt;/p&gt;
&lt;p&gt;Também não dá para resumir tudo em “linkou, contaminou”. A discussão entre link estático, link dinâmico, chamada de processo externo, plugin, API, extensão, header, IPC e serviço remoto depende da licença, do caso concreto e da jurisdição. Às vezes a resposta técnica parece óbvia e a jurídica não é. É aqui que “chamar advogado” deixa de ser piada e vira higiene básica de engenharia.&lt;/p&gt;
&lt;p&gt;Não porque todo dev precise virar jurista. Mas porque copiar código sem entender licença é o equivalente jurídico de instalar pacote do AUR sem ler PKGBUILD: funciona até parar de funcionar.&lt;/p&gt;
&lt;h2&gt;Licença como arquitetura de produto&lt;/h2&gt;
&lt;p&gt;A licença afeta adoção porque define atrito. Afeta contribuição porque define retorno. Afeta forks porque define quem pode continuar o projeto se a governança azedar. Afeta empacotamento porque distribuições como Debian filtram software com base em critérios de liberdade e redistribuição, formalizados nas &lt;a href=&quot;https://www.debian.org/social_contract#guidelines&quot;&gt;Debian Free Software Guidelines&lt;/a&gt;. Afeta SaaS porque a rede virou forma dominante de entrega. Afeta bibliotecas porque ninguém quer descobrir tarde demais que uma dependência obriga abrir um produto inteiro. Afeta ferramentas CLI porque elas podem ser distribuídas dentro de sistemas proprietários. Afeta bancos de dados porque provedores de nuvem adoram transformar infraestrutura aberta em serviço gerenciado. Afeta drivers porque integração com kernel e firmware é uma festa de compatibilidade. Afeta frameworks porque adoção depende de confiança de longo prazo.&lt;/p&gt;
&lt;p&gt;A licença também afeta a psicologia da comunidade. Um projeto permissivo pode atrair empresas, mas também pode gerar a sensação de que contribuidores voluntários estão subsidiando produto fechado. Um projeto copyleft pode proteger o comum, mas também pode afastar integradores que poderiam financiar desenvolvimento. Um projeto source-available pode proteger receita da empresa, mas quebrar confiança de quem entrou acreditando em open source. Um projeto dual-license pode sustentar um negócio, mas levantar suspeita sobre CLA, relicenciamento e controle centralizado.&lt;/p&gt;
&lt;p&gt;Não existe licença perfeita porque não existe objetivo único.&lt;/p&gt;
&lt;h2&gt;Como escolher sem fingir neutralidade&lt;/h2&gt;
&lt;p&gt;Se o projeto é um pacote pequeno e você quer que ele seja usado em qualquer lugar, MIT ou BSD provavelmente resolvem. Se você quer permissividade com uma proteção mais explícita de patentes, Apache 2.0 é uma escolha melhor, especialmente em projetos que podem atrair empresas. Se o projeto é uma biblioteca e você quer que ela seja usada por software proprietário, mas quer preservar melhorias na própria biblioteca, LGPL ou MPL podem ser mais coerentes do que GPL forte.&lt;/p&gt;
&lt;p&gt;Se o projeto é uma aplicação final e você quer garantir que derivados distribuídos continuem livres, GPL é uma escolha consciente. Se o projeto é um servidor e sua preocupação é captura por SaaS, AGPL é a ferramenta mais direta dentro do campo do software livre. Se o projeto é documentação, material didático, imagem, áudio ou texto, Creative Commons pode ser ótima; se é código, prefira licença de software. Se é um snippet mínimo, dataset, fixtures ou material que você quer colocar o mais perto possível do domínio público, CC0 pode fazer sentido. Se você quer que empresas adotem sem susto, Unlicense pode ser menos confortável do que MIT apesar da intenção parecida.&lt;/p&gt;
&lt;p&gt;Se o projeto é produto comercial com código visível, talvez você esteja no território de source-available, open core ou dual licensing. Isso não é automaticamente pecado, mas precisa ser dito com honestidade. O usuário merece saber se está entrando em um commons, em uma vitrine técnica, em um produto aberto só até onde não compete com o fornecedor ou em uma comunidade que pode perder o chão no próximo comunicado de mudança de licença.&lt;/p&gt;
&lt;p&gt;O ponto central é não escolher licença pelo template do GitHub. Escolha pelo comportamento que você quer permitir e pelo comportamento que você quer impedir. Licença é um desenho de incentivos. Ela não garante que as pessoas serão justas, mas define o que elas podem fazer quando não forem.&lt;/p&gt;
&lt;h2&gt;A parte econômica que ninguém gosta de admitir&lt;/h2&gt;
&lt;p&gt;Open source tem um problema estrutural: todo mundo quer usar, pouca gente quer pagar, e quase ninguém quer manter o pacote que quebra no Natal.&lt;/p&gt;
&lt;p&gt;Empresas financiam muito software livre e open source. Isso precisa ser dito porque a narrativa “empresa só explora comunidade” é falsa. Kernel Linux, Kubernetes, LLVM, PostgreSQL, OpenJDK, systemd, Rust, Python, OpenSSL, curl e uma quantidade obscena de infraestrutura crítica recebem contribuição, salário, hospedagem, patrocínio, tempo de engenharia e governança de empresas. Sem isso, muito do que usamos quebraria mais, andaria mais devagar ou dependeria de meia dúzia de mantenedores exaustos sendo pagos em estrela no GitHub e cobrança mal-educada em issue.&lt;/p&gt;
&lt;p&gt;Ao mesmo tempo, também é verdade que empresas capturam valor de comunidades sem devolver proporcionalmente. Pegar biblioteca mantida por voluntário, colocar em produto bilionário e tratar o mantenedor como helpdesk gratuito não é colaboração. É extração.&lt;/p&gt;
&lt;p&gt;Licença tenta responder a isso, mas não resolve tudo. Permissiva maximiza uso, mas não garante retorno. Copyleft garante reciprocidade em certos cenários, mas não garante dinheiro, manutenção ou governança saudável. Source-available protege empresa, mas pode reduzir confiança e distribuição. Fundação neutra ajuda governança, mas não paga automaticamente o trabalho invisível. CLA pode facilitar relicenciamento e dual licensing, mas também concentrar poder no patrocinador. DCO é mais leve, mas não resolve toda estratégia jurídica.&lt;/p&gt;
&lt;p&gt;No fim, licença é uma ferramenta. Governança, financiamento, cultura de contribuição, marca, trademark, roadmap e comunidade são o resto da máquina.&lt;/p&gt;
&lt;h2&gt;Conclusão: licença é o desenho do poder&lt;/h2&gt;
&lt;p&gt;Licença de software não decide apenas como o código pode ser copiado. Ela decide como o poder circula ao redor do código.&lt;/p&gt;
&lt;p&gt;A GPL não é só uma licença “restritiva”; é uma tentativa de impedir que liberdade vire insumo descartável. MIT e BSD não são licenças “sem consequência”; elas são uma escolha consciente por permissividade, inclusive quando isso permite apropriação proprietária. Apache 2.0 não é só MIT com gravata; sua cláusula de patentes muda a conversa em ambientes corporativos. LGPL e MPL não são indecisão; são respostas para o problema real de bibliotecas e composição. AGPL não é paranoia anti-SaaS; é uma resposta ao fato de que a web mudou o que significa distribuir software. CC0 não é “MIT sem texto”; é uma tentativa de dedicação ao domínio público, com suas próprias sutilezas. Source-available não é open source com nome moderno; é outra categoria, com outras promessas e outras restrições.&lt;/p&gt;
&lt;p&gt;A pior escolha é fingir que não há escolha.&lt;/p&gt;
&lt;p&gt;Licença não é burocracia. É arquitetura social. É o contrato que define se o código será bem comum, insumo comercial, ferramenta comunitária, produto de empresa, plataforma de colaboração, base de captura ou alguma mistura instável de tudo isso.&lt;/p&gt;
&lt;p&gt;E talvez essa seja a parte mais importante: nenhuma licença salva um projeto sozinha. Mas uma licença mal escolhida consegue estragar muita coisa antes do primeiro grande bug de produção.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Linux: O trade-off do kernel hardening</title><link>https://blog.kristyan.dev/posts/linux-o-trade-off-do-kernel-hardening</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/linux-o-trade-off-do-kernel-hardening</guid><description>Uma quase-nota-pessoal (e potencial pior post deste site) sobre kernel hardening no Linux, variantes de kernel e o custo real de trocar segurança abstrata por compatibilidade, desempenho e manutenção.</description><pubDate>Sun, 21 Jun 2026 23:50:00 GMT</pubDate><content:encoded>&lt;p&gt;Tem uma fase inevitável na vida de quem usa Linux: em algum momento você descobre que existe um kernel “hardened”, lê meia dúzia de README falando sobre mitigação, superfície de ataque, lockdown, memória protegida e pronto. O kernel padrão começa a parecer irresponsável. Quase vulgar. Coisa de quem não se importa com segurança.&lt;/p&gt;
&lt;p&gt;Só que segurança em Linux tem uma característica irritante: ela raramente melhora só porque você instalou algo com um nome mais sério.&lt;/p&gt;
&lt;p&gt;Kernel hardening é um assunto real. Importante. Técnico. Em alguns cenários, necessário. Mas também é um daqueles temas que viram rapidamente uma espécie de “rice de segurança”: bonito no &lt;code&gt;uname -a&lt;/code&gt;, triste no dia a dia quando o driver da NVIDIA para de carregar, o VirtualBox quebra, o BPF some, o debug fica esquisito e a pessoa descobre que “proteger o kernel” também pode custar a própria paciência.&lt;/p&gt;
&lt;p&gt;A pergunta boa não é “kernel hardened é mais seguro?”. A pergunta boa é: mais seguro contra o quê, em qual máquina, com qual ameaça, pagando qual custo?&lt;/p&gt;
&lt;p&gt;Eu uso kernel customizado no meu desktop. No meu caso, uso o &lt;code&gt;linux-zen&lt;/code&gt;. E isso já é um bom ponto de partida para separar as coisas: o Zen não é um kernel de hardening. Ele existe muito mais no mundo de responsividade, desktop, baixa latência percebida e experiência interativa do que no mundo de defesa agressiva. Ou seja: kernel customizado não significa automaticamente “kernel mais seguro”. Às vezes significa só “quero meu desktop mais esperto”. E tudo bem. O problema começa quando a gente confunde ajuste de performance, filosofia de empacotamento, liberdade de software, tempo real e hardening como se tudo fosse a mesma categoria.&lt;/p&gt;
&lt;p&gt;Não é.&lt;/p&gt;
&lt;h2&gt;Hardening é reduzir dano, não eliminar bug&lt;/h2&gt;
&lt;p&gt;Hardening, em sistemas operacionais, é o conjunto de práticas e mecanismos usados para reduzir superfície de ataque, dificultar exploração e limitar impacto quando alguma coisa dá errado. Isso pode envolver remover serviços desnecessários, restringir permissões, ativar políticas de acesso, compilar software com proteções extras ou configurar o kernel para vazar menos informação e aceitar menos comportamento perigoso por padrão.&lt;/p&gt;
&lt;p&gt;No kernel Linux, hardening normalmente significa uma mistura de quatro coisas: proteções em tempo de compilação, parâmetros de boot, configurações em runtime via &lt;code&gt;sysctl&lt;/code&gt; e políticas de segurança aplicadas por LSMs como SELinux, AppArmor, Yama e Landlock.&lt;/p&gt;
&lt;p&gt;A parte importante é entender o que hardening não é. Hardening não corrige magicamente uma vulnerabilidade. Ele pode impedir que uma vulnerabilidade vire execução de código. Pode transformar uma exploração silenciosa em crash. Pode esconder endereços internos do kernel. Pode bloquear carregamento de módulo malicioso. Pode limitar quais syscalls um processo consegue usar. Mas o bug continua sendo bug.&lt;/p&gt;
&lt;p&gt;Essa diferença parece detalhe acadêmico, mas não é. Uma vulnerabilidade é a falha. Um exploit é o uso prático dessa falha. Uma mitigação é uma barreira para atrapalhar o exploit. Redução de superfície de ataque é evitar que o caminho vulnerável esteja exposto em primeiro lugar.&lt;/p&gt;
&lt;p&gt;Atualização de segurança corrige causa. Hardening reduz chance de desastre quando a causa ainda existe, ainda não foi corrigida, ainda não foi descoberta ou ainda está em algum driver esquecido que você carrega porque precisa que a placa de captura funcione.&lt;/p&gt;
&lt;h2&gt;Por que bug no kernel é pior&lt;/h2&gt;
&lt;p&gt;O kernel roda no espaço privilegiado do sistema. O user space é onde ficam seus processos comuns: navegador, terminal, editor, servidor web, banco de dados, container runtime. O kernel space é onde mora a parte que arbitra memória, processos, syscalls, drivers, rede, filesystems e acesso ao hardware.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/kernel-hardening-linux-nao-e-magia/user-space-kernel-space.svg&quot; alt=&quot;Fronteira entre processos em user space, chamadas de sistema e o kernel Linux privilegiado&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;O problema não é a chamada de sistema existir. O problema é quando uma falha nesse caminho deixa um processo comum atravessar a fronteira de privilégio.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Quando um processo comum falha, o estrago pode ser limitado ao usuário, ao serviço ou ao container. Quando o kernel falha do jeito errado, a conversa muda. Um bug explorável no kernel pode permitir escalonamento de privilégio, fuga de container, bypass de isolamento, leitura de memória sensível ou execução de código em ring 0.&lt;/p&gt;
&lt;p&gt;Esse é o motivo pelo qual kernel hardening existe. Não é paranoia inventada por gente que compila Gentoo no porão. O kernel é a última fronteira entre um processo comprometido e o sistema inteiro. Se o atacante já está rodando código no user space, uma falha no kernel pode ser o caminho para virar dono da máquina.&lt;/p&gt;
&lt;p&gt;Ao mesmo tempo, esse também é o motivo pelo qual hardening precisa ser tratado com cuidado. O kernel é uma peça central demais para ser trocada por superstição. Se você faz hardening sem entender, pode quebrar exatamente as partes que tornam o sistema administrável: observabilidade, debug, virtualização, módulos externos, hibernação, ferramentas de tracing e integração com hardware.&lt;/p&gt;
&lt;p&gt;Segurança que ninguém consegue operar vira enfeite. Ou pior: vira motivo para desativar tudo depois, no susto, geralmente do jeito mais errado possível.&lt;/p&gt;
&lt;h2&gt;O Linux não começou “hardened”&lt;/h2&gt;
&lt;p&gt;O Linux nasceu como kernel generalista. O objetivo sempre foi rodar em muita coisa, suportar muito hardware, aceitar muitos casos de uso e manter um ecossistema enorme de drivers e arquiteturas. Segurança sempre importou, mas o kernel não começou com o mesmo conjunto de mitigations que hoje a gente considera normal.&lt;/p&gt;
&lt;p&gt;Muita coisa que hoje parece óbvia foi amadurecendo ao longo de décadas. Projetos como &lt;a href=&quot;https://pax.grsecurity.net/&quot;&gt;PaX&lt;/a&gt; e &lt;a href=&quot;https://grsecurity.net/&quot;&gt;grsecurity&lt;/a&gt; tiveram papel enorme em popularizar proteções de memória, randomização, restrições mais agressivas e uma visão mais defensiva do kernel. O grsecurity se define como uma extensão de segurança ao kernel Linux voltada a controle de acesso, prevenção de exploração baseada em corrupção de memória e hardening do sistema. O ponto histórico é: muitas ideias que hoje aparecem no debate mainstream de hardening foram testadas, defendidas ou pressionadas por esse ecossistema antes de chegarem ao kernel principal, quando chegaram.&lt;/p&gt;
&lt;p&gt;Depois veio o &lt;a href=&quot;https://kspp.github.io/&quot;&gt;Kernel Self Protection Project&lt;/a&gt;, que tenta levar proteções de autoproteção para o kernel upstream de forma incremental. Essa palavra, incremental, é importante. Kernel upstream não costuma aceitar um caminhão de patch agressivo só porque ele promete segurança. Precisa fazer sentido para manutenção, arquitetura, performance, compatibilidade e revisão por mantenedores. A segurança precisa sobreviver ao mundo real do Linux, que inclui desde servidor exposto na internet até notebook com GPU híbrida e usuário tentando rodar Steam, Docker e uma VPN duvidosa ao mesmo tempo (autodescrição).&lt;/p&gt;
&lt;p&gt;LSMs também mudaram o jogo. &lt;a href=&quot;https://www.redhat.com/en/topics/linux/what-is-selinux&quot;&gt;SELinux&lt;/a&gt;, &lt;a href=&quot;https://apparmor.net/&quot;&gt;AppArmor&lt;/a&gt;, &lt;a href=&quot;https://docs.kernel.org/admin-guide/LSM/Yama.html&quot;&gt;Yama&lt;/a&gt; e &lt;a href=&quot;https://docs.kernel.org/security/landlock.html&quot;&gt;Landlock&lt;/a&gt; existem para permitir políticas de segurança além do modelo clássico de permissões Unix. Em vez de depender só de dono, grupo e modo do arquivo, você consegue impor regras mais específicas sobre o que um processo pode acessar, executar ou inspecionar.&lt;/p&gt;
&lt;p&gt;E então vieram Spectre e Meltdown.&lt;/p&gt;
&lt;p&gt;As vulnerabilidades de execução especulativa mudaram a conversa porque mostraram que a fronteira entre hardware, kernel e processo não era tão limpa quanto parecia. A mitigação contra Meltdown trouxe o &lt;a href=&quot;https://fedoramagazine.org/kpti-new-kernel-feature-mitigate-meltdown/&quot;&gt;Kernel Page Table Isolation&lt;/a&gt;, que separa tabelas de página do kernel e do user space para dificultar leitura indevida de memória privilegiada. Isso teve custo. Em alguns workloads, custo relevante. E serviu como lembrete: mitigação de segurança não é grátis só porque veio em update.&lt;/p&gt;
&lt;h2&gt;As proteções modernas são camadas, não uma muralha&lt;/h2&gt;
&lt;p&gt;Quando alguém fala “kernel hardened”, normalmente imagina uma entidade única, como se existisse um botão chamado &lt;code&gt;security=true&lt;/code&gt;. Na prática, hardening é uma colcha de retalhos de mecanismos diferentes, cada um atacando uma classe de problema.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://documentation.ubuntu.com/security/security-features/kernel-protections/#kernel-address-space-layout-randomization&quot;&gt;KASLR&lt;/a&gt; randomiza o endereço base do kernel na memória a cada boot. Isso dificulta exploits que dependem de endereços previsíveis. Não torna exploração impossível, especialmente se houver vazamento de ponteiros, mas aumenta o trabalho do atacante.&lt;/p&gt;
&lt;p&gt;O stack protector adiciona canários de pilha para detectar corrupção antes de uma função retornar. Se alguém tenta sobrescrever o endereço de retorno por meio de overflow, a alteração pode ser detectada e o kernel pode abortar em vez de continuar em um estado comprometido. O &lt;a href=&quot;https://kspp.github.io/Recommended_Settings.html&quot;&gt;KSPP recomenda&lt;/a&gt; configurações como &lt;code&gt;CONFIG_STACKPROTECTOR_STRONG&lt;/code&gt; justamente para ampliar essa cobertura.&lt;/p&gt;
&lt;p&gt;SMEP e SMAP são recursos de CPU que impedem o kernel de executar ou acessar memória de user space de formas indevidas. Eles ajudam a bloquear técnicas clássicas em que o atacante tenta fazer o kernel pular para código controlado pelo usuário ou ler dados de uma região que não deveria ser confiável.&lt;/p&gt;
&lt;p&gt;O KPTI, já citado, isola tabelas de página para mitigar Meltdown. É uma proteção importante, mas também é um bom exemplo de custo contextual: sistemas com muitas syscalls, muito I/O ou hardware antigo podem sentir mais.&lt;/p&gt;
&lt;p&gt;Hardened usercopy &quot;protege&quot; as cópias entre kernel e user space. A ideia é evitar que falhas em operações como &lt;code&gt;copy_to_user()&lt;/code&gt; e &lt;code&gt;copy_from_user()&lt;/code&gt; virem leitura ou escrita fora dos limites esperados. Slab freelist randomization dificulta exploração de use-after-free ao tornar menos previsível a reutilização de objetos no alocador. &lt;code&gt;init_on_alloc&lt;/code&gt; e &lt;code&gt;init_on_free&lt;/code&gt; ajudam a reduzir exposição de dados residuais em memória, zerando memória em alocação ou liberação, com custos variáveis.&lt;/p&gt;
&lt;p&gt;Lockdown mode tenta proteger a imagem do kernel em execução contra acesso direto ou indireto, especialmente em conjunto com Secure Boot. A &lt;a href=&quot;https://man7.org/linux/man-pages/man7/kernel_lockdown.7.html&quot;&gt;man page do kernel lockdown&lt;/a&gt; deixa claro que a ideia é impedir modificações não autorizadas e acesso a dados sensíveis em memória do kernel. Só que isso vem com efeitos colaterais: interfaces de baixo nível, carregamento de certos módulos, acesso a memória física, kexec e algumas ferramentas de debug podem ser restringidos.&lt;/p&gt;
&lt;p&gt;Assinatura de módulos é outra peça. A &lt;a href=&quot;https://docs.kernel.org/admin-guide/module-signing.html&quot;&gt;documentação oficial de module signing&lt;/a&gt; explica que o kernel pode verificar assinaturas criptográficas ao carregar módulos, recusando módulos não assinados ou assinados por chave inválida. Isso é ótimo para dificultar rootkits via módulo de kernel. Também é ótimo para fazer você lembrar que aquele módulo DKMS do VirtualBox, VMware, ZFS ou driver proprietário não vive no mundo ideal da documentação.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;seccomp&lt;/code&gt; reduz a superfície de syscalls exposta a um processo. A &lt;a href=&quot;https://docs.kernel.org/userspace-api/seccomp_filter.html&quot;&gt;documentação do kernel&lt;/a&gt; é bem direta: muitos processos têm acesso a syscalls que nunca usam; filtrar esse conjunto reduz a superfície do kernel disponível para aquela aplicação. Mas a própria documentação avisa que seccomp não é sandbox completo. Ele é uma ferramenta para construtores de sandbox. A política de comportamento, fluxo de informação e isolamento precisa vir junto com outras camadas.&lt;/p&gt;
&lt;p&gt;Landlock é outro caso interessante porque permite que processos não privilegiados imponham restrições de acesso a si mesmos. A &lt;a href=&quot;https://docs.kernel.org/security/landlock.html&quot;&gt;documentação do Landlock&lt;/a&gt; fala em scoped access control, ou seja, controle de acesso limitado por escopo. Isso é útil para aplicações que querem se confinar sem depender de privilégio administrativo. Mas, de novo, é camada. Não é varinha.&lt;/p&gt;
&lt;p&gt;E tem o mundo dos &lt;code&gt;sysctl&lt;/code&gt;: &lt;code&gt;kernel.dmesg_restrict&lt;/code&gt;, &lt;code&gt;kernel.kptr_restrict&lt;/code&gt;, &lt;code&gt;kernel.yama.ptrace_scope&lt;/code&gt;, &lt;code&gt;kernel.unprivileged_bpf_disabled&lt;/code&gt;, &lt;code&gt;kernel.modules_disabled&lt;/code&gt;. Algumas dessas opções são relativamente tranquilas para muitos ambientes. Outras podem quebrar debug, observabilidade, tracing, eBPF, desenvolvimento, carregamento de driver e até fluxos normais de administração.&lt;/p&gt;
&lt;p&gt;O detalhe que muita gente ignora é que hardening pode acontecer em lugares diferentes. Uma coisa é compilar o kernel com &lt;code&gt;CONFIG_STRICT_KERNEL_RWX&lt;/code&gt;. Outra é passar parâmetro de boot. Outra é ajustar &lt;code&gt;sysctl&lt;/code&gt;. Outra é ativar SELinux enforcing. Outra é usar perfil seccomp em container. Outra é assinar módulos. Outra é configurar systemd para restringir serviço. Tratar tudo isso como “instalar kernel hardened” é simplificar demais.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/kernel-hardening-linux-nao-e-magia/hardening-layers.svg&quot; alt=&quot;Mapa de camadas de kernel hardening envolvendo build, boot, runtime e políticas de segurança&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hardening não é uma muralha única. É uma pilha de mecanismos que dificultam exploração, reduzem superfície ou limitam impacto.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;O kernel da sua distro provavelmente não é tão pelado quanto você imagina&lt;/h2&gt;
&lt;p&gt;Existe uma ideia meio torta de que o kernel padrão da distribuição é um kernel “sem segurança”, e o kernel hardened é o único adulto na sala. Isso era mais defensável anos atrás. Hoje, muitas distribuições já carregam um conjunto decente de mitigations.&lt;/p&gt;
&lt;p&gt;O Ubuntu, por exemplo, documenta proteções como restrição de &lt;code&gt;dmesg&lt;/code&gt;, &lt;code&gt;kptr_restrict&lt;/code&gt;, KASLR, lockdown com Secure Boot, stack protector, seções read-only e Module RO/NX na sua página de &lt;a href=&quot;https://documentation.ubuntu.com/security/security-features/kernel-protections/&quot;&gt;kernel protections&lt;/a&gt;. Fedora e RHEL historicamente apostam forte em SELinux. openSUSE e Ubuntu usam AppArmor como parte importante da política de confinamento. Debian costuma ser mais conservador, mas também herda muitas proteções upstream e oferece AppArmor. Alpine tende a ser minimalista, e Gentoo permite um nível enorme de customização, embora o antigo caminho baseado em grsecurity público tenha mudado depois da restrição de acesso aos patches.&lt;/p&gt;
&lt;p&gt;Isso não significa que todas as distros são igualmente protegidas. Não são. Arch, por exemplo, tende a entregar mais responsabilidade para o usuário. É uma das coisas boas e ruins do Arch ao mesmo tempo. Você ganha controle, mas também ganha o direito sagrado de se cortar com a própria faca.&lt;/p&gt;
&lt;p&gt;O ponto é que trocar para um kernel hardened sem olhar o restante do sistema pode ser uma solução cosmética. Se o seu SSH aceita senha fraca, se o painel administrativo está exposto sem autenticação decente, se o Docker está rodando container privilegiado com volume do host montado em &lt;code&gt;/&lt;/code&gt;, se você instala qualquer coisa do AUR sem ler PKGBUILD, o problema talvez não seja falta de KASLR espiritual.&lt;/p&gt;
&lt;p&gt;Inclusive, depois de escrever sobre &lt;a href=&quot;https://blog.kristyan.dev/posts/mais-de-400-pacotes-aur-foram-comprometidos-com-infostealer-e-rootkit&quot;&gt;pacotes comprometidos no AUR&lt;/a&gt;, fica difícil não olhar para esse tema com certo ceticismo. Muita gente quer fazer hardening no kernel, mas continua tratando script de build aleatório como se fosse pacote oficial assinado por uma entidade benevolente. Segurança não funciona por estética. Não adianta colocar fechadura biométrica na porta e deixar a janela aberta com uma placa “entre, por favor”.&lt;/p&gt;
&lt;h2&gt;Variantes de kernel não resolvem o mesmo problema&lt;/h2&gt;
&lt;p&gt;O kernel mainline, ou vanilla, é o kernel oficial vindo do upstream. Ele é a base. O kernel da distribuição é essa base com escolhas de configuração, backports, patches, suporte e política própria. O kernel LTS prioriza estabilidade e manutenção prolongada. Para produção, isso costuma ser mais interessante do que correr atrás do kernel mais novo só porque saiu ontem e alguém no fórum disse que ficou “mais fluido”.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;linux-hardened&lt;/code&gt; é outra categoria. O projeto &lt;a href=&quot;https://github.com/anthraxx/linux-hardened&quot;&gt;linux-hardened&lt;/a&gt; se apresenta como um suplemento mínimo às mudanças do Kernel Self Protection Project, sem tentar substituir SELinux ou Yama. Ele busca adicionar ou ajustar hardenings que ainda não estão no upstream do jeito desejado. É mais restritivo, e isso é justamente a proposta. Para alguns cenários, faz sentido. Para outros, é só a forma mais elegante de descobrir que hibernação, módulo externo ou ferramenta de tracing não gostou da sua nova personalidade.&lt;/p&gt;
&lt;p&gt;grsecurity/PaX é o elefante histórico na sala. Foi uma das iniciativas mais influentes em hardening de kernel Linux, com proteções agressivas e uma postura técnica que pressionou o ecossistema por anos. Também é um projeto envolto em controvérsias, especialmente por causa de disponibilidade, licenciamento, relação com upstream e a mudança para acesso mais restrito. Ele não é simplesmente “o kernel mais seguro que você instala no domingo”. É uma escolha de nicho, com implicações de suporte, custo e manutenção.&lt;/p&gt;
&lt;p&gt;Zen, Liquorix e XanMod estão em outra conversa. O &lt;a href=&quot;https://liquorix.net/&quot;&gt;Liquorix&lt;/a&gt; se descreve como um kernel voltado a responsividade em sistemas interativos, baixa latência em produção audiovisual e redução de variação em jogos. O &lt;a href=&quot;https://xanmod.org/&quot;&gt;XanMod&lt;/a&gt; se apresenta como um kernel de uso geral com configurações customizadas para uma experiência estável, suave e responsiva. O Zen segue essa linha de desktop e interatividade. Eu uso Zen porque, no meu caso, faz sentido para desktop. Não porque eu ache que ele transforma meu sistema em bunker.&lt;/p&gt;
&lt;p&gt;PREEMPT_RT também não é “kernel seguro”. É kernel para tempo real. O objetivo é latência previsível, não hardening contra exploit. Ele importa em áudio profissional, automação, indústria, sistemas embarcados e cenários em que previsibilidade temporal é requisito. Usar RT achando que é hardening é o equivalente técnico de instalar pneu de corrida para melhorar a fechadura da garagem.&lt;/p&gt;
&lt;p&gt;Linux-libre também é outra discussão. Ele remove blobs e firmware não livre. Isso é uma posição de liberdade de software, não uma garantia automática de segurança. Pode até reduzir dependência de código opaco em alguns contextos, mas também pode deixar hardware sem funcionar ou empurrar o usuário para gambiarras piores. De novo: trade-off.&lt;/p&gt;
&lt;p&gt;Kernels de cloud providers são ainda outra categoria. Eles costumam ser otimizados para o ambiente do provedor, com drivers, integração e escolhas adequadas à infraestrutura daquela nuvem. Em VPS, muitas vezes você nem controla o kernel real do jeito que imagina. Em bare metal, controla mais, mas também assume mais responsabilidade. Em Android, a comparação é útil para lembrar que “Linux kernel” pode significar um mundo bem diferente quando entra vendor tree, SELinux obrigatório, drivers específicos e ciclo de atualização de fabricante.&lt;/p&gt;
&lt;p&gt;O nome do kernel não é a política de segurança. É só uma parte dela.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/kernel-hardening-linux-nao-e-magia/kernel-variants.svg&quot; alt=&quot;Categorias de variantes de kernel Linux por objetivo, incluindo mainline, distro, LTS, hardened, desktop, tempo real, livre e cloud&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Algumas variantes compram suporte previsível, outras responsividade, outras restrição, outras uma posição filosófica. Misturar tudo como “mais seguro” atrapalha a decisão.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;O custo aparece onde dói&lt;/h2&gt;
&lt;p&gt;Hardening quase sempre cobra alguma coisa. Às vezes cobra pouco. Às vezes cobra muito. Às vezes cobra só quando você mais precisa que algo funcione.&lt;/p&gt;
&lt;p&gt;KASLR tem custo baixo, mas pode ser enfraquecido por vazamento de ponteiros. Stack protector tem overhead geralmente aceitável, mas ainda é trabalho extra. KPTI pode pesar mais em workloads com muita transição user/kernel. Mitigações de Spectre variam muito conforme CPU, microcódigo e workload. LSMs fazem checagens adicionais. seccomp executa filtro. Inicialização e limpeza de memória reduzem risco de dado residual, mas não são de graça. Auditoria demais pode virar gargalo. Lockdown pode bloquear ferramentas legítimas.&lt;/p&gt;
&lt;p&gt;E benchmark de kernel é um campo minado. O resultado depende de CPU, scheduler, filesystem, I/O, versão do compilador, flags, mitigations ativas, microcódigo, firmware, workload e distribuição. Dizer “kernel hardened é sempre mais lento” é preguiça. Dizer “não muda nada” também é.&lt;/p&gt;
&lt;p&gt;O jeito correto de pensar é: qual é o workload e qual é o risco?&lt;/p&gt;
&lt;p&gt;Um servidor público com serviço exposto, dados sensíveis e pouca necessidade de módulo externo tem um perfil. Um notebook com GPU híbrida, hibernação, Docker, OBS, Wine, Steam, VirtualBox e vontade de viver tem outro. Uma máquina de desenvolvimento precisa de debug, tracing, perf, bpftrace, ptrace e liberdade para quebrar coisa localmente. Um cluster Kubernetes precisa se preocupar com host kernel, container runtime, seccomp profile, capabilities, AppArmor/SELinux, user namespaces e políticas de pod. Um homelab exposto por Cloudflare Tunnel com senha fraca no painel web precisa talvez menos de kernel custom e mais de vergonha na cara operacional.&lt;/p&gt;
&lt;p&gt;Segurança é sempre contexto. Quem vende resposta universal normalmente está vendendo ansiedade.&lt;/p&gt;
&lt;h2&gt;Containers não salvam você do kernel&lt;/h2&gt;
&lt;p&gt;Containers são um ponto delicado porque muita gente fala deles como se fossem VMs leves. Não são. Containers compartilham o kernel do host. Namespaces, cgroups, capabilities e seccomp ajudam a construir isolamento, mas a fronteira final continua sendo o kernel.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/kernel-hardening-linux-nao-e-magia/containers-shared-kernel.svg&quot; alt=&quot;Containers separados em user space compartilhando o mesmo kernel do host Linux&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;O container reduz e organiza isolamento, mas não troca o kernel por máquina. Por isso uma falha explorável no kernel do host continua sendo assunto sério.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Isso significa que hardening no host importa muito em ambientes com containers. Também significa que features que reduzem privilégio podem aumentar superfície de ataque em outro lugar. User namespaces, por exemplo, são úteis para isolamento sem privilégio real no host, mas também expõem caminhos de kernel que historicamente renderam vulnerabilidades. Não é argumento para “desativar tudo sempre”. É argumento para parar de fingir que uma feature é puramente boa só porque aparece em palestra de segurança.&lt;/p&gt;
&lt;p&gt;No Kubernetes, a conversa fica mais séria. Não basta trocar kernel. É preciso olhar capabilities, containers privilegiados, mounts do host, perfis seccomp, AppArmor/SELinux, runtime, atualização do node, política de admissão, imagens e segredos. Um kernel mais protegido ajuda, mas não conserta cluster mal configurado.&lt;/p&gt;
&lt;p&gt;Aliás, quase nada conserta cluster mal configurado. Talvez terapia.&lt;/p&gt;
&lt;h2&gt;O que eu recomendaria sem vender milagre&lt;/h2&gt;
&lt;p&gt;Para desktop comum, eu não começaria por kernel hardened. Começaria por manter o sistema atualizado, usar navegador atualizado, evitar instalar qualquer pacote aleatório, revisar permissões, ter backup, usar full disk encryption quando fizer sentido, não rodar serviço desnecessário e entender o que está exposto. Um kernel padrão bem mantido da distro, com mitigations modernas, costuma ser uma escolha mais equilibrada do que um kernel restritivo que você vai abandonar na primeira quebra.&lt;/p&gt;
&lt;p&gt;Para desktop técnico, como o meu, um kernel customizado pode fazer sentido por performance, responsividade ou curiosidade. Por isso uso Zen. Mas eu não finjo que isso é uma política de segurança. É uma escolha de experiência. Se eu quisesse hardening real, teria que olhar para sysctl, LSM, Secure Boot, módulos, BPF, serviços, sandboxing e fluxo de atualização. Só trocar o pacote do kernel seria teatro.&lt;/p&gt;
&lt;p&gt;Para servidor público, a conversa muda. Aí faz sentido considerar SELinux ou AppArmor bem configurado, &lt;code&gt;dmesg_restrict&lt;/code&gt;, &lt;code&gt;kptr_restrict&lt;/code&gt;, restrição de BPF não privilegiado, seccomp em serviços, redução de capabilities, firewall decente, atualizações rápidas, menos módulos, menos serviços, menos superfície exposta. Um kernel LTS da distro pode ser melhor do que um kernel alternativo se ele recebe backport de segurança e suporte previsível. Em alguns casos, &lt;code&gt;linux-hardened&lt;/code&gt; ou grsecurity comercial podem fazer sentido, mas isso precisa vir com teste, monitoramento e plano de manutenção.&lt;/p&gt;
&lt;p&gt;Para máquina de desenvolvimento, agressividade demais atrapalha. &lt;code&gt;ptrace_scope&lt;/code&gt; restritivo pode interferir em debug. Lockdown pode atrapalhar tracing. BPF restrito pode quebrar observabilidade. SELinux enforcing sem entender política pode virar caça-fantasma. Ambiente de desenvolvimento precisa ser seguro, mas também precisa deixar o desenvolvedor trabalhar. Parece óbvio. Muita política interna consegue errar isso com convicção.&lt;/p&gt;
&lt;p&gt;Para homelab, o risco geralmente está menos no kernel e mais no entusiasmo. A pessoa sobe vinte serviços, expõe cinco, usa compose copiado do GitHub, não atualiza imagem, deixa painel sem autenticação forte e depois quer discutir slab allocator. Calma. Primeiro fecha porta, atualiza serviço, separa rede, usa backup e para de montar &lt;code&gt;/var/run/docker.sock&lt;/code&gt; em container que você baixou porque o README era bonito.&lt;/p&gt;
&lt;p&gt;Para ambiente corporativo, kernel hardening é decisão de governança. Precisa de inventário, homologação, matriz de compatibilidade, suporte de vendor, observabilidade, resposta a incidente, política de atualização e exceções documentadas. Segurança corporativa que só manda “ativem tudo” sem entender o impacto vira fábrica de bypass.&lt;/p&gt;
&lt;h2&gt;Alguns ajustes simples fazem sentido, mas ainda precisam de contexto&lt;/h2&gt;
&lt;p&gt;Existem configurações que, em muitos sistemas, são boas candidatas a baseline. Restringir &lt;code&gt;dmesg&lt;/code&gt; para usuários sem privilégio reduz vazamento de informação útil para exploração. Restringir ponteiros de kernel em interfaces como &lt;code&gt;/proc&lt;/code&gt; também. Bloquear BPF não privilegiado pode fazer sentido em servidor. Usar seccomp em serviços e containers é uma prática bem razoável. Reduzir capabilities em containers deveria ser rotina, não diferencial.&lt;/p&gt;
&lt;p&gt;Um exemplo de checagem simples é olhar as mitigações de CPU expostas pelo próprio kernel:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;grep . /sys/devices/system/cpu/vulnerabilities/*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso não “mede segurança”, mas mostra o estado de algumas mitigações relevantes para falhas de CPU conhecidas. Também é útil verificar alguns sysctls básicos:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sysctl kernel.dmesg_restrict
sysctl kernel.kptr_restrict
sysctl kernel.yama.ptrace_scope
sysctl kernel.unprivileged_bpf_disabled
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O problema é transformar isso em checklist cego. &lt;code&gt;kernel.yama.ptrace_scope=1&lt;/code&gt; pode ser ótimo para restringir inspeção entre processos, mas pode incomodar debug. &lt;code&gt;kernel.unprivileged_bpf_disabled=1&lt;/code&gt; pode reduzir superfície de ataque, mas pode afetar ferramentas que dependem de eBPF. &lt;code&gt;kernel.modules_disabled=1&lt;/code&gt; é forte, mas depois disso você não carrega mais módulo nenhum até reboot. Isso pode ser excelente em appliance fechado. Pode ser péssimo em desktop.&lt;/p&gt;
&lt;p&gt;Não existe configuração “segura para todo mundo” sem a frase seguinte: segura para qual uso?&lt;/p&gt;
&lt;h2&gt;A polêmica grsecurity vs upstream não é só fofoca de kernel&lt;/h2&gt;
&lt;p&gt;A história do grsecurity é importante porque expõe uma tensão real no Linux: segurança agressiva fora da árvore versus segurança incremental no upstream.&lt;/p&gt;
&lt;p&gt;Do lado de quem defende patches externos, o argumento é que upstream costuma ser lento, conservador e preocupado demais com compatibilidade. Em segurança, esperar consenso perfeito pode significar deixar classes inteiras de exploração viáveis por anos. PaX/grsecurity mostraram que dava para ir além do padrão.&lt;/p&gt;
&lt;p&gt;Do lado upstream, o argumento é que patch massivo, difícil de revisar e manter, pode virar dívida técnica séria. Uma mitigação precisa funcionar em arquiteturas diferentes, com drivers diferentes, sem quebrar subsistemas obscuros e sem criar comportamento impossível de suportar. Segurança que não entra no fluxo normal de manutenção pode ficar presa ao mantenedor externo. Quando esse mantenedor muda acesso, licença ou disponibilidade, a distro fica sem chão. O caso do antigo hardened-sources no Gentoo é um exemplo clássico dessa fragilidade.&lt;/p&gt;
&lt;p&gt;A conclusão chata é que os dois lados têm pontos válidos. Patches externos pressionam inovação. Upstream dá escala, manutenção e revisão. O ideal é que boas ideias sejam incorporadas ao kernel principal de forma sustentável. Só que esse caminho costuma ser lento, político e cheio de bikeshed técnico. Bem-vindo ao software livre em infraestrutura crítica: lindo, caótico e com thread de mailing list que parece julgamento medieval.&lt;/p&gt;
&lt;h2&gt;Hardening real começa antes do kernel&lt;/h2&gt;
&lt;p&gt;A parte menos glamourosa é a mais importante: muitas vezes o problema real não está no kernel.&lt;/p&gt;
&lt;p&gt;Está no serviço exposto sem necessidade. Na senha fraca. No painel administrativo aberto para a internet. No container privilegiado. No bucket público. No token em &lt;code&gt;.env&lt;/code&gt; commitado. No pacote do AUR instalado sem leitura. No script &lt;code&gt;curl | bash&lt;/code&gt;. No servidor que não atualiza porque “se mexer, quebra”. No Docker socket montado em container de dashboard. No Redis ouvindo em interface pública. No WordPress abandonado. No SSH liberado com senha porque “é só temporário”, e todo mundo sabe que temporário em infraestrutura significa “até o incidente”.&lt;/p&gt;
&lt;p&gt;Kernel hardening é camada de defesa. Camada boa, às vezes essencial. Mas camada. Se o resto do sistema é uma peneira, fazer hardening pode até ajudar quando tudo der errado, mas não transforma peneira em cofre.&lt;/p&gt;
&lt;p&gt;Isso não diminui a importância do tema. Pelo contrário. Coloca no lugar certo.&lt;/p&gt;
&lt;h2&gt;Então vale usar kernel hardened?&lt;/h2&gt;
&lt;p&gt;Depende. E “depende” aqui não é fuga. É a única resposta tecnicamente honesta.&lt;/p&gt;
&lt;p&gt;Faz sentido considerar um kernel hardened quando você tem ameaça realista envolvendo execução de código não confiável, multiusuário, containers, serviços expostos, ambiente sensível, requisito de compliance, risco de escalonamento local ou necessidade de reduzir ao máximo a superfície do kernel. Faz ainda mais sentido quando você consegue testar, monitorar e manter esse kernel sem depender de improviso.&lt;/p&gt;
&lt;p&gt;Também faz sentido proteger partes do sistema sem trocar o kernel inteiro: ativar e configurar LSM, restringir sysctl, usar Secure Boot com módulo assinado, aplicar seccomp, reduzir capabilities, remover módulos desnecessários, usar kernel LTS bem mantido e manter atualização em dia. Em muitos casos, isso entrega mais segurança prática do que trocar para um kernel alternativo e não entender o que mudou.&lt;/p&gt;
&lt;p&gt;É melhor evitar kernel hardened quando você depende de drivers proprietários sensíveis, DKMS, VirtualBox, VMware, ZFS fora da árvore, ferramentas pesadas de observabilidade, desenvolvimento com debug frequente, hibernação, hardware exótico ou simplesmente não tem tempo para diagnosticar quebra pós-update. Nesses casos, o kernel padrão da distribuição pode ser a escolha mais segura no sentido operacional da palavra. Segurança também é conseguir atualizar sem medo.&lt;/p&gt;
&lt;p&gt;Para desktop comum, eu tenderia a ser conservador. Para servidor exposto, eu tenderia a proteger mais, mas começando pela configuração do sistema e dos serviços. Para homelab, eu olharia primeiro para o que está exposto. Para ambiente corporativo, eu exigiria teste e política. Para máquina de desenvolvimento, eu não sacrificaria debug em nome de uma ameaça abstrata que talvez nem esteja no modelo.&lt;/p&gt;
&lt;p&gt;Kernel hardening é decisão séria de segurança quando nasce de ameaça, contexto e operação. Quando nasce só de estética, vira só mais uma forma elegante de quebrar driver, debug e virtualização.&lt;/p&gt;
&lt;p&gt;E Linux já dá trabalho suficiente sem a gente transformar ansiedade em parâmetro de boot.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Linux: UFW, Firewalls e Docker</title><link>https://blog.kristyan.dev/posts/linux-ufw-firewalls-e-docker</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/linux-ufw-firewalls-e-docker</guid><description>Um guia técnico e prático sobre UFW no Linux: o que ele faz, o que ele não faz, como conversa com netfilter, iptables, nftables e por que Docker consegue bagunçar a festa.</description><pubDate>Fri, 19 Jun 2026 19:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Firewall em Linux costuma cair em dois extremos: ou vira um assunto místico cheio de chains, hooks, tabelas e regras com cara de encantamento medieval, ou vira um botão bonito escrito “ativar proteção”.&lt;/p&gt;
&lt;p&gt;O UFW fica no meio desses dois mundos.&lt;/p&gt;
&lt;p&gt;Ele não é o firewall em si. Ele não inventa uma camada mágica de segurança. Ele não transforma uma VPS largada na internet em uma fortaleza só porque você digitou &lt;code&gt;sudo ufw enable&lt;/code&gt;. O que ele faz é mais simples, e justamente por isso mais útil: o UFW é uma interface amigável para administrar regras de firewall no Linux usando a infraestrutura do netfilter.&lt;/p&gt;
&lt;p&gt;E isso importa.&lt;/p&gt;
&lt;p&gt;Porque a maioria das pessoas não precisa começar escrevendo regras cruas de iptables ou nftables para bloquear meia dúzia de portas. Mas também não deveria tratar firewall como um amuleto. UFW é uma ferramenta boa quando você entende onde ela termina.&lt;/p&gt;
&lt;h2&gt;Antes do UFW, vem o netfilter&lt;/h2&gt;
&lt;p&gt;Para entender UFW sem cair em fantasia, primeiro é preciso separar as camadas.&lt;/p&gt;
&lt;p&gt;No Linux, quem realmente participa do caminho dos pacotes no kernel é o &lt;a href=&quot;https://www.netfilter.org/documentation/index.html&quot;&gt;netfilter&lt;/a&gt;. Ele fornece os pontos de integração usados para filtrar pacotes, fazer NAT, rastrear conexões e aplicar políticas de rede.&lt;/p&gt;
&lt;p&gt;Por cima dele entram ferramentas de espaço de usuário. Historicamente, a mais famosa foi o &lt;a href=&quot;https://www.netfilter.org/projects/iptables/index.html&quot;&gt;iptables&lt;/a&gt;, que virou quase sinônimo de firewall Linux. Depois veio o &lt;a href=&quot;https://www.netfilter.org/projects/nftables/index.html&quot;&gt;nftables&lt;/a&gt;, criado para substituir a família &lt;code&gt;iptables&lt;/code&gt;, &lt;code&gt;ip6tables&lt;/code&gt;, &lt;code&gt;arptables&lt;/code&gt; e &lt;code&gt;ebtables&lt;/code&gt; com uma arquitetura mais moderna.&lt;/p&gt;
&lt;p&gt;O UFW entra em outra camada: ele é um frontend. A própria documentação do Ubuntu descreve o UFW como uma ferramenta criada para facilitar a configuração do iptables e fornecer uma maneira amigável de criar um firewall baseado em host para IPv4 e IPv6.&lt;/p&gt;
&lt;p&gt;Ou seja:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ufw-n%C3%A3o-%C3%A9-um-firewall-m%C3%A1gico-e-isso-%C3%A9-uma-coisa-boa/ufw-netfilter-stack.svg&quot; alt=&quot;Camadas entre o UFW, os backends iptables ou nftables, o netfilter e o kernel Linux&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;O UFW simplifica a configuração, mas a filtragem de pacotes acontece sobre camadas mais baixas da pilha do Linux.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Essa separação evita muita confusão. Quando você usa UFW, você não está “fugindo” do firewall real do Linux. Você está usando uma interface mais simples para gerar e administrar regras que descem para a infraestrutura real.&lt;/p&gt;
&lt;p&gt;É a diferença entre dirigir um carro automático e fingir que o motor não existe.&lt;/p&gt;
&lt;h2&gt;Um pouco de história: por que o UFW existe&lt;/h2&gt;
&lt;p&gt;O UFW apareceu no Ubuntu 8.04 LTS como uma tentativa bem pragmática de resolver um problema comum: iptables era poderoso, mas pouco amigável para configurações simples.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://wiki.ubuntu.com/UncomplicatedFirewall&quot;&gt;wiki do Ubuntu&lt;/a&gt; descreve o UFW como um frontend para iptables, especialmente adequado para firewalls baseados em host. A ideia nunca foi substituir toda a flexibilidade de regras avançadas. A ideia foi dar uma interface previsível para casos comuns.&lt;/p&gt;
&lt;p&gt;Esse detalhe é importante porque define a expectativa correta.&lt;/p&gt;
&lt;p&gt;UFW não é uma linguagem completa de firewall. Ele é ótimo para responder perguntas simples e operacionais, como negar conexões de entrada por padrão, liberar SSH, permitir HTTP e HTTPS, limitar tentativas repetidas em uma porta ou bloquear um IP específico. Quando a pergunta vira “quero criar uma topologia complexa com múltiplas interfaces, NAT customizado, prioridades de chains e integração fina com containers”, talvez você esteja no território de nftables direto, firewalld ou regras específicas fora do UFW.&lt;/p&gt;
&lt;p&gt;E tudo bem. Ferramenta boa não precisa resolver todos os problemas do planeta. Inclusive, quando tenta, geralmente vira Kubernetes.&lt;/p&gt;
&lt;h2&gt;Instalando e verificando o básico&lt;/h2&gt;
&lt;p&gt;No Ubuntu, o UFW normalmente já vem disponível, mas pode não estar ativo. Em distribuições derivadas de Debian, a instalação é direta:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install ufw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No Arch Linux:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo pacman -S ufw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Antes de sair ativando qualquer coisa, veja o estado atual:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw status verbose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Em uma instalação comum, o UFW pode aparecer como inativo. Isso não significa que o sistema está quebrado. Significa apenas que o frontend ainda não está aplicando a política dele.&lt;/p&gt;
&lt;p&gt;Também vale entender qual backend de firewall o sistema está usando. Em muitas distribuições modernas, o comando &lt;code&gt;iptables&lt;/code&gt; pode estar usando uma camada de compatibilidade sobre nftables:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo iptables -V
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E, em sistemas baseados em Debian/Ubuntu, você pode inspecionar as alternativas:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo update-alternatives --display iptables
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso ajuda a evitar uma confusão comum: achar que “iptables” sempre significa o backend antigo. Às vezes, você está chamando a sintaxe do iptables, mas por baixo o sistema está usando nftables.&lt;/p&gt;
&lt;h2&gt;A primeira regra: não se tranque fora da máquina&lt;/h2&gt;
&lt;p&gt;Se você está configurando UFW em uma máquina remota, principalmente uma VPS acessada por SSH, a regra de ouro é simples: libere SSH antes de ativar o firewall.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow OpenSSH
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ou, se preferir explicitar a porta:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow 22/tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois disso, ative:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw enable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O próprio manual do UFW alerta para esse cenário: ativar o firewall pode derrubar conexões existentes, especialmente se a regra de SSH não estiver liberada. O UFW costuma avisar quando detecta uma sessão SSH, mas aviso não é backup, não é console serial e não é plano de recuperação.&lt;/p&gt;
&lt;p&gt;Em servidor remoto, firewall sem plano de acesso alternativo é só um jeito sofisticado de criar um ticket para você mesmo.&lt;/p&gt;
&lt;h2&gt;Políticas padrão: a base de quase tudo&lt;/h2&gt;
&lt;p&gt;Uma configuração comum e sensata para máquina pessoal, servidor simples ou VPS é negar entrada, permitir saída e negar roteamento por padrão:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw default deny routed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Na prática, isso significa que conexões novas vindas de fora serão bloqueadas, salvo exceções explícitas; conexões iniciadas pela própria máquina poderão sair; e tráfego roteado pela máquina será negado por padrão. Esse modelo funciona bem para a maioria dos hosts. Ele reduz superfície exposta sem transformar a máquina em uma ilha sem internet.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ufw-n%C3%A3o-%C3%A9-um-firewall-m%C3%A1gico-e-isso-%C3%A9-uma-coisa-boa/ufw-default-policy-flow.svg&quot; alt=&quot;Fluxo das políticas padrão do UFW: negar entrada, permitir saída e negar tráfego roteado&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A política padrão define o comportamento geral; as regras &lt;code&gt;allow&lt;/code&gt; abrem apenas os serviços necessários.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Depois você libera apenas o que precisa.&lt;/p&gt;
&lt;h2&gt;Liberando serviços comuns&lt;/h2&gt;
&lt;p&gt;Para um servidor web:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para SSH:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow OpenSSH
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para PostgreSQL apenas a partir de uma rede interna específica:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow from 192.168.1.0/24 to any port 5432 proto tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para bloquear um IP específico:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw deny from 203.0.113.10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para permitir acesso a uma porta apenas de um IP:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow from 203.0.113.20 to any port 22 proto tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Essa sintaxe é justamente o motivo pelo qual o UFW é popular. Ela é legível. Dá para entender a regra seis meses depois, o que é uma qualidade subestimada em configuração de infraestrutura.&lt;/p&gt;
&lt;h2&gt;Perfis de aplicação&lt;/h2&gt;
&lt;p&gt;O UFW também suporta perfis de aplicação. Eles ficam normalmente em &lt;code&gt;/etc/ufw/applications.d&lt;/code&gt; e permitem liberar serviços por nome.&lt;/p&gt;
&lt;p&gt;Para listar os perfis disponíveis:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw app list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para ver detalhes de um perfil:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw app info OpenSSH
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para permitir um perfil:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow OpenSSH
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso é útil quando pacotes instalam perfis próprios. Mas também tem uma pegadinha: perfil de aplicação não é auditoria de segurança. Antes de confiar em um nome bonito, veja quais portas ele realmente libera.&lt;/p&gt;
&lt;h2&gt;Regra por número, regra por conteúdo e pequenas armadilhas&lt;/h2&gt;
&lt;p&gt;Para ver as regras numeradas:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw status numbered
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para remover uma regra pelo número:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw delete 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Também é possível remover pela própria regra original:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw delete allow 80/tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A remoção por número é prática, mas exige atenção. Depois que você apaga uma regra, a numeração muda. Apagar várias regras em sequência olhando uma lista antiga é um convite para remover a regra errada.&lt;/p&gt;
&lt;p&gt;Outro detalhe importante envolve IPv6. A documentação do Ubuntu lembra que o UFW pode criar regras para IPv4 e IPv6. Em alguns casos, remover por número pode remover apenas uma das variantes. Remover pela regra original tende a ser mais claro quando a intenção é apagar a regra completa.&lt;/p&gt;
&lt;h2&gt;IPv6 não é opcional só porque você esqueceu dele&lt;/h2&gt;
&lt;p&gt;Muita gente configura firewall pensando apenas em IPv4 e esquece que a máquina também pode estar exposta em IPv6.&lt;/p&gt;
&lt;p&gt;No UFW, o suporte a IPv6 depende da configuração em:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;/etc/default/ufw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Procure por:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;IPV6=yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois de alterar isso, é comum precisar recarregar o UFW:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A moral aqui é simples: se sua máquina tem IPv6 público e seu firewall só foi pensado em IPv4, você não tem um firewall completo. Você tem uma esperança.&lt;/p&gt;
&lt;h2&gt;Logs: úteis, mas não mágicos&lt;/h2&gt;
&lt;p&gt;O UFW permite ajustar o nível de log:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw logging on
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Também existem níveis como &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt; e &lt;code&gt;full&lt;/code&gt;, conforme descrito no &lt;a href=&quot;https://manpages.ubuntu.com/manpages/noble/man8/ufw.8.html&quot;&gt;manual do UFW&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Para acompanhar logs em sistemas com journal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo journalctl -u ufw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ou, dependendo da distribuição e configuração:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo tail -f /var/log/ufw.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Logs ajudam a entender o que está sendo bloqueado, mas não substituem monitoramento, IDS, revisão de serviços expostos ou configuração correta da aplicação. Firewall é uma camada. Não é uma licença para rodar serviço vulnerável de 2014 exposto na internet.&lt;/p&gt;
&lt;h2&gt;Testando sem autoengano&lt;/h2&gt;
&lt;p&gt;Ver o status do UFW é útil:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw status verbose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mas isso mostra a configuração do firewall, não necessariamente tudo que está exposto como você imagina.&lt;/p&gt;
&lt;p&gt;Veja quais serviços estão escutando:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ss -tulpen
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Teste uma porta localmente:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc -vz 127.0.0.1 5432
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Teste de outra máquina na rede:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc -vz 192.168.1.50 5432
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E, quando fizer sentido, use um scanner a partir de fora:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nmap -Pn -p 1-1000 seu-servidor.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O teste externo é importante porque firewall, NAT, Docker, provedor cloud e bind da aplicação podem produzir resultados diferentes do que você acha olhando apenas para o host.&lt;/p&gt;
&lt;h2&gt;O comando &lt;code&gt;limit&lt;/code&gt; e o mito do anti-bruteforce mágico&lt;/h2&gt;
&lt;p&gt;O UFW tem uma ação chamada &lt;code&gt;limit&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw limit OpenSSH
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ela limita tentativas repetidas de conexão a partir do mesmo IP. Segundo o manual, o UFW normalmente nega conexões quando um IP inicia seis ou mais conexões em trinta segundos.&lt;/p&gt;
&lt;p&gt;Isso ajuda contra ruído e tentativas simples de brute force. Mas não substitui autenticação por chave, desabilitar login por senha quando possível, usar usuários não óbvios, manter o OpenSSH atualizado e monitorar tentativas suspeitas.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ufw limit&lt;/code&gt; é um freio. Não é uma muralha.&lt;/p&gt;
&lt;h2&gt;UFW em desktop Linux&lt;/h2&gt;
&lt;p&gt;Em desktop, uma configuração simples costuma ser suficiente:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso bloqueia conexões novas chegando de fora, mas permite que seu navegador, gerenciador de pacotes, cliente Git e outros programas acessem a rede normalmente.&lt;/p&gt;
&lt;p&gt;Para a maioria dos desktops, isso já reduz bastante exposição acidental. Serviços de desenvolvimento, servidores locais e ferramentas que abrem portas deixam de ficar acessíveis por qualquer máquina na mesma rede sem que você perceba.&lt;/p&gt;
&lt;p&gt;Mas vale uma observação: UFW não é um firewall interativo de aplicação no estilo “o Firefox pode acessar a internet?” ou “este binário desconhecido pode fazer conexão externa?”. Para esse tipo de controle, ferramentas como o &lt;a href=&quot;https://github.com/evilsocket/opensnitch&quot;&gt;OpenSnitch&lt;/a&gt; fazem mais sentido.&lt;/p&gt;
&lt;h2&gt;UFW em servidor&lt;/h2&gt;
&lt;p&gt;Em servidor, o raciocínio precisa ser mais explícito: tudo começa fechado, e só o necessário abre.&lt;/p&gt;
&lt;p&gt;Exemplo para um servidor web comum:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw default deny routed

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

sudo ufw enable
sudo ufw status verbose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se o banco de dados roda no mesmo host, ele provavelmente não precisa estar exposto na rede. Configure a aplicação para acessar via &lt;code&gt;localhost&lt;/code&gt; ou socket Unix, e confirme que o banco não está escutando em &lt;code&gt;0.0.0.0&lt;/code&gt; sem necessidade.&lt;/p&gt;
&lt;p&gt;Se o banco precisa ser acessado por outro host, restrinja por IP ou rede:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow from 10.0.0.0/24 to any port 5432 proto tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Essa é a diferença entre “funciona” e “funciona sem gritar seu banco para a internet”.&lt;/p&gt;
&lt;h2&gt;UFW, Docker e a festa que acaba em IPTables&lt;/h2&gt;
&lt;p&gt;Agora vem a parte em que o UFW deixa de parecer tão simples.&lt;/p&gt;
&lt;p&gt;Docker altera regras de firewall para implementar redes bridge, isolamento entre containers, NAT e publicação de portas. A documentação oficial do Docker explica que o Docker cria regras de firewall para redes bridge e, por padrão, usa iptables para isso. Também há suporte a nftables via backend próprio em versões recentes, mas isso não elimina a necessidade de entender a interação com o firewall do host.&lt;/p&gt;
&lt;p&gt;O problema clássico: Docker e UFW podem não se comportar como você espera.&lt;/p&gt;
&lt;p&gt;A própria documentação do Docker afirma que Docker e UFW são incompatíveis no sentido de que o tráfego de portas publicadas pode ser desviado antes de passar pelas chains &lt;code&gt;INPUT&lt;/code&gt; e &lt;code&gt;OUTPUT&lt;/code&gt; que o UFW usa. Resultado: uma porta publicada por container pode ficar acessível mesmo que sua configuração mental do UFW diga o contrário.&lt;/p&gt;
&lt;p&gt;Exemplo perigoso:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker run -p 8080:80 nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso publica a porta em todas as interfaces por padrão. Em uma VPS, pode significar internet inteira.&lt;/p&gt;
&lt;p&gt;Uma alternativa mais segura para desenvolvimento local é bindar explicitamente no loopback:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker run -p 127.0.0.1:8080:80 nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No Docker Compose:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;services:
  web:
    image: nginx
    ports:
      - &quot;127.0.0.1:8080:80&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esse detalhe vale ouro. Se o serviço só precisa existir localmente atrás de um proxy reverso, túnel ou ambiente de desenvolvimento, não publique em &lt;code&gt;0.0.0.0&lt;/code&gt; por preguiça.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ufw-n%C3%A3o-%C3%A9-um-firewall-m%C3%A1gico-e-isso-%C3%A9-uma-coisa-boa/ufw-docker-published-port.svg&quot; alt=&quot;Comparação entre uma porta Docker publicada em todas as interfaces e uma porta restrita ao loopback local&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Em hosts com Docker, a forma de publicar a porta pode ser mais decisiva do que a regra UFW que você imaginava estar protegendo tudo.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;“Então UFW não funciona com Docker?”&lt;/h2&gt;
&lt;p&gt;Funciona, mas com ressalvas.&lt;/p&gt;
&lt;p&gt;O ponto é não assumir que uma regra UFW bloqueando entrada vai necessariamente controlar tudo que o Docker publica. Docker mexe na pilha de firewall para fazer o container funcionar, e isso pode passar por caminhos diferentes dos que você está olhando.&lt;/p&gt;
&lt;p&gt;A documentação do Docker recomenda cautela ao desabilitar a manipulação de regras por iptables, porque isso pode quebrar a rede dos containers. Ou seja, a solução também não é sair colocando &lt;code&gt;iptables: false&lt;/code&gt; como se fosse tempero.&lt;/p&gt;
&lt;p&gt;Em ambientes com Docker, algumas práticas ajudam bastante. Publique portas apenas em &lt;code&gt;127.0.0.1&lt;/code&gt; quando elas não precisarem ser públicas, use um proxy reverso como ponto único de entrada, revise as portas publicadas com &lt;code&gt;docker ps&lt;/code&gt;, teste de fora da máquina e entenda se o daemon está usando backend iptables ou nftables. Acima de tudo, trate firewall de container como parte da arquitetura, não como detalhe esquecido depois do deploy.&lt;/p&gt;
&lt;p&gt;O Docker também documenta o backend experimental/alternativo com nftables e explica que, nesse modo, ele cria tabelas próprias como &lt;code&gt;ip docker-bridges&lt;/code&gt; e &lt;code&gt;ip6 docker-bridges&lt;/code&gt;. A recomendação é não modificar diretamente as tabelas do Docker, mas criar tabelas separadas quando precisar de regras próprias.&lt;/p&gt;
&lt;p&gt;Firewall com container não é impossível. Só deixa de ser “UFW allow 443 e fé”.&lt;/p&gt;
&lt;h2&gt;UFW route: quando a máquina também encaminha tráfego&lt;/h2&gt;
&lt;p&gt;O UFW também tem regras para tráfego roteado:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw route allow in on eth1 out on eth0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esse tipo de regra importa quando a máquina atua como roteador, gateway, VPN server, host de containers ou qualquer coisa que encaminhe pacotes entre interfaces.&lt;/p&gt;
&lt;p&gt;Mas não basta escrever uma regra &lt;code&gt;ufw route&lt;/code&gt;. O encaminhamento de IP precisa estar habilitado no sistema. O próprio manual aponta configurações em &lt;code&gt;/etc/ufw/sysctl.conf&lt;/code&gt;, como:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;net/ipv4/ip_forward=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Em IPv6, há configuração equivalente.&lt;/p&gt;
&lt;p&gt;Esse é outro bom exemplo de limite do UFW: ele administra regras, mas o comportamento final depende também de sysctl, interfaces, rotas e serviços em volta.&lt;/p&gt;
&lt;h2&gt;Comparando UFW, iptables, nftables, firewalld e OpenSnitch&lt;/h2&gt;
&lt;p&gt;UFW é uma boa escolha quando você quer uma política host-based simples, legível e fácil de manter.&lt;/p&gt;
&lt;p&gt;iptables puro dá controle mais baixo nível, mas cobra em legibilidade e manutenção. Para muitos casos, é mais poder do que necessidade.&lt;/p&gt;
&lt;p&gt;nftables é o caminho moderno e mais expressivo para regras avançadas no Linux. Ele substitui a família antiga de ferramentas e oferece uma base mais consistente. Mas escrever nftables direto exige mais entendimento da pilha.&lt;/p&gt;
&lt;p&gt;firewalld é uma alternativa interessante quando você quer um modelo dinâmico baseado em zonas e políticas. A documentação do &lt;a href=&quot;https://firewalld.org/documentation/concepts.html&quot;&gt;firewalld&lt;/a&gt; descreve a ferramenta como um firewall stateful baseado em zonas, com separação entre configuração runtime e permanente. Ele costuma aparecer bastante em Fedora, RHEL e derivados.&lt;/p&gt;
&lt;p&gt;OpenSnitch joga outro jogo: controle interativo por aplicação, especialmente para tráfego de saída em desktop Linux. É mais próximo de um “Little Snitch para Linux” do que de um substituto direto para UFW em servidor.&lt;/p&gt;
&lt;p&gt;A escolha honesta depende do problema. Para um firewall simples de host, UFW costuma ser o caminho mais direto. Para controle avançado e moderno, nftables merece mais atenção. Em ecossistemas RHEL, Fedora e derivados, firewalld conversa melhor com o modelo de zonas. Para controlar conexões por aplicação em desktop, OpenSnitch joga melhor esse jogo. E, quando o assunto é legado, manutenção de ambiente antigo ou sofrimento por nostalgia, iptables direto ainda aparece bastante.&lt;/p&gt;
&lt;p&gt;Brincadeiras à parte, iptables ainda está em muito lugar e entender sua lógica continua útil. Mas para configuração nova e avançada, nftables merece atenção.&lt;/p&gt;
&lt;h2&gt;Um fluxo prático para configurar UFW sem drama&lt;/h2&gt;
&lt;p&gt;Em uma máquina nova, eu gosto de seguir uma ordem simples.&lt;/p&gt;
&lt;p&gt;Primeiro, ver o estado:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw status verbose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois, definir políticas padrão:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw default deny routed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se for servidor remoto, liberar SSH antes de ativar:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow OpenSSH
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Adicionar os serviços realmente necessários:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ativar:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw enable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verificar:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw status numbered
sudo ss -tulpen
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Testar de fora.&lt;/p&gt;
&lt;p&gt;E documentar o motivo das portas abertas. Firewall sem documentação vira arqueologia. Você encontra uma porta liberada daqui a dois anos e ninguém sabe se era uma necessidade real, um teste esquecido ou um ritual antigo para agradar algum deploy.&lt;/p&gt;
&lt;h2&gt;O que o UFW não resolve&lt;/h2&gt;
&lt;p&gt;UFW não corrige serviço vulnerável, não substitui atualização de pacote, não faz hardening de SSH sozinho e não entende automaticamente sua arquitetura Docker. Ele também não impede vazamento se você libera a porta errada para o mundo, nem substitui autenticação, criptografia, segregação de rede, backup, monitoramento e bom senso.&lt;/p&gt;
&lt;p&gt;Isso não diminui a ferramenta. Pelo contrário. Saber o que uma ferramenta não faz é uma das formas mais saudáveis de usá-la bem.&lt;/p&gt;
&lt;h2&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;UFW é uma das melhores portas de entrada para firewall em Linux porque ele reduz a fricção sem esconder completamente o modelo mental.&lt;/p&gt;
&lt;p&gt;Ele permite criar uma política segura o suficiente para muitos hosts com poucos comandos, mas ainda obriga você a pensar em portas, protocolos, origem, destino e direção do tráfego. Isso é bom. Segurança que elimina completamente o pensamento geralmente só está escondendo a complexidade em outro lugar.&lt;/p&gt;
&lt;p&gt;O melhor uso do UFW é pragmático: negar entrada por padrão, liberar o mínimo necessário, testar de fora, prestar atenção em IPv6, entender a interação com Docker e não fingir que uma camada resolve todos os problemas.&lt;/p&gt;
&lt;p&gt;No fim, UFW não é um firewall mágico.&lt;/p&gt;
&lt;p&gt;É só uma interface simples para uma parte importante do Linux.&lt;/p&gt;
&lt;p&gt;E, honestamente, no mundo de infraestrutura, “simples e previsível” já é quase um superpoder.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>TypeScript 7.0 RC: o tsc nativo em Go chegou</title><link>https://blog.kristyan.dev/posts/typescript-7-rc-go-tsc-nativo</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/typescript-7-rc-go-tsc-nativo</guid><description>O TypeScript 7.0 RC coloca Go no coração do compilador. Para quem vive alternando entre npm install e go mod tidy, a notícia parece estranhamente pessoal.</description><pubDate>Fri, 19 Jun 2026 02:00:00 GMT</pubDate><content:encoded>&lt;p&gt;O TypeScript 7.0 RC foi anunciado em 18 de junho de 2026 e marca uma das maiores mudanças técnicas da história do projeto: o compilador passa a usar uma nova implementação nativa em Go.&lt;/p&gt;
&lt;p&gt;A notícia não é apenas “o TypeScript ficou mais rápido”. A mudança é mais estrutural. Segundo o &lt;a href=&quot;https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-rc/?ref=dailydev&quot;&gt;anúncio oficial do TypeScript 7.0 RC&lt;/a&gt;, a equipe portou a base existente do TypeScript, antes escrita em TypeScript e executada como JavaScript em Node.js, para Go. Com código nativo e paralelismo com memória compartilhada, o novo compilador é frequentemente cerca de 10 vezes mais rápido que o TypeScript 6.0.&lt;/p&gt;
&lt;p&gt;Isso coloca o TypeScript 7.0 RC em uma posição curiosa dentro do ecossistema: uma das ferramentas mais importantes para escrever JavaScript em escala agora depende de uma implementação nativa fora do JavaScript para continuar escalando.&lt;/p&gt;
&lt;p&gt;Não é uma ruptura com a linguagem. É uma mudança na infraestrutura que sustenta a linguagem.&lt;/p&gt;
&lt;h2&gt;O que foi anunciado&lt;/h2&gt;
&lt;p&gt;O TypeScript 7.0 RC é a primeira versão candidata a release do novo compilador nativo. A equipe já vinha preparando esse movimento desde o anúncio do port em Go, publicado em março de 2025 no post &lt;a href=&quot;https://devblogs.microsoft.com/typescript/typescript-native-port/&quot;&gt;A 10x Faster TypeScript&lt;/a&gt;, e depois com os &lt;a href=&quot;https://devblogs.microsoft.com/typescript/announcing-typescript-native-previews/&quot;&gt;previews nativos do TypeScript&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A diferença agora é que a mudança saiu do terreno de preview experimental e entrou no pacote principal do TypeScript.&lt;/p&gt;
&lt;p&gt;Para instalar o RC, o comando é o mesmo esperado para uma release candidata comum:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install -D typescript@rc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois disso, o &lt;code&gt;tsc&lt;/code&gt; continua sendo chamado como antes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A saída esperada é algo como:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Version 7.0.1-rc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Durante os previews, a implementação nativa era distribuída pelo pacote &lt;code&gt;@typescript/native-preview&lt;/code&gt;, com o binário &lt;code&gt;tsgo&lt;/code&gt;. No TypeScript 7.0 RC, o compilador nativo passa a ser entregue pelo pacote &lt;code&gt;typescript&lt;/code&gt; e pelo comando &lt;code&gt;tsc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Os nightlies ainda continuam sendo publicados em &lt;code&gt;@typescript/native-preview&lt;/code&gt; com o binário &lt;code&gt;tsgo&lt;/code&gt;, mas a direção já está definida: quando o TypeScript 7 for publicado como estável, o novo compilador passa a ocupar o fluxo principal do pacote &lt;code&gt;typescript&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Um port para Go, não uma reescrita livre&lt;/h2&gt;
&lt;p&gt;Um ponto importante do anúncio é que a equipe não descreve o TypeScript 7.0 como uma reescrita do zero.&lt;/p&gt;
&lt;p&gt;O texto oficial fala em um port metódico da implementação existente para Go. A lógica de type-checking foi mantida estruturalmente idêntica à do TypeScript 6.0. A intenção é preservar a semântica que os projetos já usam hoje, não criar um “TypeScript novo” incompatível com o comportamento anterior.&lt;/p&gt;
&lt;p&gt;Essa diferença é relevante porque o TypeScript não é apenas um compilador chamado manualmente no terminal. Ele é base para editor, CI, monorepos, ferramentas de build, linters, frameworks, bibliotecas e integrações que dependem de detalhes do comportamento do compilador.&lt;/p&gt;
&lt;p&gt;Uma reescrita livre poderia entregar performance, mas também abriria espaço para diferenças difíceis de rastrear. O caminho escolhido foi outro: portar a arquitetura e a lógica existentes para uma fundação nativa, tentando manter compatibilidade com o TypeScript 6.0.&lt;/p&gt;
&lt;p&gt;A equipe afirma que o TypeScript 7.0 foi avaliado contra a suíte de testes acumulada ao longo de mais de uma década e já foi testado em bases com milhões de linhas de código dentro e fora da Microsoft.&lt;/p&gt;
&lt;h2&gt;Por que isso importa&lt;/h2&gt;
&lt;p&gt;O TypeScript deixou de ser apenas uma linguagem ou uma camada de tipos em cima do JavaScript. Em muitos projetos, ele virou infraestrutura.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;tsc&lt;/code&gt; parseia arquivos, resolve módulos, monta programas, checa tipos, emite JavaScript, gera arquivos de declaração e alimenta recursos usados por editores. Em projetos pequenos, esse trabalho costuma parecer invisível. Em projetos grandes, ele vira parte relevante do tempo de feedback do desenvolvedor.&lt;/p&gt;
&lt;p&gt;Quando o type-checking demora demais, o impacto aparece no comportamento do time. Alguém passa a rodar menos o compilador localmente. Alguém deixa a checagem só para o CI. Alguém usa &lt;code&gt;transpileOnly&lt;/code&gt;. Alguém aceita um editor lento como se fosse uma característica natural da vida adulta.&lt;/p&gt;
&lt;p&gt;A mudança para Go tenta atacar exatamente esse gargalo: reduzir o custo de manter o TypeScript ativo no fluxo de desenvolvimento.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/typescript-7-rc-go-tsc-nativo/tsc-native-pipeline.svg&quot; alt=&quot;Comparação do pipeline do tsc clássico em TypeScript sobre Node.js com o novo tsc nativo em Go usando workers&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A mudança principal não está no nome do comando. Está no caminho que o comando percorre por dentro.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;O que muda na execução do compilador&lt;/h2&gt;
&lt;p&gt;O ganho de performance vem de dois fatores principais: execução nativa e paralelismo.&lt;/p&gt;
&lt;p&gt;Na implementação anterior, o compilador era escrito em TypeScript, compilado para JavaScript e executado em Node.js. Isso trouxe portabilidade e um modelo muito alinhado com o ecossistema, mas também impôs limitações para uma ferramenta que precisa lidar com grafos grandes de arquivos, análise semântica, cache, diagnósticos e editor.&lt;/p&gt;
&lt;p&gt;Na nova implementação, o TypeScript 7.0 consegue paralelizar etapas do compilador, incluindo parsing, type-checking e emit.&lt;/p&gt;
&lt;p&gt;Parsing e emit são mais naturalmente paralelizáveis porque muitos arquivos podem ser processados de maneira relativamente independente. Type-checking é mais complexo, porque tipos dependem de outros tipos, símbolos podem ser compartilhados, declarações globais interferem no programa inteiro e a ordem de análise pode afetar resultados.&lt;/p&gt;
&lt;p&gt;Para lidar com isso, o TypeScript 7.0 usa workers de type-checking com uma visão consistente do programa. O número padrão de checkers é 4, mas pode ser ajustado com a flag &lt;code&gt;--checkers&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --noEmit --checkers 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aumentar esse número pode melhorar o tempo de build em máquinas com mais núcleos e projetos maiores, mas também aumenta consumo de memória. Em CI pequeno, container limitado ou runner compartilhado, mais paralelismo pode ser contraproducente.&lt;/p&gt;
&lt;p&gt;Além disso, o TypeScript 7.0 adiciona a flag &lt;code&gt;--builders&lt;/code&gt;, voltada para builds com project references. Ela controla quantos builders podem rodar em paralelo.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --build --checkers 4 --builders 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esse ponto merece cuidado porque &lt;code&gt;--builders&lt;/code&gt; e &lt;code&gt;--checkers&lt;/code&gt; têm efeito multiplicativo. Um build com &lt;code&gt;--checkers 4 --builders 4&lt;/code&gt; pode permitir até 16 type-checkers ao mesmo tempo.&lt;/p&gt;
&lt;p&gt;Para cenários de debug, comparação de performance ou ambientes com recursos limitados, existe também o modo single-threaded:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --build --singleThreaded
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A flag &lt;code&gt;--singleThreaded&lt;/code&gt; força parsing, emit e type-checking a rodarem sem paralelismo.&lt;/p&gt;
&lt;h2&gt;O modo watch também mudou&lt;/h2&gt;
&lt;p&gt;Outra parte importante da notícia é a reconstrução do modo &lt;code&gt;--watch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O TypeScript 7.0 passa a usar uma fundação derivada do file watcher do Parcel, portada e refinada em Go. Segundo a equipe, a motivação veio da necessidade de ter um mecanismo eficiente, estável e multiplataforma para observar mudanças em arquivos sem depender de uma toolchain C++ completa.&lt;/p&gt;
&lt;p&gt;Isso é menos chamativo do que “10 vezes mais rápido”, mas é uma mudança prática importante. O modo watch é parte central do ciclo de desenvolvimento em projetos TypeScript. Ele precisa reagir rápido a mudanças, evitar trabalho desnecessário e não consumir CPU demais em bases grandes.&lt;/p&gt;
&lt;p&gt;File watching parece simples até envolver macOS, Linux, Windows, monorepos, &lt;code&gt;node_modules&lt;/code&gt;, symlinks, volumes montados e diretórios gerados automaticamente. Se esse componente é ruim, o editor e o build incremental sofrem.&lt;/p&gt;
&lt;p&gt;No anúncio, a equipe afirma que o novo watcher já mostra melhorias significativas de uso de recursos em diferentes plataformas.&lt;/p&gt;
&lt;h2&gt;O impacto no editor&lt;/h2&gt;
&lt;p&gt;O TypeScript 7.0 não mira apenas o terminal. A experiência de editor também faz parte da mudança.&lt;/p&gt;
&lt;p&gt;O novo foundation é usado pela extensão &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=TypeScriptTeam.native-preview&quot;&gt;TypeScript Native Preview para VS Code&lt;/a&gt; e passa a se apoiar no Language Server Protocol, o LSP. Isso permite que o servidor de linguagem aproveite múltiplas threads para responder requisições simultâneas.&lt;/p&gt;
&lt;p&gt;Na prática, o impacto esperado aparece em operações como autocomplete, hover, go to definition, find references, rename, auto-imports, code actions, inlay hints e diagnósticos enquanto o código é editado.&lt;/p&gt;
&lt;p&gt;A equipe afirma que funcionalidades que ainda estavam ausentes em fases anteriores, como semantic highlighting, sort imports e remove unused imports, já foram incorporadas ao estado atual do TypeScript 7.0. O anúncio também cita uma redução de mais de 20 vezes em comandos falhos no language server em comparação com o TypeScript 6.0, com base nos dados de teste da própria equipe.&lt;/p&gt;
&lt;p&gt;Para quem trabalha em bases grandes, esse talvez seja o ganho mais importante. Build rápido ajuda. Editor responsivo muda o dia.&lt;/p&gt;
&lt;h2&gt;TypeScript 6.0 é parte da transição&lt;/h2&gt;
&lt;p&gt;O TypeScript 7.0 RC não deve ser visto isoladamente. Ele depende de mudanças preparadas no TypeScript 6.0, anunciado como uma versão de transição e como a última grande release baseada na implementação JavaScript tradicional.&lt;/p&gt;
&lt;p&gt;A equipe recomenda que projetos adotem o TypeScript 6.0 antes de migrar para o 7.0. Isso porque o TypeScript 7.0 adota os novos defaults do 6.0 e transforma algumas depreciações em erros.&lt;/p&gt;
&lt;p&gt;Entre as mudanças de configuração, o TypeScript 7.0 passa a considerar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;strict&lt;/code&gt; como &lt;code&gt;true&lt;/code&gt; por padrão;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;module&lt;/code&gt; como &lt;code&gt;esnext&lt;/code&gt; por padrão;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;noUncheckedSideEffectImports&lt;/code&gt; como &lt;code&gt;true&lt;/code&gt; por padrão;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;libReplacement&lt;/code&gt; como &lt;code&gt;false&lt;/code&gt; por padrão;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stableTypeOrdering&lt;/code&gt; como &lt;code&gt;true&lt;/code&gt; e sem possibilidade de desligar;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rootDir&lt;/code&gt; como &lt;code&gt;./&lt;/code&gt; por padrão;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;types&lt;/code&gt; como &lt;code&gt;[]&lt;/code&gt; por padrão.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Também entram como não suportadas ou com comportamento de erro algumas opções antigas, como &lt;code&gt;target: es5&lt;/code&gt;, &lt;code&gt;downlevelIteration&lt;/code&gt;, &lt;code&gt;moduleResolution: node/node10&lt;/code&gt;, &lt;code&gt;moduleResolution: classic&lt;/code&gt;, &lt;code&gt;module: amd&lt;/code&gt;, &lt;code&gt;umd&lt;/code&gt;, &lt;code&gt;systemjs&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt; e &lt;code&gt;baseUrl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Essas mudanças reduzem compatibilidade com configurações legadas, mas também refletem um ecossistema mais moderno, com bundlers, ESM e runtimes evergreen ocupando o fluxo principal.&lt;/p&gt;
&lt;p&gt;O ponto prático é simples: projeto que ainda depende de opções antigas deve fazer a limpeza no TypeScript 6.0 antes de testar o 7.0.&lt;/p&gt;
&lt;h2&gt;Mudanças para JavaScript e JSDoc&lt;/h2&gt;
&lt;p&gt;O TypeScript 7.0 também muda o suporte a arquivos JavaScript analisados com JSDoc.&lt;/p&gt;
&lt;p&gt;Segundo o anúncio, a equipe revisitou essa camada para torná-la mais consistente com a forma como arquivos &lt;code&gt;.ts&lt;/code&gt; são analisados. Isso remove alguns comportamentos especiais ligados a padrões antigos de JSDoc, Closure-style syntax e inferências baseadas em formas históricas de escrever JavaScript.&lt;/p&gt;
&lt;p&gt;Algumas diferenças citadas incluem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;valores não podem mais ser usados onde tipos são esperados;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@enum&lt;/code&gt; deixa de ter tratamento especial;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&lt;/code&gt; sozinho deixa de ser aceito como tipo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@class&lt;/code&gt; não transforma uma função em construtor;&lt;/li&gt;
&lt;li&gt;postfix &lt;code&gt;!&lt;/code&gt; deixa de ser suportado;&lt;/li&gt;
&lt;li&gt;sintaxe Closure-style de função deixa de ser suportada;&lt;/li&gt;
&lt;li&gt;alias de &lt;code&gt;this&lt;/code&gt; e reatribuição completa de &lt;code&gt;prototype&lt;/code&gt; deixam de receber tratamento especial.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esse é um dos pontos de maior atenção para projetos JavaScript que usam TypeScript apenas como ferramenta de análise, especialmente bases antigas com JSDoc muito flexível.&lt;/p&gt;
&lt;h2&gt;A API programática ainda não está pronta&lt;/h2&gt;
&lt;p&gt;A maior limitação prática do TypeScript 7.0 RC está na API programática.&lt;/p&gt;
&lt;p&gt;Embora o novo &lt;code&gt;tsc&lt;/code&gt; já esteja disponível no pacote &lt;code&gt;typescript@rc&lt;/code&gt;, a equipe afirma que uma API programática estável só deve chegar depois, pelo menos no TypeScript 7.1.&lt;/p&gt;
&lt;p&gt;Isso importa porque muitas ferramentas não usam apenas o binário &lt;code&gt;tsc&lt;/code&gt;. Elas importam o pacote &lt;code&gt;typescript&lt;/code&gt; diretamente para acessar AST, diagnósticos, programas, tipos e outros recursos internos.&lt;/p&gt;
&lt;p&gt;Para reduzir o impacto dessa transição, a equipe publicou o pacote &lt;code&gt;@typescript/typescript6&lt;/code&gt;. Ele fornece o executável &lt;code&gt;tsc6&lt;/code&gt; e reexporta a API do TypeScript 6.0. Assim, um projeto pode usar o novo &lt;code&gt;tsc&lt;/code&gt; do TypeScript 7 para compilação, enquanto ferramentas que dependem da API antiga continuam usando TypeScript 6.&lt;/p&gt;
&lt;p&gt;Um exemplo de configuração com alias no &lt;code&gt;package.json&lt;/code&gt; seria:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;devDependencies&quot;: {
    &quot;typescript&quot;: &quot;npm:@typescript/typescript6@^6.0.0&quot;,
    &quot;typescript-7&quot;: &quot;npm:typescript@rc&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/typescript-7-rc-go-tsc-nativo/typescript-compatibility-split.svg&quot; alt=&quot;Diagrama mostrando o uso do tsc nativo pela CLI em paralelo com ferramentas que ainda dependem da API do TypeScript 6&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A migração pode separar o uso do compilador pela CLI do uso da API programática por ferramentas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Esse é um detalhe essencial para projetos com ESLint, test runners, frameworks, plugins internos ou qualquer ferramenta que dependa diretamente do pacote &lt;code&gt;typescript&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Como testar com segurança&lt;/h2&gt;
&lt;p&gt;O TypeScript 7.0 RC já foi apresentado como estável o suficiente para testes em fluxos diários e CI, mas ainda é uma release candidate. O caminho mais seguro é tratar a migração como mudança de ferramenta central, não como atualização trivial.&lt;/p&gt;
&lt;p&gt;Um roteiro razoável seria começar pelo TypeScript 6.0, remover depreciações e garantir que o projeto compila limpo sem &lt;code&gt;ignoreDeprecations&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Depois disso, instalar o RC:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install -D typescript@rc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rodar a checagem principal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --noEmit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Em projetos com build mode:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Em monorepos, testar project references e paralelismo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --build --checkers 4 --builders 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E comparar com o modo single-threaded:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx tsc --build --singleThreaded
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A comparação deve considerar não apenas tempo total de build, mas também diagnósticos, saída gerada, consumo de memória, comportamento no CI, modo watch e experiência no editor.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/typescript-7-rc-go-tsc-nativo/typescript-migration-path.svg&quot; alt=&quot;Fluxo sugerido para testar TypeScript 7 RC começando pelo TypeScript 6, limpando tsconfig, rodando o RC em paralelo e medindo memória e saída&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;RC em ferramenta central merece roteiro, não fé.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;O que ainda observar&lt;/h2&gt;
&lt;p&gt;O TypeScript 7.0 RC é uma mudança grande, mesmo com o esforço de compatibilidade.&lt;/p&gt;
&lt;p&gt;Os principais pontos de atenção são:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;projetos que dependem da API programática do pacote &lt;code&gt;typescript&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;monorepos com project references;&lt;/li&gt;
&lt;li&gt;CI com poucos recursos de CPU e memória;&lt;/li&gt;
&lt;li&gt;bases JavaScript com JSDoc legado;&lt;/li&gt;
&lt;li&gt;configurações antigas de &lt;code&gt;tsconfig&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;ferramentas que ainda esperam comportamento específico do TypeScript 5.x ou 6.x.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A equipe planeja lançar o TypeScript 7.0 estável dentro de aproximadamente um mês após o RC e concentrar os próximos esforços em coordenação de release, regressões reportadas e futuras capacidades de API no TypeScript 7.1.&lt;/p&gt;
&lt;p&gt;Enquanto isso, o RC já permite testar o novo compilador em projetos reais e medir o impacto da troca de fundação.&lt;/p&gt;
&lt;h2&gt;O significado da mudança&lt;/h2&gt;
&lt;p&gt;O TypeScript 7.0 RC mostra uma tendência que já vinha acontecendo no ecossistema JavaScript: ferramentas de infraestrutura estão migrando para implementações nativas quando o custo de performance começa a afetar o fluxo de desenvolvimento.&lt;/p&gt;
&lt;p&gt;Bundlers, linters, formatadores, transpiladores e runtimes já vinham explorando Go, Rust e Zig. Agora, o próprio compilador oficial do TypeScript entra nessa lista.&lt;/p&gt;
&lt;p&gt;Isso não significa que JavaScript perdeu espaço como linguagem de aplicação. O ponto é outro: tooling de linguagem tem exigências diferentes. Compiladores e language servers precisam lidar com grandes volumes de código, grafos de dependência, análise semântica, cache, concorrência e resposta rápida no editor.&lt;/p&gt;
&lt;p&gt;O TypeScript 7.0 RC é uma resposta a essa escala.&lt;/p&gt;
&lt;p&gt;Para quem escreve TypeScript, a promessa é menos tempo esperando o compilador. Para quem escreve Go, é mais um exemplo de Go sendo usado em infraestrutura de desenvolvimento. Para quem escreve os dois, é aquele momento raro em que dois mundos do dia a dia resolvem se encontrar sem precisar de um microserviço no meio.&lt;/p&gt;
&lt;p&gt;No fim, a notícia é simples: o &lt;code&gt;tsc&lt;/code&gt; mudou de motor.&lt;/p&gt;
&lt;p&gt;O comando continua familiar. A linguagem continua sendo TypeScript. Mas a fundação por baixo agora é outra.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>X11 não morreu por acaso: Wayland é a faxina que o desktop Linux adiou por décadas</title><link>https://blog.kristyan.dev/posts/x11-xorg-wayland-desktop-linux</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/x11-xorg-wayland-desktop-linux</guid><description>Uma análise histórica e técnica sobre X11, Xorg e Wayland, do MIT ao desktop Linux moderno, e por que trocar o servidor gráfico virou uma cirurgia sem anestesia.</description><pubDate>Wed, 17 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;O X11 é uma daquelas peças do Linux desktop que parecem eternas porque ficaram tempo demais funcionando bem o suficiente. Não necessariamente bem. Não necessariamente bonito. Não necessariamente seguro. Mas bem o suficiente para a maioria das pessoas abrir um terminal, arrastar uma janela torta, configurar três monitores na base da fé e seguir a vida.&lt;/p&gt;
&lt;p&gt;Esse é o tipo de tecnologia que vira infraestrutura invisível. Enquanto funciona, ninguém pensa nela. Quando quebra, parece que metade do sistema operacional foi projetado por arqueólogos com acesso a C e rancor acumulado.&lt;/p&gt;
&lt;p&gt;O problema é que o X11 não foi criado para o computador pessoal moderno. Ele nasceu em outro mundo: estações Unix, terminais gráficos, redes locais confiáveis, usuários técnicos, máquinas caras e um modelo em que “rodar um programa em uma máquina e exibir em outra” era uma feature central, não uma curiosidade de nicho. Esse contexto explica muita coisa. Também explica por que tentar encaixar captura de tela segura, sandboxing, monitores com escalas diferentes, GPUs modernas, tablets, VRR, HDR, jogos e aplicativos Electron em cima dessa arquitetura virou um esporte de resistência.&lt;/p&gt;
&lt;p&gt;O Wayland não surgiu porque alguém acordou e decidiu trocar uma peça central do desktop Linux só para irritar usuário de Arch com NVIDIA (autodescrição). Embora, olhando alguns fóruns, pareça exatamente isso. Ele surgiu porque o X11 foi acumulando responsabilidades, extensões e remendos até virar uma pilha onde muita coisa moderna funcionava apesar da arquitetura, não por causa dela.&lt;/p&gt;
&lt;h2&gt;Antes do Wayland, tinha o X; antes do X, tinha outro mundo&lt;/h2&gt;
&lt;p&gt;O X Window System nasceu no MIT em 1984, dentro do contexto do Project Athena, um projeto criado por MIT, DEC e IBM para oferecer computação distribuída em um ambiente heterogêneo de máquinas e usuários. A ideia era ter um sistema gráfico independente de fabricante, capaz de funcionar em diferentes hardwares e sistemas Unix. A versão 11 do protocolo, o famoso X11, foi lançada em setembro de 1987, e é por isso que até hoje o nome carrega esse número meio fóssil em produção: &lt;a href=&quot;https://en.wikipedia.org/wiki/X_Window_System&quot;&gt;X11 não é “mais um nome”, é literalmente a versão do protocolo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O detalhe importante é que o X nasceu como um sistema gráfico de rede. No modelo do X, o “servidor” é o programa que controla a tela, o teclado e o mouse. Os “clientes” são as aplicações que pedem para desenhar janelas e receber eventos. Isso confunde muita gente porque, no uso comum de cliente-servidor, a gente imagina o servidor como a máquina remota e o cliente como o computador do usuário. No X é o contrário: o servidor está onde está o display. O cliente pode estar na mesma máquina ou em outro computador da rede.&lt;/p&gt;
&lt;p&gt;Essa inversão fazia sentido. Se você tinha uma workstation gráfica local e queria rodar um software pesado em uma máquina remota, o X permitia que a aplicação remota desenhasse na sua tela local. Era uma arquitetura elegante para o mundo Unix acadêmico e corporativo dos anos 80. O &lt;a href=&quot;https://www.x.org/releases/current/doc/man/man7/X.7.xhtml&quot;&gt;manual do X&lt;/a&gt; e a própria história do sistema deixam claro esse foco em uma interface gráfica independente de máquina, sistema e fabricante.&lt;/p&gt;
&lt;p&gt;Só que uma boa ideia em 1987 pode virar uma dívida técnica em 2026. Especialmente quando o mundo deixa de ser uma rede local relativamente confiável e vira uma coleção de notebooks, sandboxes, Flatpaks, jogos, GPUs híbridas, telas 4K, compositores, screen sharing no navegador e aplicativos que querem capturar input global porque “produtividade”.&lt;/p&gt;
&lt;h2&gt;XFree86: quando o desktop Linux precisava de um X que funcionasse em PCs&lt;/h2&gt;
&lt;p&gt;Nos anos 90, o Linux começou a ganhar espaço em PCs comuns. Só que PC comum não era workstation Unix polida. Era placa de vídeo variada, driver estranho, BIOS suspeita, monitor que talvez informasse as resoluções corretamente e usuário querendo abrir uma interface gráfica sem vender a alma para um fornecedor proprietário.&lt;/p&gt;
&lt;p&gt;Nesse cenário, o XFree86 virou peça central. O projeto começou em 1992 a partir do X386, uma implementação do servidor X para PCs compatíveis com IBM PC, e acabou se tornando a implementação dominante do X em Linux e BSD durante boa parte dos anos 90 e começo dos anos 2000. A história curta é: o XFree86 fez o X funcionar onde o Linux desktop estava crescendo, e isso foi enorme. A história longa envolve governança, licença, conflitos de desenvolvimento e aquele tempero clássico de projeto open source importante demais para ter pouca gente decidindo tudo.&lt;/p&gt;
&lt;p&gt;O XFree86 não era só “mais um servidor gráfico”. Na prática, ele virou a referência de desenvolvimento do X no mundo livre. Só que, no início dos anos 2000, o projeto começou a enfrentar críticas de governança e, em 2004, uma mudança de licença no XFree86 4.4 gerou rejeição em várias distribuições e projetos. A partir daí, o X.Org Server tomou o lugar como implementação dominante do X11, usando uma base derivada do XFree86 antes da mudança de licença e uma governança mais aberta. O resumo histórico aparece bem documentado em fontes como a página sobre &lt;a href=&quot;https://en.wikipedia.org/wiki/XFree86&quot;&gt;XFree86&lt;/a&gt; e a história do &lt;a href=&quot;https://en.wikipedia.org/wiki/X.Org_Server&quot;&gt;X.Org Server&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Foi aí que “Xorg” virou sinônimo prático de servidor gráfico no Linux. Tecnicamente, X11 é o protocolo. Xorg é a implementação moderna mais conhecida desse protocolo. Mas no dia a dia muita gente fala “estou usando Xorg” para dizer “minha sessão gráfica é X11”. Não é preciso chamar a polícia dos nomes, mas a diferença importa quando se discute arquitetura.&lt;/p&gt;
&lt;h2&gt;O X11 é mecanismo, não política&lt;/h2&gt;
&lt;p&gt;Uma das ideias fundamentais do X é fornecer mecanismo, não política. O X não define como sua interface deve parecer. Ele não decide se a janela tem botão à esquerda, à direita, borda grossa, tema cinza triste ou transparência com gosto duvidoso. Ele oferece primitivas: janelas, eventos, desenho, input, comunicação entre cliente e servidor. A política fica com o window manager, com o toolkit, com o desktop environment e com as convenções ao redor.&lt;/p&gt;
&lt;p&gt;Isso explica por que o X conseguiu sobreviver tanto tempo. Ele era extensível. Se faltava algo, criava-se uma extensão. Renderização moderna? Extensão. Composição? Extensão. Input melhor? Extensão. Configuração dinâmica de monitor? Extensão. Sincronização? Extensão. O X virou uma espécie de kernel social do desktop Unix: pequeno no conceito original, enorme na prática, e cercado de mecanismos auxiliares que todo mundo aprendeu a respeitar com medo.&lt;/p&gt;
&lt;p&gt;No modelo clássico, o X server controla o hardware de display e input. O window manager decide onde as janelas ficam. Um compositor, quando existe, compõe o conteúdo final da tela com sombras, transparências e efeitos. O cliente gráfico é a aplicação: terminal, navegador, editor, IDE, seja lá qual for o pecado do dia.&lt;/p&gt;
&lt;p&gt;O ponto é que essas responsabilidades foram separadas em uma época em que composição não era parte essencial do fluxo. No X moderno, porém, o compositor virou praticamente obrigatório para uma experiência decente. Só que ele foi encaixado por cima de uma arquitetura que não nasceu com ele no centro.&lt;/p&gt;
&lt;p&gt;A documentação do Wayland descreve bem essa crítica: no X moderno, o servidor continua no caminho entre clientes, compositor e hardware, mesmo quando parte da responsabilidade real já foi para bibliotecas, drivers do kernel e compositores externos. A própria &lt;a href=&quot;https://wayland.freedesktop.org/docs/book/Introduction.html&quot;&gt;introdução oficial do Wayland&lt;/a&gt; aponta que o X acumulou funções como gerenciamento de display, renderização, composição e interação com drivers, criando complexidade e passos extras.&lt;/p&gt;
&lt;h2&gt;Como o X11 funciona na prática&lt;/h2&gt;
&lt;p&gt;No X11, uma aplicação normalmente conversa com o servidor X usando bibliotecas como Xlib ou XCB, diretamente ou por meio de toolkits como GTK, Qt, Motif, wxWidgets e similares. O cliente pede para criar janelas, desenhar elementos, receber eventos de teclado e mouse, manipular propriedades e interagir com outras janelas. O servidor X arbitra esses pedidos e expõe os eventos para os clientes interessados.&lt;/p&gt;
&lt;p&gt;Esse modelo tem algumas consequências importantes.&lt;/p&gt;
&lt;p&gt;A primeira é a transparência de rede. Como o protocolo foi desenhado para comunicação cliente-servidor, uma aplicação pode rodar em uma máquina e exibir em outra. Isso é parte do DNA do X, não um plugin de última hora. Em ambientes acadêmicos, corporativos e laboratoriais, isso foi extremamente útil. Em 2026, ainda existe gente que depende disso. Nem todo mundo vive dentro de um navegador com tema Dracula e cinco monitores.&lt;/p&gt;
&lt;p&gt;A segunda é que os clientes X têm poder demais dentro da sessão. Um cliente autorizado pode observar ou interferir em muito mais do que um aplicativo moderno deveria. Ferramentas de automação, captura de input, seleção global, clipboard e inspeção de janelas funcionam muito bem justamente porque o modelo de segurança é permissivo. Isso é conveniente. Também é assustador. O &lt;a href=&quot;https://www.x.org/releases/current/doc/man/man7/Xsecurity.7.xhtml&quot;&gt;manual Xsecurity&lt;/a&gt; existe porque autorização em X11 sempre foi um assunto delicado; o problema não é só “conectar ou não conectar”, mas o que um cliente autorizado consegue fazer depois que entra.&lt;/p&gt;
&lt;p&gt;A terceira é que composição no X é uma camada adicionada. O X originalmente não foi desenhado como um compositor moderno. Quando o desktop passou a exigir transparência, sombras, animações, redirecionamento de janelas e efeitos, a solução foi usar extensões como Composite, Damage, Render, XFixes, RandR, XInput e várias outras. Isso funcionou, mas criou um conjunto de acoplamentos difícil de explicar sem um quadro branco e uma crise existencial.&lt;/p&gt;
&lt;p&gt;A quarta é que renderização também mudou de lugar ao longo do tempo. No início, desenhar via primitivas do X fazia mais sentido. Depois vieram Cairo, OpenGL, DRI, Mesa, renderização direta no cliente, buffers compartilhados, GPU moderna. O servidor X foi deixando de ser o lugar natural onde o desenho acontecia e virou mais um intermediário entre partes que já sabiam conversar com o kernel e com a GPU.&lt;/p&gt;
&lt;p&gt;O resultado é um sistema impressionante, mas torto. O X11 é uma engenharia brilhante para o problema que ele queria resolver. O problema é que continuamos pedindo para ele resolver problemas que não estavam no contrato original.&lt;/p&gt;
&lt;h2&gt;O desktop moderno colocou o X11 contra a parede&lt;/h2&gt;
&lt;p&gt;O desktop Linux moderno exige coisas que parecem simples até você tentar implementar sem quebrar vinte anos de compatibilidade.&lt;/p&gt;
&lt;p&gt;Multi-monitor com densidades diferentes não é trivial. Um monitor 4K em escala 150% ao lado de um monitor 1080p em 100% exige que o sistema entenda coordenadas lógicas, coordenadas físicas, buffers, escala por saída e posicionamento sem fingir que tudo é um retângulo global homogêneo. O X11 consegue lidar com muita coisa via RandR e hacks de compositor, mas o modelo não foi feito para isso com naturalidade.&lt;/p&gt;
&lt;p&gt;HiDPI e fractional scaling também sofrem por causa dessa herança. Em X11, o toolkit, o compositor, o servidor e a aplicação podem discordar sobre o que é um pixel, o que é uma unidade lógica e quem deve escalar o quê. No Wayland, isso também não é magicamente perfeito, mas pelo menos a arquitetura permite que o compositor tenha controle real sobre outputs, escala e buffers de cada superfície.&lt;/p&gt;
&lt;p&gt;Captura de tela é outro exemplo clássico. No X11, capturar a tela era fácil porque os clientes podiam acessar informações globais da sessão com pouca cerimônia. Ferramentas antigas adoravam isso. Usuários também. Segurança, nem tanto. No Wayland, uma aplicação não deve simplesmente ler a tela inteira sem consentimento. Por isso o caminho moderno passa por portals e PipeWire: a aplicação pede permissão, o compositor decide o que pode ser compartilhado, e o stream é entregue de forma controlada. A documentação do &lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.ScreenCast.html&quot;&gt;ScreenCast portal&lt;/a&gt;, do &lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Screenshot.html&quot;&gt;Screenshot portal&lt;/a&gt; e do &lt;a href=&quot;https://docs.pipewire.org/page_portal.html&quot;&gt;PipeWire portal access control&lt;/a&gt; mostra essa mudança de filosofia.&lt;/p&gt;
&lt;p&gt;Isso é melhor arquiteturalmente. Também é mais chato. E aqui mora boa parte da briga.&lt;/p&gt;
&lt;p&gt;No X11, muitas ferramentas funcionavam porque não havia isolamento forte. No Wayland, algumas deixam de funcionar porque agora precisam pedir permissão, usar protocolo novo, depender do compositor ou esperar um portal amadurecer. Para o usuário, isso parece regressão. Para quem está desenhando o sistema, é uma correção de um erro antigo. Os dois lados têm razão em partes diferentes da frase.&lt;/p&gt;
&lt;h2&gt;Wayland: menos servidor mágico, mais compositor responsável&lt;/h2&gt;
&lt;p&gt;O Wayland muda o centro de gravidade. Em vez de um servidor X no meio, um window manager separado e um compositor externo tentando coordenar a bagunça, o compositor Wayland é o display server. Ele recebe input, sabe a geometria real da cena, decide qual superfície está onde, aplica transformações, compõe os buffers e fala com DRM/KMS para apresentar o resultado na tela.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://wayland.freedesktop.org/docs/book/Architecture.html&quot;&gt;arquitetura oficial do Wayland&lt;/a&gt; explica essa diferença seguindo o caminho de um evento de input até a tela. No X, o kernel envia o evento ao servidor X, o X decide para qual cliente mandar, o cliente redesenha, o servidor comunica dano ao compositor, o compositor recompõe e ainda precisa voltar ao X para apresentar. No Wayland, o kernel envia o evento ao compositor, o compositor sabe qual superfície deve receber o evento, o cliente renderiza em seu buffer e avisa o compositor, que então compõe e agenda o page flip usando KMS.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/x11-xorg-wayland-desktop-linux/x11-wayland-architecture.svg&quot; alt=&quot;Comparação arquitetural entre X11 e Wayland, mostrando o servidor X como intermediário e o compositor Wayland como display server&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A mudança central é tirar o servidor X do caminho crítico e colocar o compositor como árbitro de input, superfície e apresentação.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Isso remove etapas. Mais importante: remove ambiguidade de responsabilidade.&lt;/p&gt;
&lt;p&gt;O cliente Wayland não pede ao servidor para desenhar botões. Ele desenha seu conteúdo em buffers próprios, usando Cairo, OpenGL, Vulkan, software rendering, GTK, Qt ou o que for apropriado, e entrega esses buffers ao compositor. O compositor não precisa saber como a aplicação desenhou. Ele precisa saber como compor as superfícies.&lt;/p&gt;
&lt;p&gt;Na prática moderna, isso envolve Mesa, EGL, Vulkan, GBM, dma-buf, DRM, KMS, libinput e protocolos Wayland complementares. A documentação oficial menciona troca de buffers via dma-buf e integração com EGL/Vulkan no caminho de renderização acelerada. Ou seja: Wayland não é “um servidor gráfico pequeno que substitui tudo”. Wayland é um protocolo menor porque várias responsabilidades foram para os lugares onde já deveriam estar: kernel, bibliotecas gráficas, toolkits e compositores.&lt;/p&gt;
&lt;p&gt;Isso é bonito no desenho. No dia a dia, significa que cada compositor precisa implementar uma parte relevante da experiência. Mutter, KWin, wlroots, Weston e compositores independentes não são skins diferentes em cima de um servidor universal. Eles são implementações reais do display server. É por isso que “funciona no GNOME” não significa automaticamente “funciona no Sway”, e “funciona no KDE” não significa automaticamente “funciona no Hyprland”. O protocolo comum existe, mas a política e as extensões importam muito.&lt;/p&gt;
&lt;h2&gt;Mutter, KWin, wlroots e Weston: Wayland não é um bloco único&lt;/h2&gt;
&lt;p&gt;O Weston é a implementação de referência do Wayland. Ele é importante para demonstrar o protocolo, testar ideias e servir como base conceitual, mas não é o desktop que a maioria das pessoas usa. A documentação do &lt;a href=&quot;https://wayland.pages.freedesktop.org/weston/&quot;&gt;Weston&lt;/a&gt; deixa claro esse papel de compositor de referência e ambiente de desenvolvimento.&lt;/p&gt;
&lt;p&gt;No GNOME, quem faz o trabalho pesado é o Mutter. Ele começou como window manager e compositor no mundo X11, mas evoluiu para ser o compositor Wayland do GNOME Shell. O projeto tem documentação própria em &lt;a href=&quot;https://mutter.gnome.org/&quot;&gt;mutter.gnome.org&lt;/a&gt; e código no GitLab do GNOME. Quando alguém diz “Wayland no GNOME”, na prática está falando do comportamento do Mutter, do GNOME Shell, do GTK, dos portals e das decisões do projeto GNOME.&lt;/p&gt;
&lt;p&gt;No KDE Plasma, o papel equivalente é do KWin. Ele funciona como window manager no X11 e compositor no Wayland, e é uma das peças centrais do Plasma. O código fica no &lt;a href=&quot;https://invent.kde.org/plasma/kwin&quot;&gt;repositório do KWin&lt;/a&gt;. O KDE costuma expor mais opções ao usuário e historicamente tem uma postura diferente do GNOME em relação a configuração, protocolos e compatibilidade. Isso aparece na experiência Wayland também.&lt;/p&gt;
&lt;p&gt;Já o wlroots é outra história. Ele não é um desktop environment, mas uma biblioteca modular para construir compositores Wayland. Sway, river e vários compositores independentes se apoiaram ou se apoiam nesse tipo de fundação. A documentação do &lt;a href=&quot;https://wlroots.pages.freedesktop.org/wlroots/&quot;&gt;wlroots&lt;/a&gt; mostra bem a quantidade de peças envolvidas: backends DRM, libinput, renderização, output management, screencopy, xdg-shell, xwayland, tablet, pointer constraints, tearing control e assim por diante.&lt;/p&gt;
&lt;p&gt;Esse ponto é importante porque muita discussão sobre Wayland erra ao tratar o sistema como se fosse uma implementação única. Wayland é protocolo e ecossistema. Mutter, KWin e wlroots tomam decisões diferentes. Às vezes a limitação está no protocolo. Às vezes está no compositor. Às vezes está no toolkit. Às vezes está no aplicativo. Às vezes está na NVIDIA. E às vezes está no usuário tentando usar uma ferramenta de 2009 como se o modelo de segurança de 2026 fosse pedir desculpa.&lt;/p&gt;
&lt;h2&gt;XWayland: a ponte que segura o mundo antigo&lt;/h2&gt;
&lt;p&gt;A transição para Wayland só é minimamente possível porque existe o XWayland. Ele é um servidor X que roda como cliente Wayland. Aplicações X11 continuam falando X11, mas em vez de controlar diretamente uma sessão X tradicional, elas são apresentadas como superfícies dentro do compositor Wayland.&lt;/p&gt;
&lt;p&gt;Isso resolve uma parte enorme da compatibilidade. Aplicações antigas, toolkits que ainda usam X11, jogos, softwares proprietários e ferramentas que nunca foram portadas podem continuar abrindo. Sem XWayland, Wayland teria sido uma tese acadêmica bonita e uma migração praticamente inviável para o desktop real.&lt;/p&gt;
&lt;p&gt;Mas XWayland tem limites. Ele não transforma aplicações X11 em aplicações Wayland nativas. Ele preserva compatibilidade, mas não dá a elas acesso irrestrito ao compositor Wayland. Algumas integrações globais, automações, captura de input, inspeção de janelas e comportamentos específicos do X11 continuam limitados ou dependem de protocolos adicionais.&lt;/p&gt;
&lt;p&gt;Esse é o ponto que muita gente confunde: XWayland é uma camada de compatibilidade, não uma máquina do tempo. Ele é excelente para rodar aplicações antigas. Ele não existe para manter vivo todo modelo de poder global do X11 dentro de uma sessão Wayland.&lt;/p&gt;
&lt;h2&gt;Segurança: a vantagem mais desconfortável do Wayland&lt;/h2&gt;
&lt;p&gt;O argumento de segurança do Wayland é simples: uma aplicação gráfica não deve poder espionar todas as outras por padrão.&lt;/p&gt;
&lt;p&gt;No X11, o modelo tradicional permite uma convivência muito íntima entre clientes. Essa intimidade viabiliza ferramentas úteis, mas também cria uma superfície ruim para isolamento. Keyloggers, captura de tela, leitura de clipboard, enumeração de janelas e automação global são muito mais fáceis quando a sessão inteira compartilha um modelo permissivo.&lt;/p&gt;
&lt;p&gt;No Wayland, o compositor é o árbitro. Um cliente não recebe input que não é dele. Não captura a tela inteira sem passar pelo compositor ou por um portal. Não injeta input global como se fosse dono do desktop. Isso melhora o isolamento entre aplicações, especialmente em um mundo com Flatpak, sandboxing e aplicativos baixados de fontes variadas.&lt;/p&gt;
&lt;p&gt;Só que segurança quase sempre cobra aluguel em conveniência. Ferramentas antigas de screenshot, color picker, macro, automação, compartilhamento de tela e acesso remoto quebraram ou precisaram ser reescritas. O caminho moderno envolve &lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Screenshot.html&quot;&gt;portals para screenshot&lt;/a&gt;, &lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.ScreenCast.html&quot;&gt;portals para screencast&lt;/a&gt;, &lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.GlobalShortcuts.html&quot;&gt;portals para atalhos globais&lt;/a&gt;, &lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.InputCapture.html&quot;&gt;portals para captura de input&lt;/a&gt; e integração com PipeWire.&lt;/p&gt;
&lt;p&gt;Isso não é regressão acidental. É a consequência de parar de tratar qualquer aplicação da sessão como confiável por definição.&lt;/p&gt;
&lt;h2&gt;Desempenho, latência e tearing: sem milagre, mas com arquitetura melhor&lt;/h2&gt;
&lt;p&gt;Um erro comum é vender Wayland como “mais rápido” de forma genérica. Não é tão simples. Dependendo do compositor, driver, toolkit, jogo e hardware, o resultado pode variar. Mas a arquitetura do Wayland permite reduzir etapas e evitar alguns caminhos desnecessários que existem no X moderno.&lt;/p&gt;
&lt;p&gt;A documentação do Wayland destaca justamente isso: no X com compositor, o servidor pode virar um intermediário extra entre aplicação, compositor e hardware. No Wayland, o compositor recebe buffers dos clientes e apresenta usando KMS, com menos idas e vindas. Isso pode ajudar em latência e previsibilidade, mas não transforma automaticamente todo desktop em uma nave.&lt;/p&gt;
&lt;p&gt;Jogos são um caso interessante. Por muito tempo, jogadores reclamaram de latência, tearing, VRR, suporte de driver, XWayland e comportamento diferente entre compositores. Algumas dessas críticas eram bem justas. O suporte melhorou muito, especialmente com trabalho em XWayland, Mesa, drivers NVIDIA mais recentes, protocolos de tearing control, VRR e melhorias em KWin e Mutter. Mas jogos continuam sendo uma área onde detalhes importam: fullscreen, frame pacing, captura de mouse, HDR, VRR, múltiplos monitores e overlays não são brinquedos simples.&lt;/p&gt;
&lt;p&gt;A parte honesta é: X11 ainda pode parecer mais previsível para alguns setups específicos, principalmente porque tudo já foi remendado durante décadas. A parte igualmente honesta é: muitos recursos modernos estão sendo feitos primeiro, melhor ou exclusivamente pensando em Wayland.&lt;/p&gt;
&lt;h2&gt;Multi-monitor, HiDPI e fractional scaling: onde a conta chega&lt;/h2&gt;
&lt;p&gt;Se tem um lugar onde a arquitetura pesa, é em monitor.&lt;/p&gt;
&lt;p&gt;No X11, a sessão tende a operar sobre uma ideia global de tela. Extensões como RandR melhoraram muito o gerenciamento de outputs, rotação, resolução e hotplug, mas o modelo continua carregando a herança de um espaço global onde várias coisas assumem propriedades uniformes demais.&lt;/p&gt;
&lt;p&gt;No Wayland, o compositor conhece os outputs e controla a composição final. Isso permite lidar melhor com monitores diferentes, escalas diferentes, transformações e densidades distintas. Não significa que fractional scaling seja perfeito. No GNOME, KDE e wlroots, houve e ainda há diferenças de implementação, bugs, escolhas de qualidade versus performance e detalhes em aplicações XWayland. Mas o modelo arquitetural favorece esse tipo de problema moderno.&lt;/p&gt;
&lt;p&gt;Em XWayland, por exemplo, aplicações X11 podem sofrer com escala porque continuam presas ao mundo X. Uma aplicação Wayland nativa pode negociar escala e buffers de forma mais adequada com o compositor. Uma aplicação XWayland pode precisar ser escalada pelo compositor, pelo toolkit ou por alguma combinação que nem sempre fica nítida. É daí que nascem muitos relatos de “no Wayland ficou borrado” ou “no Xorg ficava melhor”. Às vezes é culpa do Wayland. Às vezes é culpa da aplicação ainda não ser Wayland nativa. Às vezes é o preço de manter compatibilidade com o passado.&lt;/p&gt;
&lt;h2&gt;NVIDIA: o vilão conveniente, mas não o único&lt;/h2&gt;
&lt;p&gt;Durante anos, NVIDIA foi uma das maiores fontes de atrito na adoção do Wayland. O ecossistema Linux gráfico livre se desenvolveu muito em torno de Mesa, DRM, KMS, GBM e drivers abertos. A NVIDIA, com driver proprietário e escolhas diferentes, incluindo EGLStreams por um período, tornou tudo mais difícil.&lt;/p&gt;
&lt;p&gt;Isso mudou bastante. Drivers recentes da NVIDIA melhoraram o suporte a GBM e Wayland, e distribuições passaram a confiar mais nesse caminho. A própria página de mudança do Fedora KDE para Plasma 6 cita que drivers NVIDIA recentes suportam GBM para Wayland e que o Fedora KDE se sentia confortável para remover a sessão X11 no Plasma 6, mantendo XWayland para aplicações X11 (&lt;a href=&quot;https://fedoraproject.org/wiki/Changes/KDE_Plasma_6&quot;&gt;Fedora KDE Plasma 6&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Mas é bom evitar o clichê preguiçoso de jogar tudo na NVIDIA. Há problemas que são do protocolo. Há problemas que são do compositor. Há problemas que são do toolkit. Há problemas que são de aplicações antigas. E há problemas que são do simples fato de que o Linux desktop é uma federação de projetos independentes tentando parecer um produto coeso.&lt;/p&gt;
&lt;p&gt;Spoiler: às vezes não parece.&lt;/p&gt;
&lt;h2&gt;&quot;Por que tanta resistência ao Wayland?&quot;&lt;/h2&gt;
&lt;p&gt;A resistência ao Wayland não é só birra. Tem gente que depende de fluxos que o X11 fazia muito bem.&lt;/p&gt;
&lt;p&gt;Acesso remoto via X11 forwarding é um exemplo óbvio. O Wayland não tenta replicar a transparência de rede do X11 no protocolo base. O modelo moderno prefere outros caminhos: RDP, VNC, PipeWire, portals, compositor-specific remoting, aplicações web, SSH com forwarding de protocolo de aplicação, ou simplesmente rodar a aplicação onde ela está. Para alguns casos, isso é melhor. Para outros, é pior. Se você dependia de &lt;code&gt;ssh -X&lt;/code&gt; como parte central do fluxo, Wayland parece uma perda real.&lt;/p&gt;
&lt;p&gt;Automação também sofreu. No X11, ferramentas podiam observar janelas, capturar teclas, mover mouse, injetar eventos e manipular a sessão com liberdade. No Wayland, isso precisa passar por protocolos controlados, portals ou APIs específicas do compositor. Para acessibilidade e automação legítima, isso exigiu reconstruir infraestrutura. Para ferramentas rápidas e sujas, isso quebrou a festa.&lt;/p&gt;
&lt;p&gt;Screen sharing foi outra dor famosa. Durante bastante tempo, compartilhar tela em Wayland era uma experiência variável: funcionava no GNOME, quebrava no browser, dependia de PipeWire, dependia do portal, dependia do Flatpak, dependia do compositor, dependia de alguma flag esquecida. Hoje está muito melhor, mas a cicatriz comunitária ficou. Quando uma pessoa perde uma call porque o compartilhamento de tela não funciona, ela não quer ouvir palestra sobre arquitetura correta. Ela quer que a porcaria da tela apareça.&lt;/p&gt;
&lt;p&gt;Acessibilidade também é um ponto sensível. Leitores de tela, ampliação, input alternativo, automação assistiva e inspeção de UI precisam de integração profunda. O X11 permitia várias abordagens por ser permissivo. Wayland exige caminhos explícitos e seguros. A direção é correta, mas a transição não é grátis.&lt;/p&gt;
&lt;h2&gt;Por que os defensores do Wayland dizem que ele é inevitável&lt;/h2&gt;
&lt;p&gt;O argumento pró-Wayland é que o X11 já cumpriu seu papel. Não porque seja inútil, mas porque virou o lugar errado para resolver problemas modernos.&lt;/p&gt;
&lt;p&gt;A própria documentação do Wayland resume a tese: ao longo do tempo, funcionalidades que ficavam no X foram movidas para bibliotecas, toolkits e kernel; o que sobra para o servidor gráfico moderno é apresentar superfícies e arbitrar input. O compositor já precisa entender a cena final, então faz sentido ele ser o display server (&lt;a href=&quot;https://wayland.freedesktop.org/docs/book/Architecture.html&quot;&gt;Wayland Architecture&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Distribuições e desktops estão seguindo essa leitura. O Fedora tornou Wayland padrão no GNOME desde o Fedora 25, com fallback para Xorg quando necessário (&lt;a href=&quot;https://fedoraproject.org/wiki/Changes/WaylandByDefault&quot;&gt;Wayland By Default&lt;/a&gt;). O Fedora KDE decidiu ir além no Plasma 6 e não oferecer sessão X11, mantendo XWayland para compatibilidade de aplicações (&lt;a href=&quot;https://fedoraproject.org/wiki/Changes/KDE_Plasma_6&quot;&gt;Fedora KDE Plasma 6&lt;/a&gt;). O Fedora também documentou a remoção dos pacotes de sessão X11 do GNOME como parte do alinhamento com o esforço upstream de aposentadoria da sessão X11 (&lt;a href=&quot;https://fedoraproject.org/wiki/Changes/WaylandOnlyGNOME&quot;&gt;Wayland-only GNOME&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;KDE Plasma 6 tornou Wayland a sessão padrão. GNOME empurrou cada vez mais o caminho Wayland. wlroots consolidou um ecossistema inteiro de compositores independentes. PipeWire e portals amadureceram. XWayland segurou compatibilidade. O resultado é que Wayland deixou de ser “o futuro” e virou “o presente, com bugs de presente”.&lt;/p&gt;
&lt;p&gt;A frase parece piada, mas é a melhor descrição da transição. X11 é o passado ainda necessário. Wayland é o presente ainda irregular. O futuro é quando essa distinção parar de importar para a maioria dos usuários.&lt;/p&gt;
&lt;h2&gt;O que ainda falta&lt;/h2&gt;
&lt;p&gt;Wayland já é perfeitamente usável para muita gente. Eu diria mais: em vários setups, é a melhor opção hoje. Mas “usável para muita gente” não é o mesmo que “substitui X11 em todos os casos”.&lt;/p&gt;
&lt;p&gt;Ainda existem áreas que merecem atenção.&lt;/p&gt;
&lt;p&gt;A primeira é padronização de protocolos entre compositores. GNOME, KDE e wlroots nem sempre implementam as mesmas extensões, ou implementam em ritmos diferentes. Isso afeta atalhos globais, captura de tela, captura de input, gerenciamento de janelas, protocolos de layer shell, virtual keyboard, remote desktop e recursos avançados. O ecossistema melhora, mas a fragmentação existe.&lt;/p&gt;
&lt;p&gt;A segunda é acessibilidade. Um desktop moderno precisa permitir automação assistiva sem abrir de novo o buraco de segurança do X11. Isso exige APIs formais, permissões, integração com toolkits e colaboração entre compositores. Não dá para tratar acessibilidade como “depois a comunidade resolve”.&lt;/p&gt;
&lt;p&gt;A terceira é automação legítima. Existem casos reais para macros, ferramentas de produtividade, key remapping avançado, streaming, KVM via software, controle remoto e testes automatizados de UI. Wayland precisa oferecer caminhos seguros para isso, e não apenas dizer “no X11 era inseguro”. Era mesmo. Mas o usuário ainda precisa trabalhar.&lt;/p&gt;
&lt;p&gt;A quarta é compatibilidade com aplicações antigas e proprietárias. XWayland ajuda muito, mas não resolve tudo. Enquanto existirem softwares que dependem de comportamentos específicos do X11, algumas pessoas vão manter sessões Xorg por necessidade, não nostalgia.&lt;/p&gt;
&lt;p&gt;A quinta é consistência de experiência. Quando uma feature funciona no GNOME, falha no KDE e depende de plugin no compositor wlroots da semana, o usuário não pensa “que diversidade arquitetural fascinante”. Ele pensa outra coisa, geralmente com mais palavrões.&lt;/p&gt;
&lt;h2&gt;X11 merece respeito, não culto&lt;/h2&gt;
&lt;p&gt;O X11 não é lixo. Essa é a crítica fácil de quem confunde modernização com ingratidão. O X11 carregou o Unix gráfico, o Linux desktop, ambientes acadêmicos, estações de trabalho, aplicações científicas, desktops inteiros, toolkits e gerações de usuários por décadas. Poucas peças de software sobrevivem tanto tempo sendo irrelevantes.&lt;/p&gt;
&lt;p&gt;Mas respeito não significa culto.&lt;/p&gt;
&lt;p&gt;O X11 foi excelente para um mundo onde rede local, estações Unix e separação entre mecanismo e política eram o centro da história. O desktop atual tem outros problemas: isolamento, composição obrigatória, GPUs modernas, múltiplos monitores heterogêneos, sandboxing, captura de tela consentida, aplicativos empacotados, segurança entre clientes, jogos, touch, tablets, HDR, VRR e acessibilidade integrada.&lt;/p&gt;
&lt;p&gt;Dá para continuar remendando Xorg? Em alguns casos, sim. E provavelmente ele ainda vai existir por muito tempo, nem que seja via XWayland, sistemas legados, desktops menores ou usuários com necessidades específicas. Mas como caminho principal do desktop Linux, o X11 virou uma base cara demais para sustentar.&lt;/p&gt;
&lt;p&gt;Wayland não é perfeito. Às vezes é irritante. Às vezes uma ferramenta antiga quebra e a explicação correta parece deboche. Às vezes o compositor que você escolheu implementa metade do que você precisa e chama o resto de “fora de escopo”. Às vezes o futuro chega com cara de issue aberta.&lt;/p&gt;
&lt;p&gt;Mas a direção faz sentido.&lt;/p&gt;
&lt;p&gt;A transição do X11 para Wayland não é a troca de um protocolo por outro. É a troca de uma filosofia: sair de uma sessão gráfica permissiva, global e historicamente remendada para um modelo onde o compositor é o centro, clientes são mais isolados, buffers são compartilhados de forma explícita e permissões passam a existir de verdade.&lt;/p&gt;
&lt;p&gt;No fundo, o drama é simples: o X11 funcionava porque confiava demais. O Wayland irrita porque desconfia mais.&lt;/p&gt;
&lt;p&gt;E, para um desktop moderno, talvez a parte irritante seja justamente a parte certa.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Git bom não começa no commit</title><link>https://blog.kristyan.dev/posts/git-bom-n%C3%A3o-come%C3%A7a-no-commit</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/git-bom-n%C3%A3o-come%C3%A7a-no-commit</guid><description>Um guia prático sobre como eu organizo versionamento com Git, GitHub e GitHub CLI, saindo do automático add/commit/push e tratando cada mudança como uma unidade planejada, validada e pronta para release.</description><pubDate>Mon, 15 Jun 2026 02:00:00 GMT</pubDate><content:encoded>&lt;p&gt;O pior jeito de aprender Git é decorar &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;commit&lt;/code&gt; e &lt;code&gt;push&lt;/code&gt; como se isso fosse um fluxo de trabalho.&lt;/p&gt;
&lt;p&gt;Funciona? Funciona. Do mesmo jeito que jogar tudo em uma pasta chamada &lt;code&gt;final-agora-vai-2&lt;/code&gt; também funciona até alguém precisar entender o que aconteceu três semanas depois.&lt;/p&gt;
&lt;p&gt;Git não é só uma máquina de salvar código. Git é uma ferramenta de rastreabilidade. GitHub não é só um lugar para empurrar branch. GitHub é onde o trabalho ganha contexto: issue, milestone, histórico, release, discussão e validação.&lt;/p&gt;
&lt;p&gt;O meu fluxo tenta resolver um problema simples: cada mudança precisa ser planejada antes, isolada durante, validada depois e rastreável no futuro. Parece burocracia até você precisar descobrir por que uma alteração entrou, qual issue ela resolvia, em qual release saiu e se alguém validou alguma coisa antes do merge.&lt;/p&gt;
&lt;p&gt;Aí deixa de ser burocracia. Vira sobrevivência.&lt;/p&gt;
&lt;h2&gt;O commit não é o começo do trabalho&lt;/h2&gt;
&lt;p&gt;O erro mais comum em projetos pequenos é tratar o commit como ponto de partida.&lt;/p&gt;
&lt;p&gt;A pessoa abre o editor, muda arquivos, testa qualquer coisa no olho, escreve um commit meio genérico e manda para o remoto. Depois cria uma issue, talvez. Ou nem cria. Quando muito, aparece um &lt;code&gt;fix stuff&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;changes&lt;/code&gt;, aquele tipo de commit que não informa nada além do fato triste de que alguém encostou no teclado.&lt;/p&gt;
&lt;p&gt;No meu fluxo, o commit é consequência. Antes dele existe uma unidade de trabalho.&lt;/p&gt;
&lt;p&gt;Essa unidade começa em uma Issue do GitHub. A issue define o escopo. O milestone define o alvo de release. A branch local isola a implementação. O commit registra a mudança. A validação decide se ela pode entrar. O merge coloca a mudança na integração. A release só acontece quando o conjunto planejado ficou pronto.&lt;/p&gt;
&lt;p&gt;A ordem importa.&lt;/p&gt;
&lt;p&gt;Sem isso, o repositório vira um diário de bordo escrito depois do naufrágio.&lt;/p&gt;
&lt;h2&gt;Antes dos comandos: branch, working tree e index&lt;/h2&gt;
&lt;p&gt;Para esse fluxo fazer sentido, vale alinhar três conceitos que muita gente passa por cima porque o tutorial tinha pressa de chegar no &lt;code&gt;git push&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Uma branch é basicamente um nome apontando para uma linha de desenvolvimento. A própria &lt;a href=&quot;https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell&quot;&gt;documentação do Pro Git&lt;/a&gt; descreve branches como ponteiros leves e móveis para commits, o que explica por que criar branch no Git é barato e rápido: você não está copiando o projeto inteiro, está criando uma nova referência para continuar o histórico dali.&lt;/p&gt;
&lt;p&gt;O working tree é a cópia dos arquivos que você está editando no disco. É o diretório do projeto do jeito que ele está agora, com arquivos modificados, criados ou removidos.&lt;/p&gt;
&lt;p&gt;O index, também chamado de staging area, é a área intermediária entre o que você editou e o que vai entrar no próximo commit. Quando você roda &lt;code&gt;git add&lt;/code&gt;, você não está “salvando no Git” ainda. Você está dizendo: “esta parte aqui deve entrar no próximo snapshot”.&lt;/p&gt;
&lt;p&gt;É por isso que eu gosto de começar olhando o estado do repositório:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git status
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;a href=&quot;https://git-scm.com/docs/git-status&quot;&gt;documentação do &lt;code&gt;git status&lt;/code&gt;&lt;/a&gt; é bem direta: ele mostra diferenças entre &lt;code&gt;HEAD&lt;/code&gt;, index e working tree, além de arquivos ainda não rastreados. Em português menos manual: ele mostra o que já está preparado para commit, o que foi alterado mas ainda não está preparado e o que o Git nem está rastreando.&lt;/p&gt;
&lt;p&gt;Esse comando é simples, mas evita muita besteira. Antes de criar branch, antes de rebase, antes de merge, antes de qualquer cirurgia: &lt;code&gt;git status&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;O modelo mental: main, dev e stage&lt;/h2&gt;
&lt;p&gt;Eu uso duas branches longas:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;main
dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;main&lt;/code&gt; é a branch estável. Ela não é playground, não é lugar de teste e não é onde eu implemento coisa “rapidinho”. Código só chega em &lt;code&gt;main&lt;/code&gt; durante release.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dev&lt;/code&gt; é a branch de integração. É onde o trabalho concluído se junta antes de virar release. Ela pode andar mais rápido que &lt;code&gt;main&lt;/code&gt;, mas não pode virar lixão. &lt;code&gt;dev&lt;/code&gt; precisa continuar buildável, testável e minimamente confiável.&lt;/p&gt;
&lt;p&gt;Para implementação, eu uso branches locais com prefixo &lt;code&gt;stage/&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;stage/&amp;lt;issue-number&amp;gt;-&amp;lt;short-english-slug&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exemplos:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;stage/12-configure-fastify
stage/18-add-terminal-renderer
stage/21-fix-ascii-width-validation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O detalhe importante: essas branches são locais.&lt;/p&gt;
&lt;p&gt;Eu não empurro (&quot;push&quot; - parecia melhor na minha cabeça) &lt;code&gt;stage/*&lt;/code&gt; para o GitHub. Para o meu fluxo pessoal, elas são apenas uma área de trabalho isolada. O que vai para o remoto durante o desenvolvimento regular é &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Em times, dá para adaptar isso para PRs, revisão obrigatória e branch remota. Mas o princípio continua o mesmo: uma mudança, uma unidade de trabalho, um escopo claro. O problema não é usar PR. O problema é transformar PR em depósito de “aproveitei e mexi nisso também”.&lt;/p&gt;
&lt;p&gt;Esse “aproveitei” é uma fábrica de histórico ruim.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;git switch&lt;/code&gt; não é só frescura nova&lt;/h2&gt;
&lt;p&gt;Nos comandos do meu fluxo, eu uso &lt;code&gt;git switch&lt;/code&gt; em vez de &lt;code&gt;git checkout&lt;/code&gt; para mudar de branch:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;a href=&quot;https://git-scm.com/docs/git-switch&quot;&gt;documentação do &lt;code&gt;git switch&lt;/code&gt;&lt;/a&gt; diz que ele muda para uma branch específica e atualiza o working tree e o index para corresponder a ela. É exatamente isso que eu quero expressar quando escrevo o comando: trocar de branch.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://git-scm.com/docs/git-checkout&quot;&gt;&lt;code&gt;git checkout&lt;/code&gt;&lt;/a&gt; também consegue trocar de branch, e a documentação dele ainda descreve esse comportamento. O problema é que &lt;code&gt;checkout&lt;/code&gt; virou um canivete suíço histórico: ele serve para trocar branch, restaurar arquivo, lidar com pathspec, detached HEAD e outras coisas que fazem sentido para o Git, mas não necessariamente para a cabeça de quem só quer ler um fluxo de trabalho.&lt;/p&gt;
&lt;p&gt;Por isso eu prefiro:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;em vez de:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git checkout dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E para criar uma branch nova já entrando nela:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch -c stage/12-configure-fastify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso substitui o velho:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git checkout -b stage/12-configure-fastify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Não é que &lt;code&gt;checkout&lt;/code&gt; esteja proibido. Ele ainda existe, ainda funciona e muita documentação antiga usa. Mas &lt;code&gt;switch&lt;/code&gt; comunica melhor a intenção. Quando o comando é sobre branch, uso &lt;code&gt;switch&lt;/code&gt;. Quando a intenção é restaurar arquivos, faz mais sentido olhar para &lt;a href=&quot;https://git-scm.com/docs/git-restore&quot;&gt;&lt;code&gt;git restore&lt;/code&gt;&lt;/a&gt;, que foi separado justamente para esse tipo de operação.&lt;/p&gt;
&lt;p&gt;Ferramenta explícita reduz confusão. E confusão em Git costuma virar meia hora olhando para o terminal com cara de quem mexeu em coisa que não devia.&lt;/p&gt;
&lt;h2&gt;O GitHub CLI entra para tirar atrito&lt;/h2&gt;
&lt;p&gt;Eu gosto de usar o GitHub CLI porque ele tira uma parte chata do fluxo: ficar alternando entre terminal, navegador, formulário, milestone, labels e release.&lt;/p&gt;
&lt;p&gt;A interface web é boa, mas para trabalho repetível o terminal ganha. O &lt;code&gt;gh&lt;/code&gt; deixa issue, milestone e release mais próximos do código. E quando essas etapas ficam mais próximas, a chance de você pular alguma diminui.&lt;/p&gt;
&lt;p&gt;Antes de começar, vale garantir que o CLI está autenticado:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh auth status
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Também gosto de conferir o repositório atual:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh repo view
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Não é glamour. É só o equivalente técnico de olhar para os dois lados antes de atravessar a rua.&lt;/p&gt;
&lt;h2&gt;Milestone não é enfeite de Kanban&lt;/h2&gt;
&lt;p&gt;Milestone é uma promessa de release.&lt;/p&gt;
&lt;p&gt;Não no sentido corporativo de promessa bonita que ninguém cumpre, mas no sentido prático: “este conjunto de issues forma a versão &lt;code&gt;v0.1.0&lt;/code&gt;”.&lt;/p&gt;
&lt;p&gt;Eu uso nomes no formato:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;v0.1.0
v0.2.0
v1.0.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para criar um milestone pelo GitHub CLI, uso a API:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh api repos/{owner}/{repo}/milestones \
  -f title=&quot;v0.1.0&quot; \
  -f description=&quot;Initial MVP release&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O &lt;code&gt;gh api&lt;/code&gt; é o comando do GitHub CLI para fazer chamadas à API do GitHub direto pelo terminal. A &lt;a href=&quot;https://cli.github.com/manual/gh_api&quot;&gt;documentação do &lt;code&gt;gh api&lt;/code&gt;&lt;/a&gt; mostra o uso de campos com &lt;code&gt;-f&lt;/code&gt;/&lt;code&gt;--raw-field&lt;/code&gt; e endpoints no formato &lt;code&gt;repos/{owner}/{repo}/...&lt;/code&gt;, o que encaixa bem para criar milestones quando não há um comando dedicado tão confortável quanto &lt;code&gt;gh issue create&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O milestone precisa ter uma descrição minimamente decente. Não precisa virar documento acadêmico, mas precisa explicar o objetivo daquela release. “Initial MVP release” já é melhor que nada. “Stuff” não é descrição, é um pedido de socorro.&lt;/p&gt;
&lt;p&gt;Antes de implementar qualquer coisa, a pergunta é:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;essa mudança pertence a qual release?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se a resposta for “não sei”, provavelmente você ainda não planejou o suficiente.&lt;/p&gt;
&lt;h2&gt;Issue antes do código&lt;/h2&gt;
&lt;p&gt;Toda mudança começa em uma issue.&lt;/p&gt;
&lt;p&gt;Feature, correção, refatoração, documentação, ajuste interno, organização de repositório: tudo precisa ter uma unidade rastreável. Não porque o GitHub precisa estar feliz, mas porque o futuro você precisa entender por que aquilo existe.&lt;/p&gt;
&lt;p&gt;Eu separo os tipos em três categorias:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;task
enhancement
bug
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Uso &lt;code&gt;task&lt;/code&gt; para manutenção, documentação, setup, organização e refatorações internas.&lt;/p&gt;
&lt;p&gt;Uso &lt;code&gt;enhancement&lt;/code&gt; para melhoria de produto, comportamento novo ou capacidade visível para quem usa o projeto.&lt;/p&gt;
&lt;p&gt;Uso &lt;code&gt;bug&lt;/code&gt; para comportamento incorreto, regressão, fluxo quebrado ou saída inválida.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://cli.github.com/manual/gh_issue_create&quot;&gt;GitHub CLI permite criar issues&lt;/a&gt; direto pelo terminal, adicionando labels por nome, milestone por nome e template por arquivo de template configurado no repositório. É aqui que o fluxo começa a ficar menos “vou lembrar de organizar depois” e mais “a organização já nasce junto com a tarefa”.&lt;/p&gt;
&lt;p&gt;Exemplo de issue para tarefa:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh issue create \
  --template task.yml \
  --title &quot;task: configure initial project structure&quot; \
  --label task \
  --milestone &quot;v0.1.0&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exemplo de melhoria:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh issue create \
  --template enhancement.yml \
  --title &quot;enhancement: add markdown readme generation endpoint&quot; \
  --label enhancement \
  --milestone &quot;v0.1.0&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exemplo de bug:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh issue create \
  --template bug.yml \
  --title &quot;bug: fix ascii rendering for invalid width&quot; \
  --label bug \
  --milestone &quot;v0.1.0&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se o repositório estiver usando Issue Types do GitHub, também dá para usar &lt;code&gt;--type&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh issue create \
  --template bug.yml \
  --title &quot;bug: fix ascii rendering for invalid width&quot; \
  --type bug \
  --label bug \
  --milestone &quot;v0.1.0&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Eu ainda manteria label mesmo usando type em alguns casos, porque label continua sendo útil para filtros, automações e leitura rápida. Mas isso depende do repositório.&lt;/p&gt;
&lt;p&gt;O ponto é: issue solta, sem template, sem milestone e sem tipo, é quase sempre dívida organizacional disfarçada de agilidade.&lt;/p&gt;
&lt;h2&gt;Criando a branch de trabalho&lt;/h2&gt;
&lt;p&gt;Com a issue criada, a implementação começa a partir de &lt;code&gt;dev&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch dev
git pull origin dev
git switch -c stage/12-configure-fastify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aqui tem três movimentos.&lt;/p&gt;
&lt;p&gt;Primeiro, eu entro em &lt;code&gt;dev&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois, atualizo minha cópia local com o remoto:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git pull origin dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Por fim, crio uma branch local para aquela issue:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch -c stage/12-configure-fastify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O &lt;code&gt;-c&lt;/code&gt; cria a branch e já troca para ela. Essa parte é pequena, mas importante: eu não quero implementar em &lt;code&gt;dev&lt;/code&gt; sem querer. A branch local existe para conter a mudança e deixar claro qual issue está sendo trabalhada.&lt;/p&gt;
&lt;p&gt;A branch carrega o número da issue e um slug curto em inglês. Isso já resolve uma parte enorme da rastreabilidade.&lt;/p&gt;
&lt;p&gt;Quando eu vejo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;stage/12-configure-fastify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;eu sei três coisas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;existe uma issue &lt;code&gt;#12&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;o escopo é configurar Fastify;&lt;/li&gt;
&lt;li&gt;essa branch não deveria conter refatoração de tema, ajuste de README e troca de Dockerfile no mesmo pacote.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Branch boa não é só nome bonito. É contrato de escopo.&lt;/p&gt;
&lt;h2&gt;Commit não é poesia, é registro técnico&lt;/h2&gt;
&lt;p&gt;Eu uso commits em inglês e com formato rígido:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;[type]/[update-scope]: summary
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exemplos bons:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;chore/readme: update project setup instructions
feat/render: add terminal markdown renderer
fix/ascii: handle missing avatar image
docs/api: document query parameters
test/github: add github client tests
refactor/theme: extract theme registry
ci/docker: add docker build check
build/package: configure typescript output
perf/cache: reduce repeated github requests
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O tipo diz a natureza da mudança. O escopo diz onde ela mexe. O resumo diz o que aconteceu.&lt;/p&gt;
&lt;p&gt;O que eu evito:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;fix/api: fixes
chore/docs: update stuff
feat/app: changes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Também evito escopos genéricos:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;chore/update: summary
feat/update: summary
fix/update: summary
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E, neste fluxo, evito artefatos de Git/GitHub em português:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;chore/atualizacao: ...
feat/ajuste: ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O post está em português. O repositório, não necessariamente. Para comandos, issues, branch names, release notes e commits, eu prefiro inglês. É mais consistente com ferramentas, ecossistema, documentação e colaboração externa.&lt;/p&gt;
&lt;p&gt;E principalmente: evita aquele híbrido estranho em que metade do histórico parece documentação técnica e metade parece anotação pessoal.&lt;/p&gt;
&lt;h2&gt;Implementação tem limite&lt;/h2&gt;
&lt;p&gt;A regra mais difícil não é decorar comando. É não sair mexendo em coisa fora do escopo.&lt;/p&gt;
&lt;p&gt;Se a issue é:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;bug: fix ascii rendering for invalid width
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;a implementação não deveria também reorganizar o README, trocar dependência, renomear módulo, alterar tema e mexer no Docker.&lt;/p&gt;
&lt;p&gt;“Já que eu estava aqui” é uma das frases mais perigosas da engenharia de software.&lt;/p&gt;
&lt;p&gt;Cada mudança fora do escopo aumenta o custo de revisão, dificulta rollback, suja o histórico e transforma uma issue simples em um pacote misterioso.&lt;/p&gt;
&lt;p&gt;Quando uma nova necessidade aparece durante a implementação, eu prefiro criar outra issue. Pode parecer mais lento, mas é mais honesto. E histórico honesto vale muito quando algo quebra.&lt;/p&gt;
&lt;h2&gt;Validação antes do merge&lt;/h2&gt;
&lt;p&gt;Antes de juntar a branch local em &lt;code&gt;dev&lt;/code&gt;, eu valido.&lt;/p&gt;
&lt;p&gt;Em projetos Node.js ou TypeScript, meu fluxo esperado é:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm run lint
npm run typecheck
npm test
npm run build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se algum script não existe, eu não simplesmente ignoro. Primeiro olho o &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat package.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois decido se faz sentido criar o script ou documentar por que ele não existe.&lt;/p&gt;
&lt;p&gt;O que não dá é fingir que validação passou porque o comando nem existia. Isso é o equivalente técnico de desligar o alarme de incêndio para melhorar o clima do prédio.&lt;/p&gt;
&lt;p&gt;Validação não garante ausência de bug. Mas reduz a chance de mergear erro besta. E erro besta é o tipo de erro mais irritante, porque ele geralmente não precisava ter chegado longe.&lt;/p&gt;
&lt;h2&gt;Merge em dev&lt;/h2&gt;
&lt;p&gt;Depois de validar, volto para &lt;code&gt;dev&lt;/code&gt;, atualizo a branch e faço merge com &lt;code&gt;--no-ff&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch dev
git pull origin dev
git merge --no-ff stage/12-configure-fastify
git push origin dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Merge é o ato de integrar uma linha de desenvolvimento em outra. A &lt;a href=&quot;https://git-scm.com/docs/git-merge&quot;&gt;documentação do &lt;code&gt;git merge&lt;/code&gt;&lt;/a&gt; descreve o comando como o mecanismo usado para incorporar mudanças de outra branch ao histórico atual. Em português prático: eu estou dizendo para &lt;code&gt;dev&lt;/code&gt; receber o trabalho feito em &lt;code&gt;stage/12-configure-fastify&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Eu uso &lt;code&gt;--no-ff&lt;/code&gt; para preservar o ponto de integração. Sem entrar em aula longa de grafo: quando o Git consegue fazer um fast-forward, ele pode simplesmente mover o ponteiro da branch para frente, sem criar um commit de merge. Isso deixa o histórico mais linear, mas também pode esconder visualmente que aquele conjunto de commits entrou como uma unidade de trabalho.&lt;/p&gt;
&lt;p&gt;Com &lt;code&gt;--no-ff&lt;/code&gt;, eu prefiro pagar o custo de um commit de merge explícito para manter a história da integração mais clara. É uma escolha. Em muitos projetos, histórico linear é preferível. No meu fluxo, a rastreabilidade da unidade de trabalho pesa mais.&lt;/p&gt;
&lt;p&gt;Depois do push, fecho a issue:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh issue close 12 --comment &quot;Implemented and merged into dev.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E apago a branch local:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git branch -d stage/12-configure-fastify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso encerra o ciclo da unidade de trabalho.&lt;/p&gt;
&lt;p&gt;A branch cumpriu sua função. A issue foi resolvida. &lt;code&gt;dev&lt;/code&gt; recebeu a mudança. O histórico sabe contar a história.&lt;/p&gt;
&lt;h2&gt;Como conferir o que falta no milestone&lt;/h2&gt;
&lt;p&gt;Antes de pensar em release, eu olho o que ainda está aberto no milestone:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh issue list \
  --milestone &quot;v0.1.0&quot; \
  --state open
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O &lt;a href=&quot;https://cli.github.com/manual/gh_issue_list&quot;&gt;&lt;code&gt;gh issue list&lt;/code&gt;&lt;/a&gt; lista issues do repositório e aceita filtros como milestone e estado. É uma forma simples de responder uma pergunta que deveria ser obrigatória antes de qualquer release:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;ainda falta alguma coisa planejada para esta versão?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se ainda existe issue aberta, a release não está pronta.&lt;/p&gt;
&lt;p&gt;Dá para discutir exceções? Claro. Sempre dá. Mas exceção precisa ser consciente. O problema é quando a exceção vira fluxo padrão e ninguém mais sabe se a versão representa um conjunto fechado de trabalho ou só “o que tinha na branch naquela hora”.&lt;/p&gt;
&lt;p&gt;Release boa tem intenção.&lt;/p&gt;
&lt;h2&gt;Release sai de main&lt;/h2&gt;
&lt;p&gt;Quando todas as issues do milestone estão fechadas e &lt;code&gt;dev&lt;/code&gt; está estável, preparo a release.&lt;/p&gt;
&lt;p&gt;O fluxo é:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git switch main
git pull origin main
git merge --no-ff dev
git tag -a v0.1.0 -m &quot;v0.1.0&quot;
git push origin main
git push origin v0.1.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aqui eu prefiro tag anotada:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git tag -a v0.1.0 -m &quot;v0.1.0&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;a href=&quot;https://git-scm.com/docs/git-tag&quot;&gt;documentação do Git diferencia tags anotadas de tags leves&lt;/a&gt;: tags anotadas carregam metadados como tagger, data e mensagem, enquanto tags leves são basicamente um nome apontando para um objeto. A própria documentação recomenda tags anotadas para releases e tags leves para marcações privadas ou temporárias.&lt;/p&gt;
&lt;p&gt;Depois crio a release no GitHub:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh release create v0.1.0 \
  --title &quot;v0.1.0&quot; \
  --notes &quot;Initial MVP release&quot; \
  --verify-tag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O &lt;code&gt;--verify-tag&lt;/code&gt; é proposital. A &lt;a href=&quot;https://cli.github.com/manual/gh_release_create&quot;&gt;documentação do &lt;code&gt;gh release create&lt;/code&gt;&lt;/a&gt; explica que, se uma tag correspondente não existir, o GitHub CLI pode criar essa tag automaticamente a partir do estado mais recente da branch padrão. Com &lt;code&gt;--verify-tag&lt;/code&gt;, o comando falha se a tag ainda não existir.&lt;/p&gt;
&lt;p&gt;E eu quero que falhe.&lt;/p&gt;
&lt;p&gt;Se eu esqueci de criar ou enviar a tag a partir de &lt;code&gt;main&lt;/code&gt;, não quero que uma release seja criada automaticamente do lugar errado. Release é um daqueles momentos em que “deixa que a ferramenta resolve” pode virar uma pequena bomba com interface bonita.&lt;/p&gt;
&lt;p&gt;Para releases com notas maiores, prefiro arquivo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gh release create v0.1.0 \
  --title &quot;v0.1.0&quot; \
  --notes-file release-notes.md \
  --verify-tag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Release note não precisa virar livro, mas precisa explicar o que saiu. Idealmente, ela deve nascer do milestone: quais issues foram concluídas, quais mudanças importam, se houve breaking change e o que a pessoa precisa saber para atualizar.&lt;/p&gt;
&lt;h2&gt;Corrigindo commits errados&lt;/h2&gt;
&lt;p&gt;Às vezes você erra o commit.&lt;/p&gt;
&lt;p&gt;Acontece. O importante é saber se é seguro reescrever o histórico.&lt;/p&gt;
&lt;p&gt;Antes de mexer nisso, eu olho o estado do repositório:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git status
git branch --show-current
git log --oneline --decorate --max-count=30
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se os commits estão locais ou se é seguro reescrever, uso rebase interativo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git rebase -i dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ou, quando estou em &lt;code&gt;dev&lt;/code&gt; comparando com o remoto:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git rebase -i origin/dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rebase é uma ferramenta poderosa justamente porque mexe na base de uma sequência de commits. A &lt;a href=&quot;https://git-scm.com/docs/git-rebase&quot;&gt;documentação oficial&lt;/a&gt; resume a ideia como “transplantar uma série de commits para um ponto inicial diferente”. Isso parece uma frase de manual porque é mesmo, então vamos traduzir.&lt;/p&gt;
&lt;p&gt;Imagine que você criou três commits em cima de uma branch. Depois percebeu que quer reorganizar esses commits, mudar mensagens, juntar dois commits pequenos demais ou colocar sua sequência em cima de uma base mais nova. O rebase permite reescrever essa sequência.&lt;/p&gt;
&lt;p&gt;No modo interativo, o Git abre uma lista de commits e deixa você decidir o que fazer com cada um. Para corrigir mensagem, marco o commit como:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;reword
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E reescrevo no formato certo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;[type]/[update-scope]: summary
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Também dá para usar rebase interativo para juntar commits com &lt;code&gt;squash&lt;/code&gt; ou &lt;code&gt;fixup&lt;/code&gt;, reordenar commits ou remover um commit local que não deveria existir. Mas esse poder vem com a parte chata: rebase reescreve histórico.&lt;/p&gt;
&lt;p&gt;Por isso a regra é simples: rebase em commit local é ferramenta de higiene. Rebase em histórico compartilhado é cirurgia. E cirurgia sem necessidade costuma terminar com alguém perguntando “por que meu branch explodiu?”.&lt;/p&gt;
&lt;p&gt;Se a branch já foi enviada e ainda assim for seguro reescrever, o push deve ser:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git push --force-with-lease
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Não uso:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git push --force
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;--force-with-lease&lt;/code&gt; ainda é uma ferramenta que precisa de cuidado, mas pelo menos tenta evitar sobrescrever trabalho remoto que você ainda não viu. &lt;code&gt;--force&lt;/code&gt; é a motosserra sem óculos de proteção.&lt;/p&gt;
&lt;p&gt;Se reescrever histórico for inseguro, eu prefiro criar um commit corretivo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;docs/versioning: correct commit convention workflow
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Histórico limpo é bom. Histórico destruído para parecer limpo é só vaidade com efeitos colaterais.&lt;/p&gt;
&lt;h2&gt;Documentação pública e documentação interna não são a mesma coisa&lt;/h2&gt;
&lt;p&gt;Outra regra que eu sigo: README não é depósito de planejamento interno.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;README.md&lt;/code&gt; precisa ser público, prático e amigável. Ele deve explicar o que o projeto faz, como instalar, como rodar, como usar, quais exemplos importam e quais configurações existem.&lt;/p&gt;
&lt;p&gt;Já documentação interna, plano de implementação, notas de arquitetura, rascunhos e checklists de desenvolvimento ficam em:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;/specs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E esse diretório não deve ser versionado:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-gitignore&quot;&gt;/specs/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso ajuda a separar o que é documentação do produto do que é documentação do processo.&lt;/p&gt;
&lt;p&gt;O usuário do projeto não precisa ler minhas notas de implementação. E eu não preciso fingir que todo rascunho interno é documentação pública.&lt;/p&gt;
&lt;h2&gt;Comentário em código não substitui clareza&lt;/h2&gt;
&lt;p&gt;Eu também evito comentários explicativos comuns no código.&lt;/p&gt;
&lt;p&gt;Não porque comentário seja proibido por religião, mas porque comentário muitas vezes vira curativo para código confuso.&lt;/p&gt;
&lt;p&gt;Em vez disso, prefiro nomes melhores, funções menores, tipos explícitos, limites de módulo claros e estrutura legível.&lt;/p&gt;
&lt;p&gt;Documentação mora em Markdown. Código deve tentar se explicar primeiro.&lt;/p&gt;
&lt;p&gt;Existem exceções: headers legais, diretivas exigidas por ferramenta, comentários raros para comportamento externo estranho. Mas exceção não deveria virar estilo.&lt;/p&gt;
&lt;p&gt;Se toda função precisa de um parágrafo explicando o que ela faz, talvez o problema não seja falta de comentário. Talvez seja a função.&lt;/p&gt;
&lt;h2&gt;Checklist do fluxo completo&lt;/h2&gt;
&lt;p&gt;Para cada unidade de trabalho, o caminho fica assim:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/git-bom-n%C3%A3o-come%C3%A7a-no-commit/git-workflow-map.svg&quot; alt=&quot;Mapa do fluxo Git com issue, milestone, branch local, validação, dev, main e release&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;O fluxo separa planejamento, implementação local, integração e publicação para manter rastreabilidade.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;1. Identificar a tarefa
2. Criar ou confirmar o milestone
3. Criar a issue com template usando GitHub CLI
4. Criar uma branch local stage/* a partir de dev
5. Implementar apenas o escopo da issue
6. Commitar usando [type]/[update-scope]: summary
7. Rodar lint, typecheck, testes e build
8. Corrigir falhas de validação
9. Fazer merge em dev com --no-ff
10. Enviar apenas dev
11. Fechar a issue
12. Apagar a branch local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E antes de uma release:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;1. Confirmar que não há issues abertas no milestone
2. Validar que dev está estável
3. Fazer merge de dev em main
4. Criar tag anotada vX.Y.Z em main
5. Enviar main e a tag
6. Criar GitHub Release a partir da tag
7. Escrever release notes em inglês
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esse fluxo não é o único possível. Nem deveria ser vendido como religião universal. Projetos maiores podem exigir PR obrigatório, revisão, branch protection, ambientes de staging, CI mais forte, changelog automatizado e aprovação formal.&lt;/p&gt;
&lt;p&gt;Mas o princípio escala: mudança sem planejamento vira ruído. Mudança sem validação vira risco. Mudança sem release vira amontoado. Mudança sem rastreabilidade vira arqueologia.&lt;/p&gt;
&lt;h2&gt;O objetivo não é complicar o Git&lt;/h2&gt;
&lt;p&gt;O objetivo desse fluxo não é transformar projeto pequeno em repartição pública com YAML.&lt;/p&gt;
&lt;p&gt;É o contrário.&lt;/p&gt;
&lt;p&gt;A ideia é tirar ambiguidade. Cada coisa tem lugar: issue planeja, milestone agrupa, branch isola, commit registra, validação filtra, &lt;code&gt;dev&lt;/code&gt; integra, &lt;code&gt;main&lt;/code&gt; estabiliza e release publica.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;add/commit/push&lt;/code&gt; continua existindo. Ele só deixa de ser o fluxo inteiro.&lt;/p&gt;
&lt;p&gt;Porque versionamento bom não é apertar três comandos em sequência. É conseguir olhar para o histórico daqui a seis meses e entender o que aconteceu sem precisar abrir uma sessão espírita com seu eu do passado.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>AUR Parte 2: O Caos Continua; Agora são 1.500 Pacotes Afetados</title><link>https://blog.kristyan.dev/posts/aur-parte-2-o-caos-continua-agora-s%C3%A3o-1500-pacotes-afetados</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/aur-parte-2-o-caos-continua-agora-s%C3%A3o-1500-pacotes-afetados</guid><description>A investigação sobre o ataque ao AUR escalou de centenas para mais de 1.500 pacotes afetados. E, para melhorar a piada, eu também tinha um deles instalado.</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Eu publiquei um post falando sobre mais de 400 pacotes do AUR comprometidos com payloads associados a infostealer e rootkit-like malware.&lt;/p&gt;
&lt;p&gt;Pois é.&lt;/p&gt;
&lt;p&gt;Aparentemente, 400 era só o trailer.&lt;/p&gt;
&lt;p&gt;A atualização mais recente da investigação aponta para algo na casa de 1.500 pacotes afetados, espalhados em ondas diferentes da campanha que a Sonatype chamou de &lt;a href=&quot;https://www.sonatype.com/blog/atomic-arch-npm-campaign-adds-malicious-dependency&quot;&gt;Atomic Arch&lt;/a&gt;. A lista pública discutida no &lt;code&gt;aur-general&lt;/code&gt; também cresceu bastante, e os próprios mantenedores do Arch chegaram a publicar uma nota dizendo que removeram os commits maliciosos conhecidos naquele momento, junto de uma lista com muitos dos pacotes afetados.&lt;/p&gt;
&lt;p&gt;Repare na palavra importante: conhecidos.&lt;/p&gt;
&lt;p&gt;Esse detalhe muda o tom da conversa. O caso deixou de ser “alguns pacotes obscuros foram comprometidos” e virou “o modelo de confiança do AUR recebeu um soco bem dado na cara”.&lt;/p&gt;
&lt;h2&gt;Não era só &lt;code&gt;atomic-lockfile&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;No primeiro momento, a campanha parecia girar principalmente em torno de PKGBUILDs alterados para puxar uma dependência npm chamada &lt;code&gt;atomic-lockfile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Isso já era ruim o suficiente. O pacote malicioso trazia um payload nativo Linux com indícios de coleta de credenciais, tentativa de ocultação e potencial exfiltração de dados. A análise também apontou referências a eBPF e APIs de &lt;code&gt;libbpf&lt;/code&gt;, o tipo de coisa que faz qualquer usuário Linux parar de rir e começar a olhar para o backup com carinho.&lt;/p&gt;
&lt;p&gt;Só que depois apareceram outras ondas.&lt;/p&gt;
&lt;p&gt;Além de &lt;code&gt;atomic-lockfile&lt;/code&gt;, os relatos passaram a citar também &lt;code&gt;js-digest&lt;/code&gt;, &lt;code&gt;lockfile-js&lt;/code&gt; e até caminhos de instalação usando Bun em vez de npm. Ou seja: não era um único pacote ruim jogado por acidente em alguns PKGBUILDs. Era uma campanha se adaptando.&lt;/p&gt;
&lt;p&gt;A tese do post anterior continua de pé, mas agora com mais peso: o problema não é “um pacote malicioso”. O problema é a facilidade com que confiança herdada vira vetor de ataque.&lt;/p&gt;
&lt;h2&gt;O AUR não foi invadido como um repositório oficial&lt;/h2&gt;
&lt;p&gt;Esse ponto continua importante.&lt;/p&gt;
&lt;p&gt;O AUR não é o repositório oficial do Arch. Ele é um repositório comunitário de receitas de build. Um pacote AUR normalmente é um repositório Git com um &lt;code&gt;PKGBUILD&lt;/code&gt;, arquivos auxiliares e, às vezes, scripts de instalação.&lt;/p&gt;
&lt;p&gt;E &lt;code&gt;PKGBUILD&lt;/code&gt; é shell script.&lt;/p&gt;
&lt;p&gt;Shell script executa comandos.&lt;/p&gt;
&lt;p&gt;A beleza do AUR é justamente essa transparência: está tudo ali para você ler. A tragédia é que quase ninguém lê.&lt;/p&gt;
&lt;p&gt;O ataque explorou uma parte bem sensível desse modelo: pacotes órfãos ou abandonados. Um pacote que já tinha nome, histórico, votos, usuários e aparência de legitimidade podia ser adotado por outro mantenedor. A partir daí, bastava alterar a receita de build para puxar uma dependência maliciosa durante o fluxo normal de instalação.&lt;/p&gt;
&lt;p&gt;Não precisava convencer o usuário a instalar um pacote chamado &lt;code&gt;totally-not-a-stealer-bin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Bastava alterar algo que ele já confiava.&lt;/p&gt;
&lt;h2&gt;E agora vem a parte ridícula: eu também estava na lista&lt;/h2&gt;
&lt;p&gt;Depois de escrever sobre o caso, fui fazer a checagem na minha própria máquina.&lt;/p&gt;
&lt;p&gt;Adivinha.&lt;/p&gt;
&lt;p&gt;Eu tinha &lt;code&gt;astah-uml&lt;/code&gt; instalado.&lt;/p&gt;
&lt;p&gt;E &lt;code&gt;astah-uml&lt;/code&gt; aparece na lista de pacotes afetados discutida na thread do &lt;code&gt;aur-general&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A parte tragicômica é essa: eu escrevi um texto inteiro sobre não tratar o AUR como loja de aplicativo e, no fim, tinha um pacote da lista instalado no meu próprio sistema. Tecnologia é maravilhosa porque ela sempre encontra um jeito de te humilhar com logs.&lt;/p&gt;
&lt;p&gt;Tecnicamente, eu não vou cravar aqui que minha máquina foi “comprovadamente infectada” sem uma análise forense completa. O que dá para afirmar é pior para o ego e melhor para a precisão: eu estava exposto.&lt;/p&gt;
&lt;p&gt;E quando você está exposto a um possível infostealer com comportamento de ocultação, a resposta responsável não é “desinstalei, vida que segue”.&lt;/p&gt;
&lt;p&gt;Eu removi o pacote. Rotacionei chaves SSH. Revoguei tokens. Revisei credenciais. Tratei a máquina como suspeita.&lt;/p&gt;
&lt;p&gt;Porque pacote removido não desfaz chave vazada.&lt;/p&gt;
&lt;h2&gt;O que eu corrigiria no texto anterior&lt;/h2&gt;
&lt;p&gt;A primeira correção é trocar “mais de 400 pacotes” por “mais de 1.500 pacotes afetados”, deixando claro que o número ainda pode variar conforme a auditoria avança.&lt;/p&gt;
&lt;p&gt;A segunda é tomar cuidado com a palavra “infectado”. Pacotes podem estar afetados no AUR sem que toda máquina que tem aquele nome instalado tenha necessariamente executado o payload. O risco real depende de janela de instalação, atualização, execução do script malicioso e do que de fato rodou no ambiente local.&lt;/p&gt;
&lt;p&gt;A terceira é não reduzir tudo a &lt;code&gt;atomic-lockfile&lt;/code&gt;. Esse foi o primeiro nome forte da história, mas a campanha parece ter usado mais de um pacote malicioso e mais de um caminho de instalação.&lt;/p&gt;
&lt;p&gt;A quarta é reforçar a recomendação mais chata e mais correta: se você instalou ou atualizou um pacote afetado durante a janela do ataque, trate como incidente. No mínimo, revise logs, remova o pacote, rotacione credenciais sensíveis e olhe com carinho para tudo que estava salvo no seu &lt;code&gt;$HOME&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O ouro de um infostealer normalmente não está em virar root.&lt;/p&gt;
&lt;p&gt;Está nas suas chaves SSH, tokens de GitHub, credenciais de cloud, &lt;code&gt;.env&lt;/code&gt; esquecidos, cookies, CLIs logadas e arquivos de configuração que você jurou que ia limpar “qualquer dia”.&lt;/p&gt;
&lt;h2&gt;AUR helper não é airbag&lt;/h2&gt;
&lt;p&gt;Eu continuo gostando de helpers como &lt;code&gt;yay&lt;/code&gt; e &lt;code&gt;paru&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Mas helper não é auditor. Ele mostra diff, mas não lê por você. Ele pergunta se quer revisar, mas não obriga você a entender. Ele automatiza build, mas não transforma script de desconhecido em software confiável.&lt;/p&gt;
&lt;p&gt;O problema não é usar AUR. O problema é usar AUR como se fosse Steam.&lt;/p&gt;
&lt;p&gt;Clicar, instalar, atualizar tudo em lote, ignorar diff, aceitar mudança de mantenedor, pular comentário, confiar em pacote órfão, fazer &lt;code&gt;--noconfirm&lt;/code&gt; e depois agir surpreso quando a cadeia de confiança cobra a conta.&lt;/p&gt;
&lt;p&gt;O AUR continua sendo uma das melhores partes do Arch.&lt;/p&gt;
&lt;p&gt;Também continua sendo uma das partes que mais exigem maturidade do usuário.&lt;/p&gt;
&lt;h2&gt;Conclusão: o caos continua, mas o aviso também&lt;/h2&gt;
&lt;p&gt;O incidente do AUR não prova que Arch é inseguro por natureza. Essa leitura é preguiçosa.&lt;/p&gt;
&lt;p&gt;Ele prova algo mais desconfortável: transparência não protege quem não olha. Flexibilidade não protege quem terceiriza julgamento. Comunidade não substitui modelo de ameaça. E conveniência, quando passa do ponto, vira anestesia.&lt;/p&gt;
&lt;p&gt;No meu caso, a lição deixou de ser teórica quando encontrei &lt;code&gt;astah-uml&lt;/code&gt; na minha própria máquina.&lt;/p&gt;
&lt;p&gt;Nada como um ataque de supply chain para transformar opinião técnica em tarefa de sábado.&lt;/p&gt;
&lt;p&gt;O AUR não acabou. O Arch não morreu. Linux não virou Windows com vírus, por favor, menos.&lt;/p&gt;
&lt;p&gt;Mas a frase do post anterior continua valendo, agora com juros compostos:&lt;/p&gt;
&lt;p&gt;PKGBUILD é código. Código executa. Código de terceiros exige revisão.&lt;/p&gt;
&lt;p&gt;E contrato de confiança, em infraestrutura, sempre cobra juros.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>GitHub Bloqueado: A Internet Brasileira Virou um Ambiente Hostil para Desenvolvedores</title><link>https://blog.kristyan.dev/posts/github-bloqueado-a-internet-brasileira-virou-um-ambiente-hostil-para-desenvolvedores</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/github-bloqueado-a-internet-brasileira-virou-um-ambiente-hostil-para-desenvolvedores</guid><description>Uma análise crítica sobre o bloqueio aparente da API do GitHub no Brasil, os efeitos colaterais dos bloqueios sigilosos da Anatel e o impacto real disso na vida de desenvolvedores, ferramentas e infraestrutura.</description><pubDate>Fri, 12 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Que baita semana para gostar de computador.&lt;/p&gt;
&lt;p&gt;De um lado, centenas de pacotes do AUR aparecem em listas de comprometimento com suspeita de infostealer e rootkit. Do outro, a API do GitHub começa a cair no Brasil como se tivesse sido hospedada numa TV Box apreendida em operação da Anatel.&lt;/p&gt;
&lt;p&gt;Se você é desenvolvedor brasileiro, a quinta-feira virou um daqueles dias em que o terminal te olha de volta e pergunta: “você tem certeza que escolheu essa profissão por vontade própria?”.&lt;/p&gt;
&lt;p&gt;O site do GitHub abria. O repositório podia até clonar. Mas ferramentas que dependem de &lt;code&gt;api.github.com&lt;/code&gt; começaram a falhar. GitHub CLI, autenticação de extensões, bots, scripts de release, automações, consultas de issues, listagens de pull requests, integrações com CI, utilitários pessoais e qualquer coisa que conversasse com a API do GitHub entrava em timeout.&lt;/p&gt;
&lt;p&gt;Não era o GitHub inteiro fora do ar. Era pior.&lt;/p&gt;
&lt;p&gt;Era aquele tipo de falha seletiva que parece bug local, depois parece problema de DNS, depois parece rota quebrada, depois começa a aparecer no relato de gente em operadoras diferentes, e no final você percebe que talvez o problema não esteja no seu computador. Talvez o problema esteja no país.&lt;/p&gt;
&lt;h2&gt;A API Que Ninguém Vê Até Parar&lt;/h2&gt;
&lt;p&gt;Para um usuário comum, GitHub é o site. É a página que abre no navegador, o botão verde de clone, o README bonito, as issues, os releases e os repositórios públicos.&lt;/p&gt;
&lt;p&gt;Para um desenvolvedor, GitHub é muito mais que isso. É uma camada de infraestrutura.&lt;/p&gt;
&lt;p&gt;A API do GitHub é o canal invisível que conecta uma quantidade enorme de ferramentas ao ecossistema da plataforma. Quando você roda &lt;code&gt;gh pr list&lt;/code&gt;, não tem um duende raspando HTML da página de pull requests. A CLI fala com a API. Quando uma extensão do VS Code precisa validar autenticação, buscar informações da conta ou acionar recursos do Copilot, ela conversa com endpoints do GitHub. Quando um script interno lista issues abertas, fecha releases, cria tags, lê metadados ou consulta rate limit, ele usa a API. Quando um dashboard seu mostra pendências de repositórios, aquilo provavelmente não está olhando para o site: está chamando &lt;code&gt;api.github.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;É por isso que o bloqueio de uma API não é pequeno só porque o site principal continua abrindo.&lt;/p&gt;
&lt;p&gt;Essa é a diferença entre quebrar a vitrine e quebrar o estoque. O usuário final olha a loja funcionando e acha que está tudo bem. O desenvolvedor entra no depósito e encontra os corredores alagados, o ERP fora do ar e o sistema de pagamento respirando por aparelhos.&lt;/p&gt;
&lt;p&gt;A internet moderna é feita de APIs. Elas são a parte menos visível e mais crítica da infraestrutura. Bloquear uma API de forma descuidada é atingir diretamente a automação, a integração e a operação de quem trabalha com tecnologia.&lt;/p&gt;
&lt;p&gt;E no caso do GitHub, isso significa mexer em uma das principais peças da cadeia global de desenvolvimento de software.&lt;/p&gt;
&lt;h2&gt;O Que Aparentemente Aconteceu&lt;/h2&gt;
&lt;p&gt;O caso ainda exige cuidado. Até onde encontrei, não há uma nota oficial clara, pública e detalhada dizendo: “a Anatel mandou bloquear &lt;code&gt;api.github.com&lt;/code&gt; por este motivo, neste escopo, nesta data, por este procedimento, com este mecanismo técnico e com este plano de correção”.&lt;/p&gt;
&lt;p&gt;O que existe são indícios fortes, relatos técnicos e um padrão já conhecido por quem acompanha bloqueios de internet no Brasil.&lt;/p&gt;
&lt;p&gt;O Ayub, do Internet Propriamente Dita, &lt;a href=&quot;https://x.com/ayubio/status/2064878070394183955?s=20&quot;&gt;publicou que havia todos os indícios típicos de bloqueio nacional&lt;/a&gt; determinado pela Anatel contra &lt;code&gt;api.github.com&lt;/code&gt;. Outros usuários reportaram que o domínio resolvia para o IP &lt;code&gt;4.228.31.149&lt;/code&gt;, mas conexões para a porta 443 simplesmente morriam em timeout. Alguns testavam por grandes operadoras e falhavam. Outros testavam por VPN ou rotas fora do Brasil e funcionava. Em comunidades técnicas, apareceram relatos de falha em Claro, Vivo, TIM, Algar e outras redes, enquanto alguns provedores regionais pareciam não sofrer o mesmo efeito.&lt;/p&gt;
&lt;p&gt;Esse padrão é importante porque ele não se parece com uma queda global do GitHub. Também não se parece simplesmente com “meu DNS está ruim”. Quando o domínio resolve corretamente, mas a conexão TCP para o destino morre no caminho, estamos em outro território. Pode ser rota quebrada, blackhole, bloqueio em provedor, filtragem em backbone, política aplicada por operadoras ou algum tipo de regra mal calibrada no caminho.&lt;/p&gt;
&lt;p&gt;O problema é que, no Brasil, quando esse tipo de falha aparece em ondas e atinge grandes operadoras, a suspeita imediatamente cai sobre o sistema de bloqueios administrativos e judiciais que vem sendo usado há anos para combater pirataria, TV Box, streaming ilegal, sites de apostas irregulares e outros alvos.&lt;/p&gt;
&lt;p&gt;O ponto não é defender pirataria. Esse espantalho é cansativo.&lt;/p&gt;
&lt;p&gt;O ponto é que um mecanismo criado para bloquear um alvo específico não pode sair atropelando infraestrutura legítima como dano colateral aceitável.&lt;/p&gt;
&lt;h2&gt;Bloqueio Sigiloso É o Nome Bonito Para Quebrar a Internet Sem Prestar Conta&lt;/h2&gt;
&lt;p&gt;A parte mais grave dessa história não é apenas a API do GitHub ter ficado inacessível. O grave é a opacidade.&lt;/p&gt;
&lt;p&gt;Quando uma autoridade pública manda bloquear algo na internet, essa decisão deveria ser pública, rastreável, auditável e tecnicamente limitada. Deveria haver escopo claro. Deveria haver mecanismo de contestação. Deveria haver transparência sobre o domínio, IP, ordem judicial ou administrativa, duração, motivação e efeito esperado. Deveria haver análise de impacto antes de sair aplicando regra em massa.&lt;/p&gt;
&lt;p&gt;Mas o que usuários técnicos vêm denunciando há tempos é justamente o contrário: bloqueios sigilosos, listas não auditáveis, decisões difíceis de rastrear e efeitos colaterais descobertos só depois que usuários legítimos perdem acesso a serviços completamente alheios ao alvo original.&lt;/p&gt;
&lt;p&gt;O Ayub vem batendo nessa tecla há bastante tempo. A tese central é simples: quando o Estado cria uma infraestrutura de bloqueio nacional e opera isso sem transparência pública adequada, não importa se o discurso inicial é combater pirataria, proteger propriedade intelectual ou derrubar serviço ilegal. O mecanismo passa a existir. E mecanismo estatal opaco, uma vez instalado, tende a expandir.&lt;/p&gt;
&lt;p&gt;Hoje é site de streaming pirata. Amanhã é domínio compartilhado em CDN. Depois é GitHub Pages. Depois é API do GitHub. Depois é um registry de container. Depois é um endpoint usado por ferramenta de autenticação. Depois é um serviço que alguma empresa brasileira usa em produção e ninguém sabe explicar por que parou.&lt;/p&gt;
&lt;p&gt;O usuário comum chama suporte e escuta “reinicie o roteador”.&lt;/p&gt;
&lt;p&gt;O desenvolvedor roda traceroute e percebe que o problema é o país.&lt;/p&gt;
&lt;h2&gt;A Fragilidade Técnica de Bloquear a Internet Moderna&lt;/h2&gt;
&lt;p&gt;Bloquear internet em 2026 não é como bloquear uma linha telefônica.&lt;/p&gt;
&lt;p&gt;A web moderna não é um conjunto simples de sites isolados, cada um com um IP dedicado, um servidor físico e uma relação direta entre domínio e conteúdo. A infraestrutura atual é compartilhada, distribuída, cacheada, balanceada, roteada por CDNs, protegida por proxies reversos, replicada em regiões diferentes e exposta por APIs que atendem milhões de clientes programáticos.&lt;/p&gt;
&lt;p&gt;Um único endereço IP pode hospedar ou encaminhar tráfego para muitos serviços. Um único domínio pode ser crítico para uma cadeia inteira de ferramentas. Um endpoint pode parecer irrelevante para quem olha de fora, mas ser essencial para autenticação, automação, deploy, monitoramento ou integração de sistemas.&lt;/p&gt;
&lt;p&gt;GitHub é um exemplo perfeito. &lt;code&gt;github.com&lt;/code&gt; é a superfície humana. &lt;code&gt;api.github.com&lt;/code&gt; é a superfície de máquina. &lt;code&gt;raw.githubusercontent.com&lt;/code&gt; serve conteúdo bruto. &lt;code&gt;objects.githubusercontent.com&lt;/code&gt; pode aparecer em downloads. O ecossistema de autenticação, releases, actions, pacotes, Copilot, integrações e CLIs conversa com múltiplos endpoints. Quebrar um pedaço pode não derrubar o site, mas derruba fluxos inteiros de trabalho.&lt;/p&gt;
&lt;p&gt;Isso é o que autoridades e operadoras frequentemente parecem subestimar. A internet não é uma lista de “endereços de sites”. É um grafo de dependências.&lt;/p&gt;
&lt;p&gt;E quando você bloqueia um nó errado, o dano se propaga.&lt;/p&gt;
&lt;h2&gt;O Desenvolvedor Vira Operador de Rede Por Obrigação&lt;/h2&gt;
&lt;p&gt;Uma das coisas mais absurdas desse episódio é ver desenvolvedores precisando diagnosticar bloqueio de infraestrutura nacional como se isso fosse parte normal do expediente.&lt;/p&gt;
&lt;p&gt;A pessoa senta para revisar um pull request. O &lt;code&gt;gh pr list&lt;/code&gt; trava. Ela testa o navegador. O GitHub abre. Ela testa a API. Timeout. Testa DNS. Resolve. Testa outro DNS. Mesmo IP. Testa VPN. Funciona. Testa operadora diferente. Às vezes funciona, às vezes não. Testa IPv6. Testa curl com timeout. Testa porta 443. Testa traceroute. Testa de uma VPS fora do Brasil. Funciona. Testa pelo 4G. Falha.&lt;/p&gt;
&lt;p&gt;Em algum momento, o trabalho deixou de ser desenvolver software e virou perícia amadora de backbone.&lt;/p&gt;
&lt;p&gt;Isso não é normal.&lt;/p&gt;
&lt;p&gt;Claro, diagnosticar rede faz parte da vida técnica. Todo desenvolvedor deveria entender o básico de DNS, TCP, TLS, HTTP e roteamento. Mas existe uma diferença entre depurar sua aplicação e ter que provar que uma autoridade ou operadora quebrou o acesso a uma infraestrutura global de desenvolvimento.&lt;/p&gt;
&lt;p&gt;O usuário técnico brasileiro está sendo empurrado para uma postura de sobrevivência: VPN, DNS alternativo, WARP, proxy, túnel SSH, VPS fora do país, fallback em ferramenta própria, wrappers locais, split tunneling, gambiarras em &lt;code&gt;/etc/hosts&lt;/code&gt;, scripts com proxy configurável.&lt;/p&gt;
&lt;p&gt;Isso pode ser tecnicamente interessante. Mas politicamente é péssimo.&lt;/p&gt;
&lt;p&gt;Quando uma população técnica começa a tratar bypass como requisito básico para trabalhar, o país está normalizando a degradação da própria internet.&lt;/p&gt;
&lt;h2&gt;Não É Sobre O GitHub Ser Sagrado&lt;/h2&gt;
&lt;p&gt;É importante deixar uma coisa clara: GitHub não é uma entidade divina. É uma empresa privada, centralizada, com seus próprios problemas, lock-ins, decisões ruins e dependências questionáveis. Eu mesmo gosto de pensar em alternativas, mirrors, forge própria, Gitea, Forgejo, GitLab, backups e estratégias para não depender cegamente de uma plataforma só.&lt;/p&gt;
&lt;p&gt;Mas essa discussão é outra.&lt;/p&gt;
&lt;p&gt;O problema aqui não é “desenvolvedores dependem demais do GitHub”. Isso pode até ser verdade, mas não justifica bloqueio colateral opaco. Se amanhã o alvo fosse GitLab, npm, PyPI, Docker Hub, crates.io, Go Proxy, Maven Central, Arch mirrors, Nix cache, Vercel, Cloudflare, AWS, Google APIs ou qualquer outra infraestrutura legítima, o princípio seria o mesmo.&lt;/p&gt;
&lt;p&gt;A crítica não é “mexeram no meu brinquedo favorito”.&lt;/p&gt;
&lt;p&gt;A crítica é: uma autoridade pública não pode tratar infraestrutura compartilhada como se fosse botão de liga e desliga em painel de TV a cabo pirata.&lt;/p&gt;
&lt;p&gt;Esse é o tipo de coisa que separa política pública séria de improviso burocrático com poder demais.&lt;/p&gt;
&lt;h2&gt;O Argumento da Pirataria Não Pode Virar Carta Branca&lt;/h2&gt;
&lt;p&gt;Toda vez que se critica bloqueio de internet no Brasil, aparece alguém dizendo que é necessário combater pirataria, proteger propriedade intelectual, bloquear golpe, impedir crime, derrubar streaming ilegal, proteger consumidor ou fechar botnet de TV Box.&lt;/p&gt;
&lt;p&gt;Algumas dessas preocupações são legítimas. Crime digital existe. Pirataria existe. Golpe existe. Infraestrutura abusada por malware existe. Ninguém sério nega isso.&lt;/p&gt;
&lt;p&gt;Mas legitimidade do objetivo não absolve irresponsabilidade do método.&lt;/p&gt;
&lt;p&gt;Se para derrubar um serviço ilegal você cria um mecanismo sigiloso que pode bloquear infraestrutura legítima sem transparência, sem contraditório, sem auditoria pública e sem reparação rápida, você não criou uma política de segurança. Criou um canhão apontado para a camada errada.&lt;/p&gt;
&lt;p&gt;O Estado não pode responder ao abuso da internet quebrando a internet.&lt;/p&gt;
&lt;p&gt;Essa frase parece óbvia. Infelizmente, no Brasil, o óbvio precisa ser documentado em traceroute.&lt;/p&gt;
&lt;h2&gt;Quando a Solução Técnica Vira Sintoma Político&lt;/h2&gt;
&lt;p&gt;O mais curioso é que a comunidade técnica sempre encontra um jeito. E isso é, ao mesmo tempo, bonito e triste.&lt;/p&gt;
&lt;p&gt;Bonito porque desenvolvedores são bons em contornar falhas. Se a rota direta não funciona, usa-se outra rota. Se o DNS do provedor mente, testa-se outro resolvedor. Se a operadora joga tráfego no buraco, passa-se por VPN. Se uma CLI trava, exporta-se &lt;code&gt;HTTPS_PROXY&lt;/code&gt;. Se uma ferramenta própria depende da API, adiciona-se suporte a proxy. Se o endpoint falha em uma rede, testa-se de uma VPS.&lt;/p&gt;
&lt;p&gt;Triste porque nada disso deveria ser necessário para acessar a API pública do GitHub.&lt;/p&gt;
&lt;p&gt;Workaround é curativo. Não é cura.&lt;/p&gt;
&lt;p&gt;E pior: workaround individual tende a anestesiar a indignação coletiva. O desenvolvedor mais experiente configura um túnel, volta a trabalhar e segue a vida. A empresa coloca uma VPN corporativa e esquece. O usuário avançado muda DNS, usa WARP, sobe proxy SOCKS e transforma a exceção em rotina. Enquanto isso, o mecanismo que causou o problema continua existindo, opaco, silencioso e pronto para quebrar outra coisa no futuro.&lt;/p&gt;
&lt;p&gt;Essa é a armadilha. Resolver para si mesmo não resolve o problema público.&lt;/p&gt;
&lt;h2&gt;A Internet Brasileira Está Ficando Menos Confiável&lt;/h2&gt;
&lt;p&gt;Existe um custo econômico e técnico nesse tipo de instabilidade.&lt;/p&gt;
&lt;p&gt;Uma empresa que depende de automações no GitHub pode perder deploy. Um time pode ficar sem revisar PR. Uma extensão de editor pode parar de autenticar. Um bot interno pode deixar de triagear issues. Uma pipeline pode falhar não porque o código está errado, mas porque um endpoint externo foi bloqueado no caminho. Um desenvolvedor júnior pode gastar horas achando que configurou errado o ambiente. Um freelancer pode perder prazo. Um projeto open source pode ficar inacessível para parte dos mantenedores.&lt;/p&gt;
&lt;p&gt;E tudo isso é invisível para a estatística comum.&lt;/p&gt;
&lt;p&gt;Do ponto de vista de quem só mede “o site abre?”, talvez nada tenha acontecido. Do ponto de vista de quem trabalha com a API, o sistema quebrou.&lt;/p&gt;
&lt;p&gt;Isso é um problema de infraestrutura nacional. A confiança na internet de um país não depende apenas de velocidade de download em propaganda de operadora. Depende de previsibilidade, neutralidade, transparência e baixa interferência arbitrária.&lt;/p&gt;
&lt;p&gt;Se desenvolvedores começam a assumir que certas APIs podem morrer por decisão opaca ou erro de bloqueio, eles passam a projetar sistemas pensando em evasão, redundância forçada e rotas estrangeiras. Isso encarece operação. Isso degrada experiência. Isso reduz competitividade. Isso transforma conectividade em risco de negócio.&lt;/p&gt;
&lt;p&gt;O Brasil já tem desafio suficiente com imposto, burocracia, instabilidade jurídica e custo de infraestrutura. Adicionar “talvez a API que você usa seja bloqueada em alguma quarta-feira” ao pacote é quase uma piada de mau gosto.&lt;/p&gt;
&lt;h2&gt;A Relação Com o Caso do AUR&lt;/h2&gt;
&lt;p&gt;O mais irônico é que esse episódio aconteceu no mesmo momento em que usuários Linux estavam discutindo pacotes AUR comprometidos.&lt;/p&gt;
&lt;p&gt;Os dois casos parecem diferentes, mas conversam muito bem.&lt;/p&gt;
&lt;p&gt;O caso do AUR é sobre supply chain de software. O caso do GitHub bloqueado é sobre supply chain de infraestrutura. Em um, a confiança quebra porque código comunitário pode ter sido manipulado. No outro, a confiança quebra porque a rede entre você e uma dependência legítima pode ser interrompida por decisão externa opaca.&lt;/p&gt;
&lt;p&gt;Nos dois casos, o desenvolvedor é lembrado de uma verdade desagradável: seu ambiente de trabalho é uma pilha de dependências que você não controla completamente.&lt;/p&gt;
&lt;p&gt;Você depende do mantenedor do pacote. Depende do upstream. Depende do registry. Depende do DNS. Depende da operadora. Depende do backbone. Depende do provedor cloud. Depende da autoridade regulatória. Depende da plataforma de hospedagem. Depende da CDN. Depende de uma cadeia enorme de decisões técnicas e políticas invisíveis.&lt;/p&gt;
&lt;p&gt;Quando tudo funciona, parece simples. Quando quebra, você descobre quantas camadas havia entre você e um comando aparentemente banal.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;yay -S&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gh pr list&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Duas linhas inocentes. Dois lembretes de que infraestrutura é confiança empilhada.&lt;/p&gt;
&lt;h2&gt;O Que Deveria Acontecer&lt;/h2&gt;
&lt;p&gt;O mínimo aceitável seria transparência.&lt;/p&gt;
&lt;p&gt;Se houve bloqueio determinado por autoridade pública, a ordem deveria ser identificável. O escopo deveria ser claro. O alvo deveria ser tecnicamente justificado. A lista de domínios ou IPs afetados deveria ser auditável por órgãos competentes e contestável por partes impactadas. Deveria existir canal rápido de correção para falso positivo. Deveria haver relatório de impacto. Deveria haver responsabilização quando infraestrutura legítima é atingida.&lt;/p&gt;
&lt;p&gt;Se não houve bloqueio, então as operadoras envolvidas deveriam explicar por que um endpoint crítico ficou inacessível em suas redes enquanto funcionava por outras rotas. Problema técnico também exige prestação de contas quando afeta tanta gente.&lt;/p&gt;
&lt;p&gt;O que não dá é ficar nesse limbo brasileiro onde ninguém sabe oficialmente o que aconteceu, todo mundo coleta evidência por conta própria, usuários técnicos viram testemunhas de rede e o incidente desaparece quando volta a funcionar.&lt;/p&gt;
&lt;p&gt;Falha que some sem explicação não deixa de ser falha. Só vira precedente.&lt;/p&gt;
&lt;h2&gt;O Que Desenvolvedores Devem Fazer&lt;/h2&gt;
&lt;p&gt;Do ponto de vista técnico, o mais importante é documentar. Não basta reclamar no Twitter ou no grupo do Telegram. É preciso coletar evidências úteis: horário, operadora, cidade, domínio afetado, IP resolvido, resultado de conexão TCP, comportamento com e sem VPN, teste em rede alternativa, traceroute quando aplicável, ferramenta impactada e mensagem de erro.&lt;/p&gt;
&lt;p&gt;Isso não é para alimentar paranoia. É para transformar sensação em dado.&lt;/p&gt;
&lt;p&gt;Também é prudente projetar ferramentas próprias com suporte a proxy e timeout decente. Não porque isso resolva o problema político, mas porque ferramentas que travam indefinidamente por falha de rede são ruins de qualquer forma. Se uma CLI depende de API externa, ela precisa falhar bem, explicar o erro, respeitar timeout, permitir proxy e não fingir que toda falha de conexão é bug de autenticação.&lt;/p&gt;
&lt;p&gt;Empresas deveriam observar esse episódio como alerta de continuidade operacional. Se sua esteira de deploy, autenticação ou release depende de um único endpoint externo acessado por uma única rota nacional, você tem um ponto de falha. Talvez o risco seja aceitável. Talvez não. Mas ele precisa ser consciente.&lt;/p&gt;
&lt;p&gt;E, principalmente, a comunidade técnica não deveria normalizar o bloqueio. Workaround é necessário para trabalhar. Mas workaround não pode virar silêncio.&lt;/p&gt;
&lt;h2&gt;Conclusão: O Brasil Está Testando a Paciência da Própria Infraestrutura&lt;/h2&gt;
&lt;p&gt;O bloqueio aparente da API do GitHub é o tipo de evento que parece pequeno para quem não entende desenvolvimento de software e enorme para quem vive dele.&lt;/p&gt;
&lt;p&gt;Para o burocrata, é só mais um domínio. Para o desenvolvedor, é autenticação, automação, integração, release, issue, PR, bot, CLI, editor, extensão e fluxo de trabalho. Para a economia digital, é mais uma rachadura na confiança de que a internet brasileira é neutra, previsível e tecnicamente séria.&lt;/p&gt;
&lt;p&gt;O problema não é apenas um timeout em &lt;code&gt;api.github.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O problema é a naturalidade com que aceitamos que pedaços essenciais da internet possam ser bloqueados, afetados ou degradados sem explicação pública adequada. O problema é o sigilo tratado como ferramenta administrativa normal. O problema é o dano colateral tratado como inconveniente menor. O problema é desenvolvedor precisando aprender bypass para revisar pull request.&lt;/p&gt;
&lt;p&gt;Ainda não é o fim do mundo. Mas é mais um daqueles sinais feios piscando no painel.&lt;/p&gt;
&lt;p&gt;No mesmo dia em que o AUR lembra que rodar código de terceiros exige desconfiança, a internet brasileira lembra que depender de infraestrutura pública também exige vigilância.&lt;/p&gt;
&lt;p&gt;A diferença é que, no AUR, pelo menos o PKGBUILD está na sua frente.&lt;/p&gt;
&lt;p&gt;No bloqueio estatal opaco, nem isso.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>O AUR Foi Comprometido: Supply Chain, Pacotes Órfãos e o Preço de Rodar Código de Estranhos</title><link>https://blog.kristyan.dev/posts/mais-de-400-pacotes-aur-foram-comprometidos-com-infostealer-e-rootkit</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/mais-de-400-pacotes-aur-foram-comprometidos-com-infostealer-e-rootkit</guid><description>Uma análise sobre o comprometimento de centenas de pacotes do AUR, o papel dos PKGBUILDs na cadeia de confiança do Arch Linux e como responder tecnicamente a um incidente de supply chain no desktop.</description><pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Se você usa Arch Linux por tempo suficiente, em algum momento passa a tratar o AUR como parte natural do sistema. Você instala o sistema base, configura o pacman, escolhe um helper como &lt;code&gt;yay&lt;/code&gt; ou &lt;code&gt;paru&lt;/code&gt;, e quando percebe está digitando &lt;code&gt;yay -S nome-do-pacote&lt;/code&gt; com a mesma tranquilidade com que instalaria algo dos repositórios oficiais.&lt;/p&gt;
&lt;p&gt;Esse é exatamente o problema.&lt;/p&gt;
&lt;p&gt;Nos últimos dias, surgiram relatos de que mais de 400 pacotes do AUR foram comprometidos com payloads associados a infostealer e rootkit. A lista circulou em um Gist público com um script de checagem chamado &lt;code&gt;aur_check.sh&lt;/code&gt;, que basicamente define um array de pacotes suspeitos e verifica, via &lt;code&gt;pacman -Qi&lt;/code&gt;, se algum deles está instalado na máquina local.&lt;/p&gt;
&lt;p&gt;O script em si não é mágico. Ele não faz análise forense. Ele não prova que sua máquina está limpa. Ele não remove nada. Ele só responde uma pergunta objetiva: algum pacote conhecido nessa lista está instalado no meu sistema?&lt;/p&gt;
&lt;p&gt;Mas a existência desse script é o sintoma, não a doença.&lt;/p&gt;
&lt;p&gt;A doença é mais profunda. É a combinação de um repositório comunitário gigantesco, pacotes órfãos ou pouco mantidos, helpers que reduzem fricção demais, usuários pulando revisão de PKGBUILD e uma cultura perigosa de tratar o AUR como se fosse um repositório oficial com outro nome.&lt;/p&gt;
&lt;p&gt;Não é.&lt;/p&gt;
&lt;p&gt;O AUR nunca foi isso.&lt;/p&gt;
&lt;h2&gt;O AUR não é o pacman com mais pacotes&lt;/h2&gt;
&lt;p&gt;O Arch Linux tem uma separação muito clara entre os repositórios oficiais e o Arch User Repository. O pacman instala pacotes dos repositórios oficiais assinados e mantidos dentro do ecossistema da distribuição. O AUR, por outro lado, hospeda receitas de build enviadas por usuários. Essas receitas normalmente vêm na forma de um &lt;code&gt;PKGBUILD&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Um &lt;code&gt;PKGBUILD&lt;/code&gt; não é um arquivo declarativo inocente como um &lt;code&gt;package.json&lt;/code&gt; simplificado ou um manifesto estático. Ele é um script shell. E script shell executa comandos.&lt;/p&gt;
&lt;p&gt;Esse detalhe muda tudo.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/mais-de-400-pacotes-aur-foram-comprometidos-com-infostealer-e-rootkit/aur-trust-boundary.svg&quot; alt=&quot;Fronteira de confiança entre o PKGBUILD remoto e a execução local durante build e instalação&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;O ponto crítico é quando uma receita remota atravessa a fronteira e passa a executar comandos dentro do seu ambiente.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Quando você instala algo do AUR, o fluxo geral é: baixar o repositório daquele pacote, ler o &lt;code&gt;PKGBUILD&lt;/code&gt;, baixar os sources definidos nele, executar as etapas de preparação, build e empacotamento, gerar um pacote compatível com o pacman e então instalar esse pacote no sistema. Em tese, isso é transparente e auditável. Em teoria, é lindo.&lt;/p&gt;
&lt;p&gt;Na prática, a maioria das pessoas não lê nada.&lt;/p&gt;
&lt;p&gt;O helper pergunta se você quer revisar o diff. Você aperta enter. Ele pergunta se quer continuar. Você aperta enter. Ele baixa meia internet, compila, instala e segue a vida.&lt;/p&gt;
&lt;p&gt;Até o dia em que alguém adiciona uma dependência maliciosa, troca uma URL de origem, injeta um comando estranho no &lt;code&gt;prepare()&lt;/code&gt;, mexe no &lt;code&gt;.install&lt;/code&gt;, ou aproveita algum pacote órfão que ninguém revisa há meses.&lt;/p&gt;
&lt;p&gt;Aí o AUR deixa de ser conveniência e vira superfície de ataque.&lt;/p&gt;
&lt;p&gt;Já tratei de falar sobre isso &lt;a href=&quot;https://blog.kristyan.dev/posts/a-ilusao-da-conveniencia-aur-helpers-e-o-preco-do-controle-no-arch-linux&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;O PKGBUILD é uma fronteira de confiança&lt;/h2&gt;
&lt;p&gt;Existe uma diferença importante entre “baixar um software” e “executar uma receita de build escrita por um desconhecido”.&lt;/p&gt;
&lt;p&gt;Quando você instala um pacote oficial, ainda existe confiança envolvida, obviamente. Mas existe uma cadeia de manutenção, assinatura, empacotamento, revisão comunitária, infraestrutura da distribuição e um nível de responsabilidade mais claro. Não é perfeito, mas existe uma estrutura.&lt;/p&gt;
&lt;p&gt;No AUR, a fronteira de confiança é outra. Você confia que o mantenedor do pacote escreveu um &lt;code&gt;PKGBUILD&lt;/code&gt; honesto. Você confia que a URL de origem aponta para o projeto correto. Você confia que o source baixado não foi trocado. Você confia que checksums foram atualizados de forma legítima. Você confia que a função &lt;code&gt;prepare()&lt;/code&gt; não executa algo suspeito. Você confia que a função &lt;code&gt;package()&lt;/code&gt; não enfia lixo em algum lugar inesperado. Você confia que os hooks de instalação não abusam do momento em que o pacote é instalado com privilégios elevados.&lt;/p&gt;
&lt;p&gt;E pior: você renova essa confiança a cada atualização.&lt;/p&gt;
&lt;p&gt;Esse é o ponto que muita gente ignora. Não basta ter auditado um pacote uma vez há seis meses. O ataque de supply chain acontece justamente quando algo que já era confiável muda. Um pacote abandonado pode ser adotado por alguém mal-intencionado. Um mantenedor pode ser comprometido. Um upstream legítimo pode ser invadido. Uma dependência transitiva pode virar o vetor real. O pacote que ontem era inofensivo pode hoje estar puxando um payload durante o build.&lt;/p&gt;
&lt;p&gt;O AUR é poderoso porque transforma qualquer usuário em empacotador.&lt;/p&gt;
&lt;p&gt;O AUR é perigoso pelo mesmo motivo.&lt;/p&gt;
&lt;h2&gt;O caso dos pacotes comprometidos&lt;/h2&gt;
&lt;p&gt;O que chamou atenção nesse incidente foi a escala. Não estamos falando de um pacote obscuro isolado com meia dúzia de usuários. Os relatos apontaram centenas de pacotes contaminados em um intervalo curto de tempo, muitos deles aparentemente órfãos ou pouco vigiados. O padrão discutido pela comunidade envolvia alterações em PKGBUILDs e dependências suspeitas, com destaque para uma dependência npm chamada &lt;code&gt;atomic-lockfile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Esse detalhe importa porque mostra uma tendência cada vez mais comum: ataques modernos de supply chain raramente precisam explorar uma vulnerabilidade sofisticada no kernel, no compilador ou no gerenciador de pacotes. Eles exploram confiança operacional.&lt;/p&gt;
&lt;p&gt;Não é preciso quebrar criptografia. Não é preciso achar um zero-day cinematográfico. Basta convencer o usuário a executar o caminho “normal” de instalação.&lt;/p&gt;
&lt;p&gt;O desenvolvedor moderno já vive cercado de scripts automáticos. &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;pip install&lt;/code&gt;, &lt;code&gt;curl | bash&lt;/code&gt;, &lt;code&gt;make install&lt;/code&gt;, &lt;code&gt;docker compose up&lt;/code&gt;, &lt;code&gt;yay -S&lt;/code&gt;, GitHub Actions, hooks de pre-commit, extensões de editor, plugins de shell, temas de terminal, dotfiles baixados de repositórios aleatórios. O desktop de desenvolvimento virou uma colcha de retalhos de pequenos pontos de execução automática.&lt;/p&gt;
&lt;p&gt;O AUR entra nesse cenário como uma peça extremamente conveniente, mas também extremamente sensível. Ele é a cola entre o usuário Arch e quase qualquer coisa que ainda não chegou aos repositórios oficiais. Só que cola demais também gruda sujeira.&lt;/p&gt;
&lt;h2&gt;O problema não é usar AUR. O problema é usar AUR como se fosse Steam&lt;/h2&gt;
&lt;p&gt;Seria fácil escrever um texto moralista dizendo “não use AUR”. Também seria inútil.&lt;/p&gt;
&lt;p&gt;O AUR é uma das grandes forças do Arch Linux. Ele resolve um problema real: empacotar software que não está nos repositórios oficiais, versões &lt;code&gt;-git&lt;/code&gt;, builds customizados, binários proprietários, ferramentas pequenas, utilitários de nicho, temas, drivers, clients experimentais, forks e integrações que dificilmente teriam espaço em uma distribuição mais conservadora.&lt;/p&gt;
&lt;p&gt;O problema é quando o AUR vira loja de aplicativo.&lt;/p&gt;
&lt;p&gt;A pessoa pesquisa o nome do programa, instala o primeiro resultado, ignora o diff, ignora os comentários, ignora o mantenedor, ignora a data da última atualização, ignora os sources, ignora checksums, ignora dependências novas, e ainda automatiza atualização com &lt;code&gt;--noconfirm&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Isso não é workflow avançado. Isso é superstição com shell.&lt;/p&gt;
&lt;p&gt;O usuário Arch gosta de repetir que usa uma distribuição simples, transparente e controlável. Mas transparência só serve se você olhar. O PKGBUILD estar disponível não protege ninguém se a revisão vira teatro. O helper mostrar diff não resolve nada se o diff é tratado como tela de loading.&lt;/p&gt;
&lt;p&gt;O AUR exige uma postura diferente. Não é “instalar pacote”. É aceitar temporariamente uma receita de build escrita por terceiros dentro do seu ambiente local.&lt;/p&gt;
&lt;p&gt;Essa frase deveria pesar mais.&lt;/p&gt;
&lt;h2&gt;O que um pacote malicioso consegue fazer?&lt;/h2&gt;
&lt;p&gt;A resposta honesta é: depende do ponto em que ele executa, do usuário que executa e do quanto seu ambiente está exposto.&lt;/p&gt;
&lt;p&gt;Durante o build, um &lt;code&gt;PKGBUILD&lt;/code&gt; malicioso pode rodar comandos como seu usuário normal. Isso já é suficiente para muita coisa ruim. Seu usuário normalmente tem acesso ao seu &lt;code&gt;$HOME&lt;/code&gt;, às suas chaves SSH, aos seus tokens salvos em arquivos de configuração, ao cache de navegadores, às credenciais de CLIs, ao histórico do shell, aos projetos de trabalho, aos repositórios Git, aos arquivos &lt;code&gt;.env&lt;/code&gt;, às sessões de ferramentas de cloud e a uma quantidade absurda de material sensível.&lt;/p&gt;
&lt;p&gt;Muita gente pensa em segurança Linux apenas como “virou root ou não virou root”. Isso é uma visão pobre. Para um infostealer, root é bônus. O ouro está no usuário.&lt;/p&gt;
&lt;p&gt;Se o objetivo é roubar tokens do GitHub, credenciais npm, chaves SSH, arquivos de configuração de cloud, carteiras, cookies, secrets de projeto ou variáveis persistidas em dotfiles, o usuário normal já é suficiente. Um &lt;code&gt;cat ~/.ssh/id_ed25519&lt;/code&gt;, uma busca por &lt;code&gt;.env&lt;/code&gt;, uma leitura de &lt;code&gt;~/.config&lt;/code&gt;, um acesso a tokens de CLI e uma requisição HTTP para fora podem causar estrago antes de qualquer prompt de sudo aparecer.&lt;/p&gt;
&lt;p&gt;Já durante a instalação do pacote gerado, o risco pode subir. Pacotes podem ter scripts de instalação executados pelo pacman. Dependendo do que foi empacotado e de como o fluxo foi montado, código pode rodar em contexto privilegiado. Aí a conversa deixa de ser roubo de credencial e vira persistência, manipulação de serviços, alteração de binários, hooks, unidades systemd, modificações em diretórios globais e outros vetores mais desagradáveis.&lt;/p&gt;
&lt;p&gt;É por isso que “removi o pacote” não é necessariamente resposta suficiente.&lt;/p&gt;
&lt;p&gt;Se o pacote malicioso só estava instalado mas nunca foi executado, talvez o dano seja limitado. Se ele rodou durante build ou install, você precisa tratar como incidente. E se há indícios de rootkit, persistência ou alteração de componentes do sistema, a resposta tecnicamente responsável pode ser reinstalar a máquina a partir de mídia confiável e rotacionar credenciais a partir de outro dispositivo limpo.&lt;/p&gt;
&lt;p&gt;É chato. É trabalhoso. Mas segurança não liga para conveniência.&lt;/p&gt;
&lt;h2&gt;Como eu checaria minha máquina&lt;/h2&gt;
&lt;p&gt;A primeira reação de muita gente quando aparece um Gist com script de checagem é rodar:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl alguma-coisa | bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Não faça isso.&lt;/p&gt;
&lt;p&gt;Esse reflexo é exatamente parte do problema cultural que permite ataques de supply chain. O incidente envolve execução de código não confiável. A resposta não pode ser executar mais código não confiável sem ler.&lt;/p&gt;
&lt;p&gt;O fluxo correto é baixar o arquivo, inspecionar, entender e só depois executar. No caso do &lt;code&gt;aur_check.sh&lt;/code&gt;, a versão que circulou é relativamente simples: define um array com os nomes dos pacotes afetados, itera por eles e usa &lt;code&gt;pacman -Qi&lt;/code&gt; para ver se algum está instalado. Ainda assim, a própria interface do GitHub alerta para caracteres Unicode ocultos ou bidirecionais. Isso não significa automaticamente que o script é malicioso, mas é motivo suficiente para abrir em um editor que mostre caracteres invisíveis, usar &lt;code&gt;cat -A&lt;/code&gt;, &lt;code&gt;sed -n&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;file&lt;/code&gt;, &lt;code&gt;xxd&lt;/code&gt; ou qualquer ferramenta que permita enxergar o que realmente está no arquivo.&lt;/p&gt;
&lt;p&gt;Eu faria algo nessa linha:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p /tmp/aur-malware-check
cd /tmp/aur-malware-check
curl -L -o aur_check.sh &apos;&amp;lt;raw-do-gist&amp;gt;&apos;
file aur_check.sh
sed -n &apos;1,80p&apos; aur_check.sh
tail -n 40 aur_check.sh
grep -nE &apos;curl|wget|bash -c|eval|base64|chmod|chattr|systemctl|crontab|sudo|su|rm -rf|nc|python|perl|ruby|node&apos; aur_check.sh
cat -A aur_check.sh | sed -n &apos;1,120p&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois de revisar, eu executaria sem sudo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;chmod +x aur_check.sh
./aur_check.sh | tee aur_check_result.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mas eu não pararia aí. O script é uma ajuda, não uma autoridade. Eu também compararia a lista de pacotes suspeitos com os pacotes instalados localmente. O objetivo é gerar uma lista limpa dos afetados de verdade, sem depender só da saída visual.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pacman -Qqm | sort &amp;gt; foreign-packages.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O comando acima lista pacotes estrangeiros, ou seja, pacotes instalados que não pertencem aos repositórios oficiais conhecidos pelo pacman. Nem todo pacote estrangeiro veio necessariamente do AUR, mas no desktop Arch comum essa lista é um excelente ponto de partida para enxergar sua exposição.&lt;/p&gt;
&lt;p&gt;Se algum pacote da lista aparecer instalado, a remoção precisa ser cuidadosa. Eu não sairia apagando metade do sistema no pânico. Primeiro verificaria se o pacote é explicitamente instalado ou dependência, olharia dependentes reversos, leria o log do pacman e só então removeria com &lt;code&gt;pacman -Rns&lt;/code&gt; ou pelo helper, sem permitir rebuild ou reinstalação automática.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pacman -Qi nome-do-pacote
pactree -r nome-do-pacote
sudo pacman -Rns nome-do-pacote
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois da remoção, eu rodaria a checagem de novo. Se o resultado indicar que nenhum pacote conhecido permanece instalado, ótimo. Mas isso só responde à pergunta sobre presença de pacote. Não responde à pergunta sobre comprometimento do usuário, persistência ou exfiltração anterior.&lt;/p&gt;
&lt;h2&gt;Remover pacote não desfaz roubo de token&lt;/h2&gt;
&lt;p&gt;Esse é o ponto mais importante do texto.&lt;/p&gt;
&lt;p&gt;Quando falamos de infostealer, a linha do tempo importa. Se o código malicioso rodou ontem, roubou seus tokens e você removeu o pacote hoje, os tokens continuam roubados. Remoção local não faz a chave SSH voltar para dentro da gaveta. Não invalida token do GitHub. Não troca senha. Não revoga sessão. Não limpa um segredo vazado dentro de algum log remoto.&lt;/p&gt;
&lt;p&gt;É por isso que resposta a incidente não é só limpeza de pacote. É contenção, erradicação e recuperação.&lt;/p&gt;
&lt;p&gt;Se um dos pacotes afetados estava instalado e principalmente se foi atualizado durante a janela do ataque, eu consideraria a máquina suspeita. A partir de outro dispositivo limpo, eu rotacionaria senhas importantes, revogaria tokens de GitHub, npm, PyPI, Docker Hub, registries privados, provedores cloud e qualquer serviço usado em CLI. Eu revisaria chaves SSH, GPG, arquivos &lt;code&gt;.env&lt;/code&gt;, credenciais de deploy, webhooks e secrets de CI/CD.&lt;/p&gt;
&lt;p&gt;Também olharia o básico de persistência local: unidades systemd de usuário, unidades systemd globais recém-criadas, crontabs, arquivos em &lt;code&gt;~/.config/systemd/user&lt;/code&gt;, alterações em shell startup files como &lt;code&gt;.bashrc&lt;/code&gt;, &lt;code&gt;.zshrc&lt;/code&gt;, &lt;code&gt;.profile&lt;/code&gt;, &lt;code&gt;.config/fish/config.fish&lt;/code&gt;, binários estranhos em &lt;code&gt;~/.local/bin&lt;/code&gt;, entradas suspeitas no autostart e arquivos recentes em locais como &lt;code&gt;/tmp&lt;/code&gt;, &lt;code&gt;~/.cache&lt;/code&gt; e diretórios de build do AUR.&lt;/p&gt;
&lt;p&gt;Não é para sair deletando tudo. É para investigar com calma. Deletar evidência antes de entender o que aconteceu pode atrapalhar mais do que ajudar.&lt;/p&gt;
&lt;p&gt;Se houver sinal de rootkit ou persistência privilegiada, a abordagem pragmática é parar de fingir que dá para “limpar na mão” com meia dúzia de comandos copiados de fórum. Rootkit joga em outra categoria. Nesse cenário, backup seletivo de dados, reinstalação limpa e rotação de credenciais é o caminho sensato.&lt;/p&gt;
&lt;p&gt;A pergunta não é “consigo salvar essa instalação?”. A pergunta é “quanto tempo vale a minha confiança?”.&lt;/p&gt;
&lt;h2&gt;Helpers são conveniência, não modelo de segurança&lt;/h2&gt;
&lt;p&gt;Eu gosto de helpers. Uso esse tipo de ferramenta porque ninguém merece clonar manualmente cada repositório do AUR, rodar &lt;code&gt;makepkg&lt;/code&gt;, instalar pacote, acompanhar atualização e repetir o processo para tudo. &lt;code&gt;yay&lt;/code&gt; e &lt;code&gt;paru&lt;/code&gt; existem porque resolvem um problema real de ergonomia.&lt;/p&gt;
&lt;p&gt;Mas helper não é auditor.&lt;/p&gt;
&lt;p&gt;O fato de uma ferramenta mostrar diff não significa que você leu. O fato de ela perguntar se deseja revisar não significa que a revisão aconteceu. O fato de ela automatizar build não significa que o build é seguro. Automatizar uma decisão ruim só faz a decisão ruim acontecer mais rápido.&lt;/p&gt;
&lt;p&gt;O maior erro é configurar atualização do AUR como se fosse atualização oficial do sistema. Rodar tudo com &lt;code&gt;--noconfirm&lt;/code&gt;, pular diff, aceitar alteração em lote e atualizar pacote AUR obscuro sem olhar é transformar o seu desktop em pipeline de CI de desconhecidos.&lt;/p&gt;
&lt;p&gt;Pacotes oficiais eu atualizo com muito mais tranquilidade. Pacotes AUR eu trato como exceção. Se eu puder usar pacote oficial, uso pacote oficial. Se o software oferece release binária confiável, assinatura e checksum bem documentados, avalio. Se existe Flatpak mantido de forma decente, pode ser melhor para certos aplicativos de desktop. Se preciso do AUR, tento manter o número de pacotes pequeno e revisável.&lt;/p&gt;
&lt;p&gt;Isso não é paranoia. É redução de superfície.&lt;/p&gt;
&lt;h2&gt;Como revisar um PKGBUILD de verdade&lt;/h2&gt;
&lt;p&gt;Revisar PKGBUILD não é apenas olhar se o nome do pacote parece certo. É observar as mudanças.&lt;/p&gt;
&lt;p&gt;A primeira coisa é conferir &lt;code&gt;source&lt;/code&gt;. De onde o código vem? É o repositório oficial do projeto? É um release versionado? É um arquivo jogado em algum domínio aleatório? É um binário pré-compilado sem assinatura? A URL mudou nesta atualização? O checksum mudou porque saiu uma versão nova ou porque alguém trocou o arquivo?&lt;/p&gt;
&lt;p&gt;Depois vem a lógica do script. Funções como &lt;code&gt;prepare()&lt;/code&gt;, &lt;code&gt;build()&lt;/code&gt;, &lt;code&gt;check()&lt;/code&gt; e &lt;code&gt;package()&lt;/code&gt; devem fazer sentido para o tipo de software empacotado. Um pacote simples que de repente começa a chamar &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;python -c&lt;/code&gt;, &lt;code&gt;base64 -d&lt;/code&gt;, &lt;code&gt;chmod +x&lt;/code&gt; em arquivo baixado dinamicamente ou escreve em lugares estranhos merece atenção. Não porque todo uso desses comandos seja malicioso, mas porque esse é justamente o tipo de ponto em que payloads se escondem.&lt;/p&gt;
&lt;p&gt;Também vale olhar arquivos &lt;code&gt;.install&lt;/code&gt;. Eles podem definir ações de &lt;code&gt;post_install&lt;/code&gt;, &lt;code&gt;post_upgrade&lt;/code&gt; e &lt;code&gt;pre_remove&lt;/code&gt;. Isso é útil para pacotes legítimos, mas também é um lugar óbvio para persistência. Se um pacote de tema, fonte, ícone, utilitário pequeno ou app simples quer mexer com serviço, daemon, cron, systemd ou diretório global sensível, a sobrancelha tem que subir.&lt;/p&gt;
&lt;p&gt;A revisão ideal é comparar o diff da atualização, não reler o pacote inteiro do zero sempre. O que mudou desde a versão anterior? Entrou dependência nova? O maintainer mudou? O pacote foi adotado recentemente? O upstream mudou de lugar? Alguém comentou algo suspeito na página do AUR? O pacote ficou órfão por muito tempo e voltou do nada?&lt;/p&gt;
&lt;p&gt;Esse é o tipo de pergunta que separa usuário avançado de usuário que só decorou comando.&lt;/p&gt;
&lt;h2&gt;O problema estrutural: supply chain é arquitetura&lt;/h2&gt;
&lt;p&gt;Esse incidente não é só “malware no AUR”. É mais uma manifestação do mesmo problema que aparece em npm, PyPI, Docker Hub, GitHub Actions, extensões de editor, plugins de shell e templates de projeto.&lt;/p&gt;
&lt;p&gt;A indústria inteira empilhou automação em cima de confiança implícita.&lt;/p&gt;
&lt;p&gt;A gente baixa dependência de dependência de dependência, executa script de install, roda gerador de projeto, instala plugin, importa action, puxa container, baixa binário de release, cola comando de README e depois finge surpresa quando alguém compromete um elo fraco.&lt;/p&gt;
&lt;p&gt;O AUR só torna isso mais visível porque o modelo é honesto. Ele não esconde que você está executando receita de usuário. Está tudo lá. O PKGBUILD é texto. O histórico está no Git. O diff pode ser visto. A página avisa que aquilo é conteúdo produzido por usuários. A responsabilidade nunca deixou de existir.&lt;/p&gt;
&lt;p&gt;O problema é que conveniência anestesia responsabilidade.&lt;/p&gt;
&lt;p&gt;E isso não é exclusivo de Arch. Usuário Ubuntu que cola &lt;code&gt;curl | bash&lt;/code&gt; de qualquer README está no mesmo jogo. Usuário macOS que instala fórmula Homebrew sem olhar source também participa. Desenvolvedor Node que roda &lt;code&gt;npm install&lt;/code&gt; em projeto aleatório está confiando em lifecycle scripts. Usuário Docker que roda imagem aleatória com volume montado no &lt;code&gt;$HOME&lt;/code&gt; também está brincando com a fronteira de confiança.&lt;/p&gt;
&lt;p&gt;O Arch só não tenta te proteger de você mesmo.&lt;/p&gt;
&lt;p&gt;Isso é virtude e defeito ao mesmo tempo.&lt;/p&gt;
&lt;h2&gt;O que eu mudaria no meu próprio uso&lt;/h2&gt;
&lt;p&gt;Depois de um incidente assim, minha conclusão não é abandonar o Arch. Também não é abandonar o AUR. A conclusão é tratar AUR como exceção operacional, não como padrão de instalação.&lt;/p&gt;
&lt;p&gt;Eu começaria reduzindo minha lista de pacotes estrangeiros. &lt;code&gt;pacman -Qqm&lt;/code&gt; deveria ser uma lista que eu consigo explicar. Se tem coisa ali que não uso há meses, sai. Se existe alternativa oficial, migro. Se instalei só para testar, removo. Se é pacote abandonado e sem comentários recentes, reavalio. Se é binário proprietário que baixa coisa de um domínio opaco, penso duas vezes.&lt;/p&gt;
&lt;p&gt;Também evitaria atualização cega de AUR. Atualizar o sistema com pacotes oficiais é uma coisa. Atualizar receitas comunitárias de build sem ler diff é outra. Eu prefiro gastar dois minutos revisando alterações do que duas horas tentando descobrir por que apareceu uma unidade systemd suspeita no meu usuário.&lt;/p&gt;
&lt;p&gt;Outra medida prática é separar melhor os ambientes. Nem todo app experimental precisa viver no host principal. Ferramentas de teste podem rodar em container, VM, Distrobox descartável ou usuário separado. Isso não elimina risco, especialmente se você monta seu &lt;code&gt;$HOME&lt;/code&gt; inteiro dentro do ambiente, mas reduz blast radius quando feito com cuidado.&lt;/p&gt;
&lt;p&gt;E, principalmente, eu deixaria menos segredo solto no desktop. Tokens permanentes em arquivo de texto, &lt;code&gt;.env&lt;/code&gt; antigos esquecidos, chaves SSH sem passphrase, credenciais cloud logadas para sempre, PAT amplo no GitHub, npm token global, tudo isso transforma qualquer infostealer simples em desastre caro. O atacante não precisa ser brilhante se o ambiente está servido em bandeja.&lt;/p&gt;
&lt;h2&gt;Conclusão: o AUR continua incrível, mas não é inocente&lt;/h2&gt;
&lt;p&gt;O AUR é uma das melhores partes do Arch Linux. Também é uma das mais perigosas quando usada sem disciplina.&lt;/p&gt;
&lt;p&gt;Esse incidente dos pacotes comprometidos não deve ser lido como “Arch é inseguro” ou “Linux pegou vírus”. Essa leitura é preguiçosa. O ponto real é mais interessante: sistemas abertos deslocam parte da responsabilidade para o usuário. Você ganha controle, transparência e flexibilidade. Em troca, perde a desculpa de dizer que ninguém avisou.&lt;/p&gt;
&lt;p&gt;O AUR sempre avisou.&lt;/p&gt;
&lt;p&gt;PKGBUILD é código. Código executa. Código de terceiros exige revisão. Helper é conveniência. Conveniência não é segurança. Pacote removido não desfaz credencial roubada. Máquina comprometida não volta a ser confiável só porque o terminal ficou verde de novo.&lt;/p&gt;
&lt;p&gt;No fim, esse caso é menos sobre 400 pacotes específicos e mais sobre maturidade operacional. A pergunta não é se você usa Arch. A pergunta é se você entende a cadeia de execução que você mesmo autorizou.&lt;/p&gt;
&lt;p&gt;Porque quando você digita &lt;code&gt;yay -S&lt;/code&gt; sem ler nada, você não está apenas instalando um programa.&lt;/p&gt;
&lt;p&gt;Você está assinando um contrato de confiança com alguém que talvez você nunca tenha visto na vida.&lt;/p&gt;
&lt;p&gt;E contrato de confiança, em infraestrutura, sempre cobra juros.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>LUKS por Baixo do Capô: Arquitetura de Criptografia no Linux, dm-crypt e Recuperação Forense</title><link>https://blog.kristyan.dev/posts/luks-por-baixo-do-capo</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/luks-por-baixo-do-capo</guid><description>Uma análise sobre o funcionamento do Linux Unified Key Setup (LUKS), o gerenciamento de mapeamento de blocos via kernel, gerenciamento de cabeçalhos e recuperação de partições criptografadas.</description><pubDate>Mon, 08 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Criptografia de disco parece simples até você precisar recuperar um volume quebrado, explicar por que uma senha nova não recriptografou terabytes de dados, ou descobrir que aquele backup do header que você “faria depois” era literalmente a diferença entre recuperar tudo e aceitar o luto.&lt;/p&gt;
&lt;p&gt;No Linux, a combinação mais comum para proteger dados em repouso é LUKS com dm-crypt. Muita gente fala “LUKS criptografa o disco”, mas isso é uma meia verdade conveniente. O LUKS não é exatamente o motor criptográfico. Ele é o formato, o cabeçalho, a estrutura de metadados e o gerenciamento de chaves. Quem faz o trabalho pesado de cifrar e decifrar blocos é o &lt;code&gt;dm-crypt&lt;/code&gt;, no kernel, usando o Device Mapper.&lt;/p&gt;
&lt;p&gt;Essa separação importa porque evita uma confusão bem comum: tratar criptografia de disco como se fosse uma camada mística de segurança absoluta. Não é. É uma peça muito boa para um problema específico: proteger dados em repouso contra acesso offline ao dispositivo, roubo de mídia, descarte malfeito de disco, perda de notebook, snapshot bruto de volume e outras situações em que alguém tem acesso aos blocos, mas não à chave.&lt;/p&gt;
&lt;p&gt;Quando o sistema está ligado, desbloqueado e comprometido, o jogo é outro. LUKS não é antivírus, não é EDR, não é firewall, não é controle de acesso e não salva servidor onde alguém já virou root. Chato, mas necessário dizer.&lt;/p&gt;
&lt;h2&gt;LUKS é o formato; dm-crypt é o motor&lt;/h2&gt;
&lt;p&gt;O &lt;code&gt;dm-crypt&lt;/code&gt; é um alvo do Device Mapper que fornece criptografia transparente de dispositivos de bloco usando a Crypto API do kernel. A própria documentação do kernel descreve o &lt;code&gt;crypt&lt;/code&gt; target como uma camada de criptografia transparente para block devices, com algoritmos como &lt;code&gt;aes-xts-plain64&lt;/code&gt; sendo usados na prática em muitos setups modernos.&lt;/p&gt;
&lt;p&gt;Já o &lt;code&gt;cryptsetup&lt;/code&gt; é a ferramenta de espaço de usuário que você usa para criar, abrir, fechar, consultar e administrar esses volumes. Segundo a &lt;a href=&quot;https://man7.org/linux/man-pages/man8/cryptsetup.8.html&quot;&gt;man page do cryptsetup&lt;/a&gt;, ao desbloquear um volume criptografado, a ferramenta cria um novo mapeamento de dispositivo, enquanto a criptografia e descriptografia ficam a cargo do driver &lt;code&gt;dm-crypt&lt;/code&gt; no kernel.&lt;/p&gt;
&lt;p&gt;Na prática, o fluxo é este:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;você cria um contêiner LUKS em um dispositivo;&lt;/li&gt;
&lt;li&gt;o LUKS armazena metadados, parâmetros e keyslots;&lt;/li&gt;
&lt;li&gt;o &lt;code&gt;cryptsetup&lt;/code&gt; valida a senha ou keyfile;&lt;/li&gt;
&lt;li&gt;o kernel cria um dispositivo virtual em &lt;code&gt;/dev/mapper/&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;o sistema de arquivos passa a enxergar esse dispositivo como um bloco normal.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A aplicação não sabe se está escrevendo em disco criptografado. O PostgreSQL, o SQLite, o Vim, o &lt;code&gt;cp&lt;/code&gt;, o &lt;code&gt;rsync&lt;/code&gt; e o resto da turma só veem um sistema de arquivos montado. A criptografia acontece abaixo disso, na camada de blocos.&lt;/p&gt;
&lt;p&gt;Isso é elegante porque não exige que cada aplicação implemente criptografia. Também é perigoso para a cabeça do usuário, porque a transparência da camada faz parecer que nada está acontecendo. E quando segurança parece invisível demais, sempre aparece alguém para esquecer qual problema ela realmente resolve.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/luks-por-baixo-do-capo/luks-dm-crypt-stack.svg&quot; alt=&quot;Camadas entre senha, header LUKS, chave de volume, dm-crypt, sistema de arquivos e disco físico&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A senha não cifra os dados diretamente; ela libera um keyslot que protege a chave de volume usada pelo dm-crypt.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;O que existe dentro de um volume LUKS&lt;/h2&gt;
&lt;p&gt;Um volume LUKS não é só “um disco com senha”. Ele tem uma estrutura.&lt;/p&gt;
&lt;p&gt;Em um volume LUKS, existe um cabeçalho com metadados sobre o contêiner: versão do formato, algoritmo, UUID, parâmetros de derivação de chave, área de keyslots e informações necessárias para abrir corretamente o dispositivo. A &lt;a href=&quot;https://man7.org/linux/man-pages/man8/cryptsetup.8.html&quot;&gt;man page do cryptsetup&lt;/a&gt; resume bem a diferença: volumes em modo plain têm criptografia básica sem metadados, enquanto volumes LUKS incluem um header padronizado que permite keyslots múltiplos e gerenciamento de chaves.&lt;/p&gt;
&lt;p&gt;A parte mais importante é esta: os dados do disco não são criptografados diretamente com a sua senha.&lt;/p&gt;
&lt;p&gt;A senha serve para liberar uma chave de volume. Essa chave de volume é a chave usada para criptografar os dados. Os keyslots armazenam cópias protegidas dessa chave, cada uma derivada de uma senha, keyfile ou mecanismo de autenticação compatível.&lt;/p&gt;
&lt;p&gt;É por isso que trocar a senha de um volume LUKS não exige recriptografar o disco inteiro. Você não está reescrevendo todos os blocos de dados. Você está alterando a forma como uma chave de volume é protegida em um keyslot.&lt;/p&gt;
&lt;p&gt;Bonito no README, importantíssimo no desastre.&lt;/p&gt;
&lt;h2&gt;Keyslots: múltiplas portas para a mesma chave&lt;/h2&gt;
&lt;p&gt;Keyslot é um daqueles conceitos que parecem detalhe até você precisar remover o acesso de alguém sem formatar um volume de alguns terabytes.&lt;/p&gt;
&lt;p&gt;No LUKS, vários keyslots podem desbloquear a mesma chave de volume. Isso permite ter, por exemplo, uma senha de uso diário, uma senha de emergência guardada em local seguro e um keyfile usado por automação. Cada entrada pode ser adicionada, alterada ou removida sem recriptografar os dados.&lt;/p&gt;
&lt;p&gt;Para ver a estrutura de um volume, o comando mais útil é:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksDump /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ele mostra informações do header, versão do LUKS, UUID, cipher, keyslots ativos e parâmetros de derivação. É um comando de inspeção, não de desbloqueio.&lt;/p&gt;
&lt;p&gt;Para adicionar uma nova senha ou keyfile:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksAddKey /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Para remover uma senha conhecida:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksRemoveKey /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E para matar um slot específico:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksKillSlot /dev/sdb1 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esse último exige cuidado. Remover o slot errado pode não destruir o volume, desde que existam outros slots válidos, mas pode destruir o seu acesso se você não souber exatamente quais credenciais ainda funcionam. O Linux entrega ferramentas afiadas. A parte de não sair correndo pela casa com a faca na mão continua sendo sua.&lt;/p&gt;
&lt;h2&gt;Criando e montando um volume LUKS manualmente&lt;/h2&gt;
&lt;p&gt;Para criar um volume LUKS em um dispositivo, o comando clássico é:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup --type luks2 luksFormat /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use &lt;code&gt;/dev/sdb1&lt;/code&gt; como exemplo, não como conselho universal. Conferir o dispositivo antes de rodar &lt;code&gt;luksFormat&lt;/code&gt; não é frescura; é sobrevivência. Esse comando inicializa o contêiner LUKS e pode destruir dados existentes no alvo. Se você rodar no disco errado, não existe argumento filosófico que desfaça a besteira.&lt;/p&gt;
&lt;p&gt;Depois de criar o contêiner, você abre o volume:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup open /dev/sdb1 dados_criptografados
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso cria um mapeamento em:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;/dev/mapper/dados_criptografados
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A partir daí, você cria um sistema de arquivos dentro do dispositivo mapeado:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkfs.ext4 /dev/mapper/dados_criptografados
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E monta normalmente:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkdir -p /mnt/dados
sudo mount /dev/mapper/dados_criptografados /mnt/dados
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tudo que for escrito em &lt;code&gt;/mnt/dados&lt;/code&gt; será escrito no sistema de arquivos, que por sua vez escreverá no dispositivo mapeado, que por sua vez passará pelo &lt;code&gt;dm-crypt&lt;/code&gt; antes de atingir o dispositivo físico.&lt;/p&gt;
&lt;p&gt;Para encerrar corretamente:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo umount /mnt/dados
sudo cryptsetup close dados_criptografados
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Repare na ordem. Primeiro desmonta o sistema de arquivos. Depois fecha o mapeamento criptográfico. Fechar o mapeamento com o filesystem ainda em uso é pedir para o sistema reclamar - com razão.&lt;/p&gt;
&lt;h2&gt;O header é pequeno, mas manda no destino do disco inteiro&lt;/h2&gt;
&lt;p&gt;O header do LUKS é uma das partes mais importantes do volume. Ele não contém os seus arquivos em texto claro, mas contém os metadados necessários para chegar até a chave de volume protegida pelos keyslots.&lt;/p&gt;
&lt;p&gt;Se o header for destruído, corrompido ou sobrescrito, o restante do disco vira ruído criptográfico. Não é drama. É o design fazendo exatamente o que se espera de criptografia: sem os metadados e a chave correta, os dados não devem ser recuperáveis.&lt;/p&gt;
&lt;p&gt;A própria &lt;a href=&quot;https://man7.org/linux/man-pages/man8/cryptsetup.8.html&quot;&gt;man page do cryptsetup&lt;/a&gt; avisa que, se o header de um volume LUKS for danificado, os dados podem ser permanentemente perdidos sem um backup de header. Também explica que o &lt;code&gt;luksHeaderBackup&lt;/code&gt; salva uma cópia binária do header e da área de keyslots.&lt;/p&gt;
&lt;p&gt;Faça o backup:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksHeaderBackup /dev/sdb1 \
  --header-backup-file luks-header-sdb1.bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E, em caso de desastre, a restauração usa:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksHeaderRestore /dev/sdb1 \
  --header-backup-file luks-header-sdb1.bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mas tem uma pegadinha importante: backup de header não é item decorativo para jogar no mesmo disco e esquecer. Ele precisa ficar fora do dispositivo protegido, preferencialmente em mídia separada, com backup e controle de acesso.&lt;/p&gt;
&lt;p&gt;Também não trate o arquivo como completamente inofensivo. Um backup de header não abre o volume sozinho sem senha ou chave válida, mas ele contém keyslots e metadados suficientes para permitir tentativas offline contra as credenciais. Além disso, restaurar um header antigo pode reverter mudanças de keyslot: senhas removidas podem voltar, senhas adicionadas depois do backup podem desaparecer, e o estado do volume pode ficar inconsistente em cenários mais complexos.&lt;/p&gt;
&lt;p&gt;Backup bom é aquele que você sabe restaurar. Backup de header que nunca foi testado é fé com extensão &lt;code&gt;.bin&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;LUKS protege confidencialidade, não integridade por padrão&lt;/h2&gt;
&lt;p&gt;Um ponto que muita explicação sobre LUKS deixa escapar: criptografia de disco tradicional protege confidencialidade. Ela impede que alguém leia os dados sem a chave. Isso não significa, automaticamente, que ela impeça adulteração detectável dos blocos.&lt;/p&gt;
&lt;p&gt;Em setups comuns com &lt;code&gt;dm-crypt&lt;/code&gt;, um atacante com acesso ao dispositivo offline pode alterar blocos cifrados. Ele talvez não saiba produzir uma alteração útil, mas ainda pode causar corrupção. Dependendo do sistema de arquivos, da aplicação e da área alterada, o resultado pode variar de “arquivo quebrado” até “boa sorte entendendo esse comportamento estranho”.&lt;/p&gt;
&lt;p&gt;Existem modos e arquiteturas que adicionam integridade autenticada, como combinações envolvendo &lt;code&gt;dm-integrity&lt;/code&gt; e recursos do LUKS2, mas isso não vem de graça. Há custo de espaço, desempenho, complexidade operacional e compatibilidade. O ponto não é sair ligando tudo porque parece mais seguro. O ponto é entender que LUKS comum não é uma assinatura criptográfica gigante do disco inteiro.&lt;/p&gt;
&lt;p&gt;Segurança sem modelo de ameaça vira decoração.&lt;/p&gt;
&lt;h2&gt;TRIM, SSD e vazamento de padrão de uso&lt;/h2&gt;
&lt;p&gt;Outro detalhe que costuma ser tratado com pressa é o descarte de blocos, também conhecido como TRIM em SSDs.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;dm-crypt&lt;/code&gt; pode permitir que operações de discard atravessem a camada criptografada. Isso pode ajudar SSDs e thin provisioning, mas também pode revelar padrões de uso: quais áreas estão alocadas, quais foram liberadas, como o volume evolui ao longo do tempo. A &lt;a href=&quot;https://docs.kernel.org/admin-guide/device-mapper/dm-crypt.html&quot;&gt;documentação do kernel sobre dm-crypt&lt;/a&gt; alerta que permitir discards em dispositivos criptografados pode vazar informações sobre o dispositivo cifrado, como tipo de sistema de arquivos e espaço utilizado.&lt;/p&gt;
&lt;p&gt;Não significa que &lt;code&gt;allow-discards&lt;/code&gt; é sempre proibido. Significa que não é uma opção neutra.&lt;/p&gt;
&lt;p&gt;Em notebook pessoal, servidor com SSD, ambiente virtualizado, storage thin-provisioned ou banco de dados com padrão de escrita específico, a decisão muda. Segurança real quase sempre é trade-off. Quem promete solução sem custo geralmente está vendendo curso, não arquitetura.&lt;/p&gt;
&lt;h2&gt;Performance: AES-NI ajuda, mas “desprezível” é palavra perigosa&lt;/h2&gt;
&lt;p&gt;Em CPUs modernas com aceleração de hardware, como AES-NI, o overhead de criptografia pode ser baixo em muitos cenários. Em alguns desktops e servidores, a diferença prática é quase invisível para uso comum.&lt;/p&gt;
&lt;p&gt;Mas escrever “o overhead é desprezível” como regra geral é exagero.&lt;/p&gt;
&lt;p&gt;O impacto depende do algoritmo, do modo de operação, do tamanho dos blocos, do dispositivo, da CPU, do scheduler, da carga de I/O, do uso de discard, da presença de integridade autenticada e do tipo de workload. Um desktop com NVMe e AES-NI não é a mesma coisa que um servidor velho, uma VM limitada, um ARM barato ou um storage saturado.&lt;/p&gt;
&lt;p&gt;Antes de cravar, rode ao menos:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cryptsetup benchmark
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E, mais importante, teste a carga real. Benchmark sintético é útil para entender limite criptográfico, mas não substitui medir o comportamento da aplicação que vai rodar em cima do volume.&lt;/p&gt;
&lt;h2&gt;Criptografia total de disco e o problema do boot remoto&lt;/h2&gt;
&lt;p&gt;Full Disk Encryption é ótimo até o servidor reiniciar às três da manhã e ficar parado esperando uma senha no console que ninguém tem aberto.&lt;/p&gt;
&lt;p&gt;Esse é o problema clássico de criptografar a raiz do sistema em máquinas remotas. Se tudo que importa está atrás do LUKS, alguém precisa desbloquear o volume antes do sistema subir completamente. Em notebook, isso é normal. Em servidor remoto, vira operação.&lt;/p&gt;
&lt;p&gt;Uma abordagem comum é colocar um SSH mínimo no initramfs, muitas vezes com Dropbear, para permitir desbloqueio remoto antes da montagem da raiz. Funciona, mas adiciona superfície de ataque justamente no estágio mais delicado do boot. Você passa a depender de rede, configuração do initramfs, chaves SSH, política de acesso e atualização correta dessa mini infraestrutura.&lt;/p&gt;
&lt;p&gt;Outra abordagem é separar o sistema operacional dos dados. A raiz sobe sem criptografia completa, o SSH normal inicia, e os volumes sensíveis ficam em LUKS separados. Depois do boot, um operador ou automação controlada desbloqueia apenas os volumes de dados.&lt;/p&gt;
&lt;p&gt;Isso não é “mais seguro” ou “menos seguro” universalmente. É uma escolha de ameaça.&lt;/p&gt;
&lt;p&gt;Se o risco principal é roubo físico de discos de dados, descarte de mídia ou snapshot bruto de volume, criptografar apenas dados sensíveis pode ser suficiente e mais operável. Se o risco inclui acesso ao disco do sistema, manipulação de binários, alteração de initramfs, persistência no boot ou exposição de segredos em &lt;code&gt;/etc&lt;/code&gt;, talvez a raiz também precise entrar na conta.&lt;/p&gt;
&lt;p&gt;Arquitetura boa começa com uma pergunta sem glamour: contra quem exatamente eu estou me defendendo?&lt;/p&gt;
&lt;h2&gt;LUKS em análise forense: trabalhe em cópia e monte read-only&lt;/h2&gt;
&lt;p&gt;Em resposta a incidentes, CTFs ou análise forense autorizada, é comum encontrar imagens brutas contendo partições LUKS. O procedimento correto não é sair montando a imagem original com escrita liberada como se fosse pendrive de música.&lt;/p&gt;
&lt;p&gt;Primeiro, trabalhe em cópia. Segundo, prefira loop device somente leitura. Terceiro, abra o volume em modo read-only quando o objetivo for análise.&lt;/p&gt;
&lt;p&gt;Um fluxo mais conservador seria:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo losetup --read-only --find --show imagem.raw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O comando retorna algo como:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;/dev/loop0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Se a imagem tiver tabela de partições, pode ser necessário usar ferramentas como &lt;code&gt;parted&lt;/code&gt;, &lt;code&gt;fdisk&lt;/code&gt;, &lt;code&gt;kpartx&lt;/code&gt; ou &lt;code&gt;losetup -P&lt;/code&gt; para expor as partições internas. Depois, com a partição correta identificada, o volume pode ser aberto em modo somente leitura:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup open --readonly --type luks /dev/loop0p2 volume_analise
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;E montado também como somente leitura:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mount -o ro /dev/mapper/volume_analise /mnt/analise
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ferramentas como &lt;code&gt;binwalk&lt;/code&gt; podem ajudar a encontrar assinaturas em arquivos binários, mas não devem virar muleta mental. Em disco real, tabela de partição, offsets, headers e alinhamento importam. Se você não sabe onde começa o contêiner LUKS, o problema não é o &lt;code&gt;cryptsetup&lt;/code&gt;; é a análise do layout.&lt;/p&gt;
&lt;p&gt;E vale repetir: análise forense pressupõe autorização. Sem isso, muda de “investigação” para “problema jurídico com terminal aberto”.&lt;/p&gt;
&lt;h2&gt;O que LUKS não resolve&lt;/h2&gt;
&lt;p&gt;LUKS é excelente dentro do escopo certo. Fora dele, vira amuleto.&lt;/p&gt;
&lt;p&gt;Ele não protege seus dados quando o volume já está desbloqueado e alguém comprometeu o sistema. Não impede exfiltração por malware rodando com permissão do usuário. Não protege contra senha fraca. Não substitui backup. Não corrige servidor mal configurado. Não faz controle de acesso por arquivo. Não impede que alguém apague o disco. Não garante integridade por padrão. Não salva uma máquina onde o atacante consegue alterar o boot sem que você perceba.&lt;/p&gt;
&lt;p&gt;Também não resolve o velho problema da disponibilidade. Criptografia pode transformar falhas pequenas em desastres definitivos. Um header perdido, uma senha esquecida, um keyslot removido errado ou um backup inexistente podem ser mais eficientes que muito ransomware.&lt;/p&gt;
&lt;p&gt;Isso não é argumento contra criptografia. É argumento contra usar criptografia sem operação.&lt;/p&gt;
&lt;h2&gt;Checklist mínimo antes de confiar em um volume LUKS&lt;/h2&gt;
&lt;p&gt;Algumas práticas simples evitam boa parte da tragédia:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksDump /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verifique o volume, os keyslots ativos e os parâmetros antes de mexer.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup luksHeaderBackup /dev/sdb1 \
  --header-backup-file luks-header-sdb1.bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Faça backup do header e guarde fora do disco.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo cryptsetup open /dev/sdb1 teste_restore
sudo cryptsetup close teste_restore
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Teste se a credencial esperada realmente abre o volume.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cryptsetup benchmark
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Meça o básico de performance criptográfica, mas valide com carga real.&lt;/p&gt;
&lt;p&gt;E, principalmente, mantenha backup dos dados. Header backup não substitui backup de conteúdo. Ele só preserva a chance de acessar o volume caso os metadados quebrem. Se o SSD morrer, se o filesystem corromper, se alguém apagar os arquivos ou se você formatar o dispositivo errado, o header backup não vira máquina do tempo.&lt;/p&gt;
&lt;h2&gt;LUKS é simples. A operação em volta dele não é.&lt;/h2&gt;
&lt;p&gt;O LUKS faz uma coisa muito bem: padroniza como o Linux gerencia volumes criptografados, múltiplas credenciais e metadados para criptografia de disco. O &lt;code&gt;dm-crypt&lt;/code&gt; faz o trabalho pesado no kernel. O &lt;code&gt;cryptsetup&lt;/code&gt; entrega a interface administrativa. Juntos, eles formam uma das soluções mais sólidas para proteger dados em repouso no ecossistema Linux.&lt;/p&gt;
&lt;p&gt;Mas a parte difícil nunca foi apenas rodar &lt;code&gt;luksFormat&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A parte difícil é saber qual dispositivo você está formatando. É guardar o header. É ter backup. É entender o que acontece quando troca uma senha. É saber que TRIM pode vazar padrão de uso. É lembrar que criptografia sem integridade tem limites. É planejar boot remoto. É aceitar que volume desbloqueado é dado acessível para o sistema.&lt;/p&gt;
&lt;p&gt;Criptografia de disco não é um botão mágico de segurança. É uma ferramenta de engenharia.&lt;/p&gt;
&lt;p&gt;E como toda ferramenta de engenharia no Linux, ela funciona muito bem — até alguém usar sem entender e depois culpar o kernel.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Systemd: A Guerra do Init, Complexidade Arquitetural e o Fim do SysVinit</title><link>https://blog.kristyan.dev/posts/systemd-a-guerra-do-init</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/systemd-a-guerra-do-init</guid><description>Uma análise sobre a adoção controversa do Systemd (2012-2013), as limitações estruturais do SysVinit, o ecossistema de alternativas como runit e OpenRC e as decisões de engenharia que moldaram o Linux moderno.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Toda discussão sobre systemd começa técnica e termina parecendo briga de família em churrasco.&lt;/p&gt;
&lt;p&gt;De um lado, gente dizendo que ele salvou o boot do Linux moderno. Do outro, gente tratando o projeto como se fosse um polvo arquitetural tentando abraçar o sistema operacional inteiro com tentáculos em &lt;code&gt;init&lt;/code&gt;, logs, rede, DNS, sessões, usuários, containers, boot e, se bobear, o café da manhã.&lt;/p&gt;
&lt;p&gt;A parte chata é que os dois lados têm algum motivo.&lt;/p&gt;
&lt;p&gt;O systemd resolveu problemas reais. Ele trouxe uma forma mais coerente de declarar serviços, lidar com dependências, supervisionar processos, ativar daemons sob demanda e entender o estado do sistema sem depender de uma coleção de scripts shell tentando parecer arquitetura.&lt;/p&gt;
&lt;p&gt;Mas também aumentou o acoplamento entre componentes fundamentais do Linux. E isso explica por que tanta gente nunca engoliu muito bem essa vitória.&lt;/p&gt;
&lt;p&gt;Só que a guerra do init não foi apenas uma discussão entre “boot rápido” e “filosofia Unix”. Ela foi uma transição histórica meio traumática, atravessada por decisões de distribuição, disputas de governança, ressentimento técnico, medo de lock-in e uma boa dose de drama comunitário.&lt;/p&gt;
&lt;p&gt;Antes de comparar systemd, SysVinit, Upstart, OpenRC e companhia, vale entender como a gente chegou nesse ponto.&lt;/p&gt;
&lt;p&gt;Porque o systemd não venceu porque era simpático.&lt;/p&gt;
&lt;p&gt;Ele venceu porque o modelo anterior estava velho, remendado e insuficiente para o tipo de sistema Linux que as distribuições queriam entregar.&lt;/p&gt;
&lt;h2&gt;Antes da guerra, o init já estava cansado&lt;/h2&gt;
&lt;p&gt;O problema não começou com Lennart Poettering escrevendo um post no blog e decidindo irritar metade da internet.&lt;/p&gt;
&lt;p&gt;O modelo clássico do SysVinit já carregava sinais de desgaste fazia tempo.&lt;/p&gt;
&lt;p&gt;Ele era baseado em scripts shell, runlevels e convenções de diretório como &lt;code&gt;/etc/init.d&lt;/code&gt; e &lt;code&gt;/etc/rc?.d&lt;/code&gt;. Funcionava. Durante muito tempo, funcionou bem o suficiente. Mas “funcionou bem o suficiente” é aquela frase que geralmente aparece antes de alguém precisar manter um servidor em produção às três da manhã.&lt;/p&gt;
&lt;p&gt;No SysVinit tradicional, iniciar um serviço significava executar um script. Parar um serviço significava executar outro trecho do mesmo script. Saber se um serviço estava vivo podia depender de PID files, heurísticas, convenções e fé. Muita fé.&lt;/p&gt;
&lt;p&gt;Isso não quer dizer que o mundo SysV era burro ou parado.&lt;/p&gt;
&lt;p&gt;Distribuições adicionaram melhorias. O Debian, por exemplo, teve mecanismos como &lt;a href=&quot;https://manpages.debian.org/unstable/insserv/insserv.8.en.html&quot;&gt;&lt;code&gt;insserv&lt;/code&gt;&lt;/a&gt;, para ordenar scripts com base em dependências declaradas em headers LSB, e &lt;a href=&quot;https://manpages.debian.org/bookworm/startpar/startpar.1.en.html&quot;&gt;&lt;code&gt;startpar&lt;/code&gt;&lt;/a&gt;, para execução paralela.&lt;/p&gt;
&lt;p&gt;Então não é tecnicamente correto dizer que o SysVinit ficou eternamente preso a uma sequência linear e inocente de scripts. O mundo real era mais complexo.&lt;/p&gt;
&lt;p&gt;Mas essas melhorias eram remendos sobre um modelo centrado em scripts.&lt;/p&gt;
&lt;p&gt;A base continuava frágil para supervisionar processos complexos, lidar com dependências dinâmicas, ativação sob demanda, rastreamento confiável de processos filhos e integração com recursos modernos do kernel.&lt;/p&gt;
&lt;p&gt;O Linux tinha mudado. O init, nem tanto.&lt;/p&gt;
&lt;h2&gt;Upstart parecia o futuro por alguns anos&lt;/h2&gt;
&lt;p&gt;Antes do systemd virar o padrão óbvio das principais distribuições, o candidato mais forte a substituir o SysVinit era o Upstart.&lt;/p&gt;
&lt;p&gt;O Upstart nasceu na Canonical e foi adotado pelo Ubuntu. A ideia era trocar parte da rigidez do SysVinit por um modelo orientado a eventos. Em vez de depender apenas de runlevels e scripts sequenciais, serviços poderiam reagir a eventos do sistema.&lt;/p&gt;
&lt;p&gt;Isso parecia um caminho natural.&lt;/p&gt;
&lt;p&gt;O mundo desktop estava ficando mais dinâmico. Hardware aparecia e sumia. Interfaces de rede mudavam. Sessões gráficas ficavam mais complexas. Sistemas precisavam reagir a eventos em vez de apenas executar uma lista de scripts no boot e torcer para tudo continuar igual.&lt;/p&gt;
&lt;p&gt;O Upstart também tinha uma vantagem política importante: ele prometia uma transição menos traumática. Ainda conseguia conviver com scripts SysV, o que tornava a migração mais palatável.&lt;/p&gt;
&lt;p&gt;Só que o Upstart não virou o ponto de convergência do ecossistema.&lt;/p&gt;
&lt;p&gt;O Fedora planejou trocar Upstart por systemd no Fedora 15. A própria página de feature do Fedora descrevia o systemd como substituto para SysVinit e Upstart, destacando paralelização agressiva, ativação por socket e D-Bus, uso de cgroups e lógica transacional de dependências. Na prática, o Fedora queria algo mais integrado ao Linux moderno do que o Upstart oferecia.&lt;/p&gt;
&lt;p&gt;E aí a transição deixou de ser apenas técnica.&lt;/p&gt;
&lt;p&gt;Quando uma distribuição grande escolhe uma tecnologia, é uma decisão. Quando várias escolhem a mesma, vira gravidade.&lt;/p&gt;
&lt;h2&gt;Fedora puxou a fila&lt;/h2&gt;
&lt;p&gt;O Fedora foi uma das primeiras grandes distribuições a abraçar o systemd com força.&lt;/p&gt;
&lt;p&gt;A página &lt;a href=&quot;https://fedoraproject.org/wiki/Features/systemd&quot;&gt;&lt;code&gt;Features/systemd&lt;/code&gt;&lt;/a&gt; mirava o Fedora 15 e dizia explicitamente que o plano era tornar o systemd o padrão, substituindo o Upstart. Também deixava claro que a compatibilidade com scripts SysV seria importante durante a migração.&lt;/p&gt;
&lt;p&gt;Isso é um detalhe importante.&lt;/p&gt;
&lt;p&gt;O systemd não entrou no mundo prometendo “joguem tudo fora amanhã”. Ele entrou prometendo uma ponte: suporte a scripts antigos, unidades nativas para serviços novos e uma arquitetura mais moderna por baixo.&lt;/p&gt;
&lt;p&gt;A promessa era sedutora para mantenedores de distribuição.&lt;/p&gt;
&lt;p&gt;Dava para migrar aos poucos. Dava para empacotar serviços com units nativas. Dava para manter compatibilidade por um tempo. Dava para melhorar boot, supervisão e introspecção sem exigir que todo software do planeta fosse reescrito no mesmo dia.&lt;/p&gt;
&lt;p&gt;Esse “por um tempo” é onde mora a ironia.&lt;/p&gt;
&lt;p&gt;Porque compatibilidade temporária, em infraestrutura, geralmente vira contrato emocional eterno. E quando o projeto finalmente começa a desmontar a ponte, sempre aparece alguém dizendo: “mas eu ainda estava usando”.&lt;/p&gt;
&lt;h2&gt;Arch fez do jeito Arch&lt;/h2&gt;
&lt;p&gt;O Arch Linux adotou systemd como padrão em novas instalações em outubro de 2012.&lt;/p&gt;
&lt;p&gt;O comunicado foi bem direto: o grupo &lt;code&gt;base&lt;/code&gt; passou a conter &lt;code&gt;systemd-sysvcompat&lt;/code&gt;, então novas instalações passariam a iniciar com systemd por padrão. Instalações existentes não seriam afetadas imediatamente, e os pacotes &lt;code&gt;initscripts&lt;/code&gt; e &lt;code&gt;sysvinit&lt;/code&gt; ainda continuariam disponíveis por um tempo.&lt;/p&gt;
&lt;p&gt;Ou seja: bem Arch.&lt;/p&gt;
&lt;p&gt;Sem cerimônia demais. Sem três camadas de abstração emocional. O recado era basicamente: “isso aqui é o padrão novo; se você tem instalação antiga, a wiki está ali”.&lt;/p&gt;
&lt;p&gt;Mas mesmo no Arch havia o ponto central da transição: alguns pacotes ainda não tinham units nativas e podiam continuar usando scripts legados por um período. A migração não era um botão mágico. Era uma troca gradual, pacote por pacote, serviço por serviço.&lt;/p&gt;
&lt;p&gt;O systemd venceu também porque conseguiu ser adotado incrementalmente.&lt;/p&gt;
&lt;p&gt;Isso não torna a transição indolor. Só torna possível.&lt;/p&gt;
&lt;h2&gt;Debian virou o campo de batalha&lt;/h2&gt;
&lt;p&gt;Se Fedora foi a vanguarda técnica e Arch foi a migração pragmática, o Debian foi o ringue principal.&lt;/p&gt;
&lt;p&gt;A decisão do Debian sobre o init padrão para o Jessie foi uma das discussões mais famosas da história recente das distribuições Linux. Não porque ninguém soubesse iniciar um serviço. Mas porque Debian não é só uma distribuição. É um projeto com governança própria, cultura própria e um peso enorme no ecossistema.&lt;/p&gt;
&lt;p&gt;Quando o Debian escolhe uma direção, derivados sentem o impacto.&lt;/p&gt;
&lt;p&gt;O Comitê Técnico do Debian discutiu systemd, Upstart, OpenRC e SysVinit. A disputa ficou especialmente quente entre systemd e Upstart. Em 2014, a decisão terminou com voto de desempate do presidente do comitê a favor do systemd, como coberto pela LWN em &lt;a href=&quot;https://lwn.net/Articles/584508/&quot;&gt;&lt;code&gt;Debian decides on systemd—for now&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Esse “for now” era importante.&lt;/p&gt;
&lt;p&gt;A decisão não encerrou a polêmica. Ela apenas definiu o caminho para o Jessie.&lt;/p&gt;
&lt;p&gt;O debate envolvia mais do que recurso técnico. Havia uma preocupação real com acoplamento. Um dos pontos mais sensíveis era se pacotes poderiam depender de um init específico rodando como PID 1. Em outras palavras: Debian deveria aceitar um ecossistema onde componentes de desktop e serviços começassem a presumir systemd?&lt;/p&gt;
&lt;p&gt;Esse era o coração da briga.&lt;/p&gt;
&lt;p&gt;Não era apenas “qual init é melhor?”. Era “que tipo de distribuição o Debian quer ser?”.&lt;/p&gt;
&lt;p&gt;Uma distribuição onde systemd é o padrão, mas alternativas seguem viáveis?&lt;/p&gt;
&lt;p&gt;Ou uma distribuição onde o systemd vira tão central que alternativas passam a existir só no papel, mantidas na base da teimosia e de patches?&lt;/p&gt;
&lt;p&gt;A pergunta era boa. Ainda é.&lt;/p&gt;
&lt;h2&gt;Ubuntu perdeu graciosamente, mais ou menos&lt;/h2&gt;
&lt;p&gt;O Ubuntu tinha seu próprio init: Upstart.&lt;/p&gt;
&lt;p&gt;Então a adoção do systemd pelo Debian colocou a Canonical em uma posição desconfortável. Continuar insistindo no Upstart significaria manter uma divergência pesada em relação ao Debian, justamente a base técnica do Ubuntu.&lt;/p&gt;
&lt;p&gt;No Ubuntu 15.04, o systemd substituiu o Upstart como gerenciador padrão de boot e serviços em quase todos os sabores, exceto Ubuntu Touch. As &lt;a href=&quot;https://wiki.ubuntu.com/VividVervet/ReleaseNotes&quot;&gt;&lt;code&gt;release notes do Ubuntu 15.04&lt;/code&gt;&lt;/a&gt; ainda indicavam que o Upstart continuava controlando sessões de usuário e que havia caminho para bootar com Upstart pelo GRUB, mas o padrão já tinha mudado.&lt;/p&gt;
&lt;p&gt;Essa parte é importante porque mostra que a guerra não terminou com um “todo mundo percebeu que systemd era perfeito”.&lt;/p&gt;
&lt;p&gt;Terminou porque manter alternativas divergentes ficou caro.&lt;/p&gt;
&lt;p&gt;Distribuições não tomam decisões só com base em pureza arquitetural. Elas tomam decisões com base em manutenção, integração, quantidade de patches, disponibilidade de mantenedores, compatibilidade com upstream e pressão do ecossistema.&lt;/p&gt;
&lt;p&gt;O Ubuntu não precisava amar o systemd para adotá-lo.&lt;/p&gt;
&lt;p&gt;Bastava a conta da divergência ficar ruim demais.&lt;/p&gt;
&lt;h2&gt;E aí veio o Devuan&lt;/h2&gt;
&lt;p&gt;A reação mais simbólica à adoção do systemd no Debian foi o Devuan.&lt;/p&gt;
&lt;p&gt;O Devuan nasceu como um fork do Debian com a proposta de manter uma distribuição sem systemd como padrão. Ele virou um lembrete permanente de que a briga não era só sobre comandos diferentes para iniciar serviço.&lt;/p&gt;
&lt;p&gt;Era sobre confiança.&lt;/p&gt;
&lt;p&gt;Para parte da comunidade, o systemd representava uma centralização perigosa demais. Para outra parte, a resistência parecia nostalgia disfarçada de princípio técnico.&lt;/p&gt;
&lt;p&gt;As duas leituras são simplistas quando aparecem sozinhas.&lt;/p&gt;
&lt;p&gt;Existia nostalgia, sim. Mas também existiam preocupações legítimas.&lt;/p&gt;
&lt;p&gt;E existia pragmatismo técnico, sim. Mas também existia uma tendência real de concentração em torno de um projeto só.&lt;/p&gt;
&lt;p&gt;O Devuan não precisava “vencer” para provar um ponto. O simples fato de existir já mostrava que uma parte da comunidade não queria seguir a corrente principal sem resistência.&lt;/p&gt;
&lt;h2&gt;As principais polêmicas da época&lt;/h2&gt;
&lt;p&gt;A guerra do init foi barulhenta porque juntou várias discussões diferentes no mesmo saco.&lt;/p&gt;
&lt;p&gt;A primeira era a filosofia Unix.&lt;/p&gt;
&lt;p&gt;O argumento clássico dizia que sistemas deveriam ser compostos por ferramentas pequenas, independentes e combináveis. O systemd parecia ir na direção contrária: uma suite integrada, com vários componentes coordenados, APIs próprias e um centro de gravidade cada vez maior.&lt;/p&gt;
&lt;p&gt;A crítica fazia sentido, mas às vezes era mal formulada.&lt;/p&gt;
&lt;p&gt;Chamar systemd de “um único binário gigante que faz tudo” sempre foi tecnicamente errado. O systemd é uma suite de componentes. O próprio site oficial descreve o projeto como uma &lt;a href=&quot;https://systemd.io/&quot;&gt;suite de blocos básicos para um sistema Linux&lt;/a&gt;, com PID 1, gerenciador de serviços, logging, configuração de hostname, tempo, usuários logados, containers, rede, DNS e outras peças.&lt;/p&gt;
&lt;p&gt;A crítica séria não é “é tudo um binário”.&lt;/p&gt;
&lt;p&gt;A crítica séria é: “muita coisa fundamental passou a orbitar o mesmo projeto”.&lt;/p&gt;
&lt;p&gt;A segunda polêmica era o journald.&lt;/p&gt;
&lt;p&gt;Para muita gente, trocar logs textuais tradicionais por um journal binário parecia uma afronta. A caricatura era simples: “acabaram com &lt;code&gt;/var/log&lt;/code&gt;”. Só que não era bem assim. O journald podia coexistir com syslog, encaminhar mensagens e ser configurado de várias formas.&lt;/p&gt;
&lt;p&gt;A crítica correta não era “não existem mais logs de texto”.&lt;/p&gt;
&lt;p&gt;A crítica correta era: “agora existe uma camada central com formato próprio, ferramentas próprias e semântica própria para consultar parte importante do estado do sistema”.&lt;/p&gt;
&lt;p&gt;Isso tem vantagens. Também tem custo.&lt;/p&gt;
&lt;p&gt;A terceira polêmica era o acoplamento com desktops modernos.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;systemd-logind&lt;/code&gt; virou uma peça importante para sessões, seats, inibição de suspensão e diretórios runtime de usuário. Isso impactou ambientes gráficos, gerenciadores de login e distribuições que queriam usar outro init. A crítica não era apenas ao PID 1, mas ao fato de componentes do desktop passarem a depender de APIs associadas ao systemd.&lt;/p&gt;
&lt;p&gt;A quarta era portabilidade.&lt;/p&gt;
&lt;p&gt;O systemd foi desenhado para Linux. Ele usa recursos específicos do kernel Linux, como cgroups, de forma central. Para quem vinha de uma tradição mais Unix-like e portável entre diferentes sistemas, isso parecia uma ruptura.&lt;/p&gt;
&lt;p&gt;Para os defensores, era justamente o ponto: parar de fingir portabilidade genérica e usar bem o Linux real.&lt;/p&gt;
&lt;p&gt;A quinta era social.&lt;/p&gt;
&lt;p&gt;A discussão sobre systemd ficou pessoal demais, rápido demais. Houve crítica técnica legítima, mas também houve hostilidade, ataque pessoal e muito ruído. Isso é péssimo porque degrada a discussão: quem critica vira automaticamente “dinossauro”, quem defende vira automaticamente “fanboy de Red Hat”, e ninguém precisa mais pensar.&lt;/p&gt;
&lt;p&gt;É confortável. E inútil.&lt;/p&gt;
&lt;p&gt;O resultado é que systemd virou menos uma tecnologia e mais um teste de personalidade.&lt;/p&gt;
&lt;h2&gt;Agora sim: o comparativo técnico importa&lt;/h2&gt;
&lt;p&gt;Depois de todo esse contexto histórico, o comparativo técnico fica mais honesto.&lt;/p&gt;
&lt;p&gt;Porque a pergunta nunca foi apenas “qual init inicia serviço mais rápido?”.&lt;/p&gt;
&lt;p&gt;A pergunta era: qual modelo faz mais sentido para um Linux moderno, com desktops complexos, containers, cgroups, dispositivos dinâmicos, unidades de usuário, timers, sockets, sessões gráficas, virtualização e um ecossistema enorme de pacotes?&lt;/p&gt;
&lt;p&gt;O SysVinit representava simplicidade histórica, previsibilidade e uma quantidade absurda de conhecimento acumulado. Mas também representava scripts shell frágeis, supervisão limitada e dificuldade para modelar dependências modernas.&lt;/p&gt;
&lt;p&gt;O Upstart tentou resolver parte disso com eventos. Foi importante, teve adoção real e parecia o caminho natural por alguns anos. Mas não virou a fundação comum das principais distribuições.&lt;/p&gt;
&lt;p&gt;OpenRC, runit e s6 seguem sendo alternativas tecnicamente respeitáveis, cada uma com suas escolhas. OpenRC mantém um modelo mais próximo da tradição de init com dependências explícitas e boa legibilidade. runit e s6 valorizam supervisão simples e composição. Em certos ambientes, especialmente sistemas menores, servidores minimalistas ou distribuições específicas, fazem bastante sentido.&lt;/p&gt;
&lt;p&gt;Mas o systemd venceu no Linux mainstream porque ofereceu um pacote completo.&lt;/p&gt;
&lt;p&gt;E essa frase é elogio e crítica ao mesmo tempo.&lt;/p&gt;
&lt;h2&gt;O que o systemd mudou de verdade&lt;/h2&gt;
&lt;p&gt;O systemd foi anunciado publicamente em 2010, no texto clássico de Lennart Poettering, &lt;a href=&quot;https://0pointer.de/blog/projects/systemd.html&quot;&gt;&lt;code&gt;Rethinking PID 1&lt;/code&gt;&lt;/a&gt;. A proposta não era só trocar um binário chamado &lt;code&gt;init&lt;/code&gt; por outro. A proposta era repensar o papel do processo PID 1 em um sistema Linux moderno.&lt;/p&gt;
&lt;p&gt;No Linux, o PID 1 é o primeiro processo em user space. Ele nasce depois do kernel e vira responsável por iniciar o resto do sistema. Isso não é pouca coisa. Se o PID 1 quebra, o sistema não fica “meio triste”. Ele entra em crise existencial.&lt;/p&gt;
&lt;p&gt;O systemd assumiu esse papel com uma ideia central: em vez de iniciar scripts soltos, ele gerencia unidades.&lt;/p&gt;
&lt;p&gt;Uma unidade pode ser um serviço, um socket, um mount point, um timer, um target, um device, um path e por aí vai. A documentação de &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html&quot;&gt;&lt;code&gt;systemd.unit&lt;/code&gt;&lt;/a&gt; descreve esse modelo como a base declarativa do systemd.&lt;/p&gt;
&lt;p&gt;Na prática, isso muda bastante coisa.&lt;/p&gt;
&lt;p&gt;Em vez de escrever um script shell enorme tentando cobrir &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;restart&lt;/code&gt;, &lt;code&gt;reload&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt; e mais meia dúzia de casos especiais, você descreve o comportamento esperado de um serviço em um arquivo &lt;code&gt;.service&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Um exemplo mínimo:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[Unit]
Description=Minha aplicação
After=network.target

[Service]
Type=exec
ExecStart=/usr/local/bin/minhaapp --foreground
Restart=on-failure

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isso não é perfeito, mas é muito mais legível do que boa parte dos scripts de init que existiam no mundo real.&lt;/p&gt;
&lt;p&gt;O systemd passa a entender que existe uma unidade chamada &lt;code&gt;minhaapp.service&lt;/code&gt;, que ela deve iniciar depois de &lt;code&gt;network.target&lt;/code&gt;, que o processo principal é executado por &lt;code&gt;ExecStart&lt;/code&gt;, e que ele deve ser reiniciado em caso de falha.&lt;/p&gt;
&lt;p&gt;E o mais importante: isso não é só texto decorativo. O systemd usa essas informações para montar um grafo de dependências e executar transações de inicialização, parada e reload com muito mais contexto do que o SysVinit clássico tinha.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/systemd-a-guerra-do-init/systemd-unit-graph.svg&quot; alt=&quot;Grafo simplificado de units do systemd conectando targets, services, sockets, timers, mounts e cgroups&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;O ganho do systemd não é apenas iniciar serviços: é tratar o sistema como um grafo supervisionado de unidades.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Targets não são só runlevels com outro nome&lt;/h2&gt;
&lt;p&gt;No SysVinit, runlevels representavam estados globais do sistema. O runlevel 3, por exemplo, geralmente indicava modo multiusuário em texto; o runlevel 5, modo gráfico. O significado exato podia variar por distribuição, porque Linux adora transformar padrão em sugestão.&lt;/p&gt;
&lt;p&gt;O systemd substitui essa ideia por targets.&lt;/p&gt;
&lt;p&gt;Existe uma compatibilidade aproximada entre runlevels e targets, mas não é uma equivalência perfeita. A própria documentação de &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/247/runlevel.html&quot;&gt;&lt;code&gt;runlevel&lt;/code&gt;&lt;/a&gt; no systemd trata runlevels como uma forma obsoleta de agrupar serviços. Já &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/systemd.target.html&quot;&gt;&lt;code&gt;systemd.target&lt;/code&gt;&lt;/a&gt; descreve targets como unidades usadas para agrupar outras unidades.&lt;/p&gt;
&lt;p&gt;A diferença prática é que vários targets podem estar ativos ao mesmo tempo. Eles não são apenas “modos globais exclusivos”. São pontos de sincronização e agrupamento dentro do grafo de unidades.&lt;/p&gt;
&lt;p&gt;O boot moderno com systemd gira em torno de targets como &lt;code&gt;basic.target&lt;/code&gt;, &lt;code&gt;multi-user.target&lt;/code&gt;, &lt;code&gt;graphical.target&lt;/code&gt;, &lt;code&gt;sockets.target&lt;/code&gt;, &lt;code&gt;timers.target&lt;/code&gt; e outros. A documentação de &lt;a href=&quot;https://www.man7.org/linux/man-pages/man7/bootup.7.html&quot;&gt;&lt;code&gt;bootup&lt;/code&gt;&lt;/a&gt; mostra bem esse fluxo.&lt;/p&gt;
&lt;p&gt;Isso torna o sistema mais flexível, mas também mais abstrato.&lt;/p&gt;
&lt;p&gt;E abstração, como sempre, cobra pedágio.&lt;/p&gt;
&lt;h2&gt;Cgroups: a parte que muita gente ignora&lt;/h2&gt;
&lt;p&gt;Uma das mudanças mais importantes do systemd não está no arquivo &lt;code&gt;.service&lt;/code&gt;. Está no uso de cgroups.&lt;/p&gt;
&lt;p&gt;No modelo antigo, um daemon podia fazer fork, criar subprocessos, perder relação clara com o script que o iniciou e deixar o init dependendo de PID files para descobrir quem era o processo principal.&lt;/p&gt;
&lt;p&gt;Isso funcionava até não funcionar.&lt;/p&gt;
&lt;p&gt;E quando não funcionava, sobrava para alguém rodar &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;kill&lt;/code&gt;, olhar &lt;code&gt;/var/run&lt;/code&gt;, tentar entender se o processo morreu, se o PID foi reutilizado, se o daemon fez fork duas vezes ou se o script simplesmente mentiu.&lt;/p&gt;
&lt;p&gt;O systemd usa control groups para associar processos a unidades. Quando ele inicia um serviço, os processos daquele serviço entram em uma hierarquia de cgroups vinculada à unit. Isso permite saber quais processos pertencem a qual serviço, aplicar limites de recursos e encerrar árvores inteiras de processos com mais previsibilidade.&lt;/p&gt;
&lt;p&gt;É por isso que comandos como este são tão úteis:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;systemctl status nginx.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O &lt;code&gt;systemctl&lt;/code&gt; não está apenas lendo um arquivo qualquer. Ele consulta o estado que o systemd mantém sobre aquela unit: processo principal, subprocessos, logs recentes, status, código de saída e relação com o resto do sistema.&lt;/p&gt;
&lt;p&gt;Isso não significa que PID files desapareceram do planeta. A documentação de &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html&quot;&gt;&lt;code&gt;systemd.service&lt;/code&gt;&lt;/a&gt; ainda suporta &lt;code&gt;PIDFile=&lt;/code&gt;, especialmente para serviços &lt;code&gt;Type=forking&lt;/code&gt;. Mas, para serviços modernos, o caminho mais limpo é deixar a aplicação rodar em foreground e permitir que o systemd supervisione diretamente.&lt;/p&gt;
&lt;p&gt;Um serviço legado ainda pode fazer sentido assim:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[Unit]
Description=Meu daemon legado
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/sbin/meudaemon --daemonize --pidfile /run/meudaemon.pid
PIDFile=/run/meudaemon.pid
Restart=on-failure

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mas isso é compatibilidade com o mundo antigo.&lt;/p&gt;
&lt;p&gt;O ideal moderno é algo mais direto:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[Unit]
Description=Minha aplicação moderna
After=network.target

[Service]
Type=exec
ExecStart=/usr/local/bin/minhaapp --foreground
Restart=on-failure

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Menos ritual. Mais supervisão real.&lt;/p&gt;
&lt;h2&gt;Socket activation: iniciar só quando precisa&lt;/h2&gt;
&lt;p&gt;Outra ideia importante do systemd é socket activation.&lt;/p&gt;
&lt;p&gt;Em vez de iniciar todos os serviços durante o boot e torcer para ninguém tropeçar na ordem de dependências, o systemd pode criar sockets antes dos daemons e iniciar o serviço apenas quando houver conexão. Essa ideia não nasceu do nada; o próprio Poettering já explicava isso em textos sobre &lt;a href=&quot;https://0pointer.de/blog/projects/socket-activation.html&quot;&gt;&lt;code&gt;socket activation&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O modelo é simples: uma unit &lt;code&gt;.socket&lt;/code&gt; define o ponto de escuta, e uma unit &lt;code&gt;.service&lt;/code&gt; define o serviço ativado quando aquele socket recebe tráfego.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;# /etc/systemd/system/foobar.socket
[Unit]
Description=Socket do foobard

[Socket]
ListenStream=/run/foobar.sock

[Install]
WantedBy=sockets.target
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;# /etc/systemd/system/foobar.service
[Unit]
Description=Serviço do foobard

[Service]
ExecStart=/usr/local/bin/foobard
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depois:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;systemctl daemon-reload
systemctl enable --now foobar.socket
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A documentação de &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/249/systemd.socket.html&quot;&gt;&lt;code&gt;systemd.socket&lt;/code&gt;&lt;/a&gt; detalha esse comportamento. O ganho é claro: inicialização paralela, menos dependência rígida de ordem e possibilidade de ativação sob demanda.&lt;/p&gt;
&lt;p&gt;Isso é bonito no papel e útil na prática.&lt;/p&gt;
&lt;p&gt;Também é mais uma prova de que o systemd não tentou apenas “substituir o init”. Ele tentou redesenhar a forma como serviços se relacionam com o sistema.&lt;/p&gt;
&lt;h2&gt;O journald não matou o /var/log&lt;/h2&gt;
&lt;p&gt;Poucas partes do systemd irritam tanta gente quanto o &lt;code&gt;journald&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A crítica mais comum é que ele trocou arquivos de texto simples por um formato binário. Isso é parcialmente verdade, mas a frase costuma ser usada de um jeito meio preguiçoso.&lt;/p&gt;
&lt;p&gt;O &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/247/systemd-journald.service.html&quot;&gt;&lt;code&gt;systemd-journald&lt;/code&gt;&lt;/a&gt; coleta logs do kernel, da saída padrão e erro padrão de serviços, de syslog e de outras fontes. Esses logs podem ser armazenados em journal persistente ou volátil, dependendo da configuração. O &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/journalctl.html&quot;&gt;&lt;code&gt;journalctl&lt;/code&gt;&lt;/a&gt; é a ferramenta usada para consultar esses registros.&lt;/p&gt;
&lt;p&gt;Na prática:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;journalctl -u nginx.service -b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Esse comando mostra os logs da unit &lt;code&gt;nginx.service&lt;/code&gt; no boot atual. É difícil negar que isso é conveniente.&lt;/p&gt;
&lt;p&gt;O problema é quando a explicação vira caricatura: “o journald substituiu o syslog e acabou com &lt;code&gt;/var/log&lt;/code&gt;”.&lt;/p&gt;
&lt;p&gt;Não é bem assim.&lt;/p&gt;
&lt;p&gt;O journald pode coexistir com &lt;code&gt;rsyslog&lt;/code&gt; ou &lt;code&gt;syslog-ng&lt;/code&gt;. Ele também pode encaminhar mensagens para um daemon syslog tradicional. A própria documentação do systemd sobre &lt;a href=&quot;https://systemd.io/SYSLOG/&quot;&gt;syslog&lt;/a&gt; trata essa integração.&lt;/p&gt;
&lt;p&gt;Então a crítica correta não é “o journald apagou os logs de texto da humanidade”.&lt;/p&gt;
&lt;p&gt;A crítica correta é outra: o systemd centralizou a coleta e a consulta de logs em um componente próprio, com formato próprio, ferramentas próprias e semântica própria.&lt;/p&gt;
&lt;p&gt;Isso tem vantagens reais: metadados estruturados, filtros por unit, boot, prioridade, PID, usuário e mais um monte de campos úteis.&lt;/p&gt;
&lt;p&gt;Mas também tem custo: mais dependência de ferramenta específica, mais uma peça para entender, mais uma camada entre o operador e o log bruto.&lt;/p&gt;
&lt;p&gt;De novo: trade-off.&lt;/p&gt;
&lt;p&gt;Não conto de terror.&lt;/p&gt;
&lt;h2&gt;A crítica ao “monolito” precisa mirar no alvo certo&lt;/h2&gt;
&lt;p&gt;Chamar o systemd de “um único binário gigante que controla tudo” é tecnicamente errado.&lt;/p&gt;
&lt;p&gt;O systemd é uma suite. Existem componentes diferentes: PID 1, &lt;code&gt;journald&lt;/code&gt;, &lt;code&gt;logind&lt;/code&gt;, &lt;code&gt;resolved&lt;/code&gt;, &lt;code&gt;networkd&lt;/code&gt;, &lt;code&gt;timesyncd&lt;/code&gt;, &lt;code&gt;homed&lt;/code&gt;, &lt;code&gt;boot&lt;/code&gt;, &lt;code&gt;nspawn&lt;/code&gt;, entre outros.&lt;/p&gt;
&lt;p&gt;Eles não são todos o mesmo processo. Também não são todos obrigatórios em toda instalação. A documentação sobre &lt;a href=&quot;https://systemd.io/MINIMAL_BUILDS/&quot;&gt;minimal builds&lt;/a&gt; deixa claro que há componentes centrais e componentes opcionais.&lt;/p&gt;
&lt;p&gt;Mas isso não absolve a crítica.&lt;/p&gt;
&lt;p&gt;O problema não é “um único binário”. O problema é o escopo do projeto.&lt;/p&gt;
&lt;p&gt;O systemd virou o lugar onde muita coisa do sistema Linux passou a se concentrar: init, serviços, logs, sessões, timers, sockets, DNS, rede, containers, home directories, boot loader e por aí vai.&lt;/p&gt;
&lt;p&gt;Alguns componentes são excelentes. Outros são opcionais. Outros são controversos. E alguns dão aquela sensação de que alguém olhou para o Linux e pensou: “isso aqui ainda não tem um binário nosso, que descuido”.&lt;/p&gt;
&lt;p&gt;A crítica séria ao systemd não deveria ser “é tudo um binário só”.&lt;/p&gt;
&lt;p&gt;Deveria ser: “a suite systemd cria um centro de gravidade muito forte no ecossistema Linux”.&lt;/p&gt;
&lt;p&gt;Isso é bem diferente.&lt;/p&gt;
&lt;p&gt;E muito mais difícil de responder com meme.&lt;/p&gt;
&lt;h2&gt;logind não é homed, e detalhes importam&lt;/h2&gt;
&lt;p&gt;Um erro comum em discussões sobre systemd é jogar todos os componentes no mesmo balde e chamar tudo de “systemd fazendo coisa demais”.&lt;/p&gt;
&lt;p&gt;Sim, o projeto tem escopo amplo. Mas se a crítica técnica erra o componente, ela perde força.&lt;/p&gt;
&lt;p&gt;Por exemplo: quem gerencia logins, sessões, seats, inibidores de suspensão e diretórios runtime de usuário é o &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/systemd-logind.service.html&quot;&gt;&lt;code&gt;systemd-logind&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Já o &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/256/systemd-homed.service.html&quot;&gt;&lt;code&gt;systemd-homed&lt;/code&gt;&lt;/a&gt; lida com gerenciamento de áreas home e contas de usuário associadas. É outra coisa.&lt;/p&gt;
&lt;p&gt;Dá para criticar os dois. Dá para achar que ambos expandem demais o alcance do projeto. Mas não dá para confundir as funções e depois reclamar que ninguém leva a crítica a sério.&lt;/p&gt;
&lt;p&gt;Precisão importa, principalmente quando a opinião é forte.&lt;/p&gt;
&lt;h2&gt;A compatibilidade com SysV está acabando no upstream&lt;/h2&gt;
&lt;p&gt;Durante muitos anos, uma das respostas para a crítica era: “calma, o systemd ainda consegue lidar com scripts SysV”.&lt;/p&gt;
&lt;p&gt;Isso era verdade.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;systemd-sysv-generator&lt;/code&gt; criava units automaticamente a partir de scripts SysV, permitindo compatibilidade com serviços antigos.&lt;/p&gt;
&lt;p&gt;Mas essa ponte não é garantia eterna.&lt;/p&gt;
&lt;p&gt;No upstream, o systemd v260 removeu o suporte a scripts de serviço System V. As &lt;a href=&quot;https://github.com/systemd/systemd/releases&quot;&gt;notas da release v260&lt;/a&gt; dizem explicitamente que o suporte a scripts System V foi removido e recomendam atualizar software para incluir units nativas. A página de &lt;a href=&quot;https://systemd.io/INCOMPATIBILITIES/&quot;&gt;compatibilidade com SysV&lt;/a&gt; também passou a tratar esse suporte como histórico.&lt;/p&gt;
&lt;p&gt;Isso não significa que toda distribuição removeu tudo imediatamente. Distribuições empacotam versões diferentes, aplicam patches, seguram mudanças e preservam compatibilidade quando precisam.&lt;/p&gt;
&lt;p&gt;Mas a direção do upstream é clara: unit nativa é o caminho. Script SysV é legado.&lt;/p&gt;
&lt;p&gt;E isso muda o tom da conversa.&lt;/p&gt;
&lt;p&gt;Em 2015, dava para falar em transição com camada de compatibilidade.&lt;/p&gt;
&lt;p&gt;Em 2026, essa camada já está sendo desmontada no projeto principal.&lt;/p&gt;
&lt;p&gt;Quem ainda mantém serviço com script SysV deveria começar a migrar para unit nativa antes que a gambiarra vire arqueologia operacional.&lt;/p&gt;
&lt;h2&gt;run0: porque até o sudo entrou na conversa&lt;/h2&gt;
&lt;p&gt;Como se systemd já não estivesse em assunto suficiente, a série 256 trouxe o &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/256/run0.html&quot;&gt;&lt;code&gt;run0&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;run0&lt;/code&gt; funciona como uma invocação alternativa do &lt;code&gt;systemd-run&lt;/code&gt; para executar comandos com privilégios elevados ou diferentes. Ele usa autenticação via polkit e cria um serviço isolado para executar o comando, sem depender de SetUID/SetGID como o &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;É tentador chamar isso de “substituto do sudo”, mas essa frase simplifica demais.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;sudo&lt;/code&gt; é uma ferramenta madura, amplamente usada, com um modelo conhecido de configuração via &lt;code&gt;sudoers&lt;/code&gt;. O &lt;code&gt;run0&lt;/code&gt; segue outra lógica: ele se apoia no systemd, em polkit e em units transitórias.&lt;/p&gt;
&lt;p&gt;Isso não quer dizer que seja ruim.&lt;/p&gt;
&lt;p&gt;Quer dizer que ele carrega a filosofia do systemd até no ato de elevar privilégio: em vez de “rodar um comando como root”, ele cria um contexto gerenciado pelo service manager.&lt;/p&gt;
&lt;p&gt;Tecnicamente interessante.&lt;/p&gt;
&lt;p&gt;Filosoficamente previsível.&lt;/p&gt;
&lt;p&gt;Socialmente inflamável.&lt;/p&gt;
&lt;p&gt;Ou seja: systemd sendo systemd.&lt;/p&gt;
&lt;h2&gt;O systemd venceu porque o mundo mudou&lt;/h2&gt;
&lt;p&gt;A tese mais honesta é esta: o systemd venceu porque o Linux que as distribuições queriam entregar já não cabia bem no modelo clássico de init.&lt;/p&gt;
&lt;p&gt;Máquinas modernas têm serviços dinâmicos, dispositivos aparecendo e sumindo, sessões gráficas complexas, containers, virtualização, cgroups, timers, sockets, unidades de usuário, dependências condicionais e integração profunda com o desktop.&lt;/p&gt;
&lt;p&gt;Dá para fazer muita coisa disso sem systemd? Sim.&lt;/p&gt;
&lt;p&gt;Dá para fazer com OpenRC, runit, s6, supervision trees e outras abordagens? Sim.&lt;/p&gt;
&lt;p&gt;Dá para fazer de forma integrada, padronizada e amplamente adotada entre as principais distribuições Linux? Aí a conversa muda.&lt;/p&gt;
&lt;p&gt;O systemd não ganhou por ser minimalista.&lt;/p&gt;
&lt;p&gt;Ele ganhou por ser abrangente.&lt;/p&gt;
&lt;p&gt;E essa abrangência é justamente a fonte da vitória e da crítica.&lt;/p&gt;
&lt;h2&gt;O custo da padronização&lt;/h2&gt;
&lt;p&gt;Padronização é confortável até você perceber que ela também concentra poder técnico.&lt;/p&gt;
&lt;p&gt;Quando quase tudo no Linux mainstream assume systemd, projetos começam a depender de APIs, comportamentos e componentes associados a ele. Distribuições alternativas precisam manter compatibilidade, adaptar pacotes ou remar contra uma corrente cada vez mais forte.&lt;/p&gt;
&lt;p&gt;Isso não torna o systemd “maligno”.&lt;/p&gt;
&lt;p&gt;Mas torna o ecossistema menos plural em uma camada muito sensível.&lt;/p&gt;
&lt;p&gt;A filosofia Unix clássica defendia ferramentas pequenas, independentes e combináveis. O systemd segue outra filosofia: componentes integrados, estado centralizado, interfaces comuns e coordenação forte.&lt;/p&gt;
&lt;p&gt;Não é que uma seja automaticamente certa e a outra automaticamente errada.&lt;/p&gt;
&lt;p&gt;Mas são visões diferentes de sistema.&lt;/p&gt;
&lt;p&gt;O problema é fingir que essa diferença não existe.&lt;/p&gt;
&lt;p&gt;O systemd trouxe ordem onde havia muita cola shell. Trouxe introspecção onde havia script opaco. Trouxe supervisão real onde havia PID file. Trouxe um modelo declarativo onde havia convenção espalhada.&lt;/p&gt;
&lt;p&gt;Mas também trouxe um centro de gravidade enorme.&lt;/p&gt;
&lt;p&gt;E centros de gravidade enormes são úteis até virarem dependência inevitável.&lt;/p&gt;
&lt;h2&gt;Então o systemd é bom ou ruim?&lt;/h2&gt;
&lt;p&gt;Essa pergunta é ruim.&lt;/p&gt;
&lt;p&gt;O systemd é uma resposta técnica forte para problemas reais do Linux moderno. Ele é melhor que o SysVinit clássico em supervisão, dependências, introspecção, ativação sob demanda e integração com recursos do kernel como cgroups.&lt;/p&gt;
&lt;p&gt;Ao mesmo tempo, ele representa uma mudança de filosofia.&lt;/p&gt;
&lt;p&gt;Sai o modelo de várias peças pequenas e relativamente independentes; entra uma suite integrada que define grande parte da experiência operacional do sistema.&lt;/p&gt;
&lt;p&gt;Quem diz que systemd é só “bloat” ignora os problemas reais que ele resolveu.&lt;/p&gt;
&lt;p&gt;Quem diz que systemd é apenas progresso inevitável ignora os custos reais que ele trouxe.&lt;/p&gt;
&lt;p&gt;A resposta adulta é mais chata: systemd é uma engenharia pragmática, poderosa e expansiva. Ele resolveu um problema enorme e criou outro tipo de problema no caminho.&lt;/p&gt;
&lt;p&gt;No fim, a guerra do init acabou não porque todo mundo concordou.&lt;/p&gt;
&lt;p&gt;Acabou porque as principais distribuições seguiram em frente.&lt;/p&gt;
&lt;p&gt;O systemd venceu.&lt;/p&gt;
&lt;p&gt;Mas venceu do jeito mais systemd possível: não apenas substituindo o init, e sim redefinindo o que o init deveria ser.&lt;/p&gt;
&lt;p&gt;E talvez seja exatamente por isso que tanta gente ainda discute.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>A Ilusão da Conveniência: AUR, Helpers e o Preço do Controle no Arch Linux</title><link>https://blog.kristyan.dev/posts/a-ilusao-da-conveniencia-aur-helpers-e-o-preco-do-controle-no-arch-linux</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/a-ilusao-da-conveniencia-aur-helpers-e-o-preco-do-controle-no-arch-linux</guid><description>Funcionamento do Arch User Repository, o papel dos AUR helpers, os riscos da abstração cega e como manter a soberania sobre o seu sistema.</description><pubDate>Fri, 29 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Uma das primeiras coisas que muitos usuários fazem ao instalar o Arch Linux é baixar um helper para o AUR, como o yay ou o paru. Na superfície, esses programas parecem mágicos, permitindo instalar praticamente qualquer software do mundo com um comando simples no terminal. No entanto, essa conveniência irrestrita mascara a verdadeira natureza do sistema operacional. O ecossistema do Arch Linux foi desenhado sob o princípio da responsabilidade técnica do usuário. Quando você transforma ferramentas de automação em caixas pretas que você não compreende, você está abrindo mão do controle e se preparando para o próximo colapso do sistema.&lt;/p&gt;
&lt;h2&gt;O que é o AUR e por que ele não é um repositório de binários&lt;/h2&gt;
&lt;p&gt;Para entender o risco da abstração, precisamos dar um passo atrás e entender a fundação. O AUR (Arch User Repository) não é um espelho de pacotes pré-compilados e validados, diferentemente dos repositórios oficiais gerenciados nativamente pelo pacman. Ele é essencialmente um gigantesco indexador de receitas de compilação criadas e mantidas por usuários aleatórios da internet.&lt;/p&gt;
&lt;p&gt;Quando você busca algo no AUR, o que você encontra é um script chamado PKGBUILD. Esse arquivo de texto dita ao sistema de onde baixar o código-fonte original e quais comandos exatos executar para compilar aquele software localmente na sua máquina. Ao contrário de instalar um binário pré-construído via pacman, baixar pacotes do repositório comunitário exige poder de processamento do seu próprio hardware, o que pode levar de alguns minutos a várias horas dependendo do tamanho do software.&lt;/p&gt;
&lt;p&gt;Para otimizar esse tempo, é fundamental garantir que o processo de compilação utilize todas as threads disponíveis da sua CPU. Você pode ajustar o arquivo de configuração do makepkg editando a diretiva apropriada.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nvim /etc/makepkg.conf

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Altere a variável de compilação para refletir o número de núcleos do seu processador, conforme o exemplo abaixo que utiliza quatro threads.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;MAKEFLAGS=&quot;-j4&quot;

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;A Anatomia Crítica de um PKGBUILD&lt;/h2&gt;
&lt;p&gt;Como a plataforma é alimentada pela comunidade, instalar um pacote sem ler seu script de instalação significa executar um código desconhecido no seu computador. A própria documentação oficial da ArchWiki traz um aviso categórico informando que AUR helpers não são suportados pelo Arch Linux e que os usuários devem conhecer o processo de construção manual para solucionar problemas.&lt;/p&gt;
&lt;p&gt;Ao abrir um arquivo PKGBUILD, sua atenção deve focar em parâmetros de segurança específicos. A variável source identifica exatamente de onde o script está buscando os arquivos. O ideal é que o domínio aponte para o repositório oficial do desenvolvedor no GitHub ou GitLab. As chaves de integridade servem para validar se o arquivo baixado não foi adulterado, enquanto as marcações depends e makedepends listam as ferramentas necessárias para a execução e compilação do código.&lt;/p&gt;
&lt;p&gt;A regra de ouro de segurança em um PKGBUILD é observar as funções de ciclo de vida. Qualquer chamada de aplicação ou comando executado fora dessas funções estruturadas é um sinal vermelho. Se você notar comandos de remoção apagando diretórios incoerentes ou strings em formato hexadecimal sendo decodificadas, aborte a instalação imediatamente. Além disso, antes de iniciar o processo, verifique a página web do pacote para conferir os comentários de outros usuários, o número de votos, as requisições de remoção e se o mantenedor possui reputação mantendo outros projetos.&lt;/p&gt;
&lt;h2&gt;O Fluxo Manual na Prática&lt;/h2&gt;
&lt;p&gt;A construção manual é um processo direto e transparente que fornece total entendimento das ações em andamento. Primeiro, você deve clonar o repositório utilizando a ferramenta git.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone https://aur.archlinux.org/librewolf-bin.git

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Após clonar os arquivos da plataforma, entre no diretório criado e execute o comando responsável pela construção e instalação.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd librewolf-bin
makepkg -si

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;O parâmetro s garante que todas as dependências oficiais sejam instaladas via pacman automaticamente, enquanto o parâmetro i orienta a instalação do pacote recém-criado no sistema. Esse método purista garante total soberania, mas possui um grande defeito prático na usabilidade de longo prazo. Para manter o software atualizado, você precisará retornar a essa mesma pasta, executar a ferramenta git para puxar as novas modificações e rodar a compilação inteira novamente de forma braçal.&lt;/p&gt;
&lt;h2&gt;O Abismo da Abstração e as Ferramentas Modernas&lt;/h2&gt;
&lt;p&gt;É exatamente para resolver o problema massante das atualizações manuais recorrentes que os helpers foram inventados. Eles automatizam o rastreamento, o download e a compilação, mas nem todos operam com a mesma filosofia técnica perante o usuário.&lt;/p&gt;
&lt;p&gt;A ferramenta yay é escrita na linguagem Go e se consolidou rapidamente na comunidade fazendo basicamente tudo que você espera de um gerenciador moderno. Ela funciona como um invólucro para o pacman, permitindo atualizar os repositórios oficiais e os projetos comunitários simultaneamente. No entanto, por padrão, esse software facilita excessivamente a negligência do usuário, permitindo pular a leitura obrigatória do PKGBUILD com um simples apertar da tecla Enter.&lt;/p&gt;
&lt;p&gt;O aplicativo paru foi desenvolvido na linguagem Rust por um dos criadores originais do yay que decidiu focar em recursos adicionais e segurança. O grande diferencial aqui é a mitigação do comportamento descuidado, já que o utilitário força você a interagir ativamente com a etapa de revisão do pacote. Se você possuir o software bat instalado no sistema, o script é renderizado com realce de sintaxe colorido direto no terminal, tornando a auditoria visual muito amigável. Outro recurso excelente é o parâmetro GC, que busca os comentários recentes da página web e os exibe no terminal para facilitar a investigação de erros de instalação.&lt;/p&gt;
&lt;p&gt;O utilitário pikaur, por sua vez, é construído em Python e foca drasticamente na eficiência do tempo do usuário através de uma abordagem interativa inteligente. Quem já compilou pacotes robustos sabe a frustração de descobrir horas depois que o processo foi paralisado no meio do caminho aguardando uma confirmação. O pikaur antecipa todas as perguntas, revisões de pacotes e resoluções de conflitos estruturais antes mesmo de iniciar a construção. Você responde todas as pendências nos primeiros instantes e pode abandonar a máquina com a certeza plena de que a instalação finalizará sem bloqueios.&lt;/p&gt;
&lt;p&gt;Em hipótese alguma recomendo utilizar gerenciadores gráficos como o pamac para lidar com compilações comunitárias. Ferramentas visuais abstraem o processo sistêmico de tal forma que quebram frequentemente sob a menor anomalia, criando usuários completamente perdidos que não conseguem decifrar um aviso de erro trivial no terminal.&lt;/p&gt;
&lt;h2&gt;A Terceira Via com o Chaotic AUR&lt;/h2&gt;
&lt;p&gt;Existe um cenário intermediário engenhoso para quem precisa de dezenas de softwares complexos da comunidade, mas se recusa a perder horas preciosas do dia compilando bibliotecas imensas. O Chaotic AUR é um repositório comunitário automatizado de terceiros que compila os pacotes mais populares do AUR e os entrega como binários já prontos para uso.&lt;/p&gt;
&lt;p&gt;Para integrar esse recurso, você precisa inicialmente importar as chaves criptográficas diretamente dos servidores de homologação.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo pacman-key --recv-key 3056513887B78AEB --keyserver keyserver.ubuntu.com
sudo pacman-key --lsign-key 3056513887B78AEB

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Prossiga instalando os pacotes responsáveis pelo chaveiro de segurança e pela lista de espelhos oficiais.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo pacman -U &apos;https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst&apos;
sudo pacman -U &apos;https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst&apos;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finalize o procedimento adicionando a declaração do repositório no final do seu arquivo de configuração central do gerenciador de pacotes.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[chaotic-aur]
Include = /etc/pacman.d/chaotic-mirrorlist

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Após atualizar a base de dados do sistema, pacotes gigantes podem ser instalados instantaneamente ignorando a etapa de construção. Vale a ressalva de que o Chaotic AUR possui um catálogo curado limitado e que transferir a confiança da sua auditoria local para uma infraestrutura remota de terceiros exige cautela.&lt;/p&gt;
&lt;h2&gt;Conclusão&lt;/h2&gt;
&lt;p&gt;Não existe nenhum demérito em utilizar ferramentas modernas para otimizar a sua rotina no terminal. Aplicativos automatizados são engrenagens fundamentais de produtividade para gerenciar um sistema exposto ao volume caótico de atualizações de uma distribuição de liberação contínua. O erro inadmissível reside na delegação absoluta da sua segurança pessoal.&lt;/p&gt;
&lt;p&gt;Utilize os automatizadores pelo mero conforto operacional, mas mantenha a destreza técnica aguçada para auditar meticulosamente os scripts inseridos no seu ambiente. Preservar o conhecimento brutal da arquitetura manual é a única garantia real de que você saberá consertar a sua estação de trabalho quando os utilitários mágicos apresentarem falhas graves. No ecossistema Arch Linux, o domínio visceral sobre a própria máquina é inegociável.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item><item><title>Hello World</title><link>https://blog.kristyan.dev/posts/hello-world</link><guid isPermaLink="true">https://blog.kristyan.dev/posts/hello-world</guid><description>Como construí este blog do zero com Astro, TypeScript e Tailwind CSS — arquitetura, decisões técnicas e o fluxo de desenvolvimento.</description><pubDate>Mon, 25 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Todo blog de dev começa com um &quot;Hello World&quot;. Este não seria diferente.&lt;/p&gt;
&lt;p&gt;Este é o primeiro post oficial, e nada mais justo do que escrever sobre como o próprio blog foi construído: as decisões técnicas, a arquitetura, o que funcionou e o que eu teria feito diferente.&lt;/p&gt;
&lt;h2&gt;Por que um blog?&lt;/h2&gt;
&lt;p&gt;Há um tempo venho sentindo que não documentava o suficiente o que aprendo. Livros, projetos, experimentos... tudo ficava na minha cabeça ou em arquivos avulsos. Um blog resolve isso. Não porque alguém necessariamente vai ler, mas porque escrever sobre algo é a melhor forma de descobrir se você realmente entendeu.&lt;/p&gt;
&lt;h2&gt;A stack&lt;/h2&gt;
&lt;p&gt;A escolha foi clara desde o início: queria algo estático, simples de manter e sem banco de dados. Nada de CMS, nada de painel administrativo. Só arquivos Markdown no repositório.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Astro&lt;/strong&gt; foi a escolha natural para o framework. Ele foi feito exatamente para esse caso de uso: sites com pouco ou nenhum JavaScript no cliente, geração estática e suporte nativo a Markdown com Content Collections.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TypeScript&lt;/strong&gt; para tudo. Sem &lt;code&gt;any&lt;/code&gt;, sem atalhos. O schema do frontmatter é validado com &lt;strong&gt;Zod&lt;/strong&gt; em tempo de build. Se um campo obrigatório estiver faltando, o build quebra. Isso evita posts malformados chegarem em produção.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tailwind CSS&lt;/strong&gt; para estilização. Sem CSS modules, sem styled-components. Só utilitários. O resultado é um bundle pequeno e componentes fáceis de escanear.&lt;/p&gt;
&lt;h2&gt;Arquitetura&lt;/h2&gt;
&lt;p&gt;A estrutura do projeto ficou assim:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tree -I &apos;node_modules|.astro&apos;
.
├── astro.config.mjs
├── content
│   └── posts
│       └── hello-world.md
├── package.json
├── package-lock.json
├── public
├── README.md
├── src
│   ├── components
│   │   ├── Footer.astro
│   │   ├── Header.astro
│   │   ├── MarkdownContent.astro
│   │   ├── PostCard.astro
│   │   └── ThemeToggle.astro
│   ├── content.config.ts
│   ├── layouts
│   │   ├── BaseLayout.astro
│   │   └── PostLayout.astro
│   ├── lib
│   │   ├── markdown.ts
│   │   ├── posts.ts
│   │   └── seo.ts
│   ├── pages
│   │   ├── 404.astro
│   │   ├── index.astro
│   │   └── posts
│   │       └── [slug].astro
│   ├── styles
│   │   └── global.css
│   └── types
│       └── post.ts
├── tailwind.config.mjs
├── tsconfig.json
└── vercel.json

12 directories, 24 files
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Os posts vivem fora do &lt;code&gt;src/&lt;/code&gt;, dentro de &lt;code&gt;content/posts/&lt;/code&gt;. O Astro lê essa pasta automaticamente via Content Collections. Nenhum import manual, nenhuma rota registrada na mão. Crio um arquivo &lt;code&gt;.md&lt;/code&gt;, salvo, e ele aparece.&lt;/p&gt;
&lt;p&gt;A lógica de leitura dos posts está isolada em &lt;code&gt;src/lib/posts.ts&lt;/code&gt;. Essa função filtra posts não publicados, ordena por data e é reutilizada em todas as páginas que precisam listar posts.&lt;/p&gt;
&lt;h2&gt;Roteamento&lt;/h2&gt;
&lt;p&gt;Duas rotas principais:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt; lista todos os posts publicados&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/posts/[slug]&lt;/code&gt; renderiza o post completo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;O slug vem diretamente do nome do arquivo. &lt;code&gt;hello-world.md&lt;/code&gt; vira &lt;code&gt;/posts/hello-world&lt;/code&gt;. Sem configuração extra.&lt;/p&gt;
&lt;h2&gt;Dark mode&lt;/h2&gt;
&lt;p&gt;O dark mode é controlado por classe CSS no elemento &lt;code&gt;html&lt;/code&gt;, com preferência salva no &lt;code&gt;localStorage&lt;/code&gt;. Um script inline no &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; aplica o tema antes do primeiro render para evitar flash de tema errado.&lt;/p&gt;
&lt;h2&gt;Deploy&lt;/h2&gt;
&lt;p&gt;O blog é hospedado na &lt;strong&gt;Vercel&lt;/strong&gt;. O deploy é automatizado via &lt;strong&gt;GitHub Actions&lt;/strong&gt;: qualquer push para &lt;code&gt;main&lt;/code&gt; que altere um arquivo dentro de &lt;code&gt;content/posts/&lt;/code&gt; dispara um webhook que aciona a Vercel para reconstruir o site.&lt;/p&gt;
&lt;p&gt;Escrevo o post, faço o commit, faço o push. Em alguns segundos está no ar.&lt;/p&gt;
&lt;h2&gt;O que ficou de fora&lt;/h2&gt;
&lt;p&gt;Intencionalmente não implementei:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Paginação&lt;/strong&gt; - por enquanto não preciso&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Busca&lt;/strong&gt; - idem&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RSS&lt;/strong&gt; - está nos planos&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Syntax highlighting&lt;/strong&gt; - vem em breve&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A ideia foi lançar simples e ir adicionando conforme a necessidade real aparecer. Overengineering em blog pessoal é uma armadilha fácil.&lt;/p&gt;
&lt;h2&gt;Considerações finais&lt;/h2&gt;
&lt;p&gt;O projeto inteiro tem menos de 25 arquivos. O build leva poucos segundos. Adicionar um post novo leva menos de um minuto.&lt;/p&gt;
&lt;p&gt;É exatamente o que eu queria.&lt;/p&gt;
&lt;p&gt;Até o próximo.&lt;/p&gt;
</content:encoded><dc:creator>Kristyan Carvalho</dc:creator></item></channel></rss>