Sistemas imutáveis são o futuro?
“Na minha máquina funciona” é um dos maiores memes da programação, com a evolução da tecnologia, especialmente por conta dos contêineres, essa frase deixou e ser tão utilizada. A ideia dos contêineres nesse âmbito é muito simples, “se só na sua máquina funciona, a gente vai enviar a sua máquina para o deploy”.
Essa é uma super simplificação, mas tem tudo a ver com a pergunta que o membro do canal, Renan Santos enviou pra gente no Diolinux Responde deste mês.
“Existe uma vantagem prática em sistemas imutáveis como o Vanilla OS? Um Ubuntu imutável todo em snap seria mais estável?”
Uma pergunta muito interessante e pertinente, porque apesar disso estar sentido discutido agora em sistemas de desktop com maior ênfase, a imutabilidade estava aqui o tempo todo, e só você não viu.
Hoje a gente explorará sistemas imutáveis e como eles se relacionam com segurança, confiabilidade e praticidade para você que usa e para quem desenvolve os softwares.
Um sistema mais seguro
Um dos conceitos que queremos abordar hoje é de “Defense in Depth”, um assunto mais recorrente no meio de cibersegurança, mas que se relaciona diretamente com a ideia de sistemas imutáveis. Defense in Depth, ou “defesa profunda” numa tradução livre, é um termo utilizado em cibersegurança para designar uma estratégia de defesa digital que consiste em múltiplas medidas complementares e suplementares para proteger os assets de indivíduos e organizações.
Apesar de soar um pouco complicado, a ideia central é simples e intuitiva. Com múltiplas camadas e técnicas de proteção, se uma delas falha, existe a possibilidade de mitigar o ataque.
É como se você quisesse proteger o seu castelo e para isso você colocasse uma porta de metal na entrada, enquanto todos os muros são muito altos, num âmbito de defense in depth, além disso, você teria um fosso com crocodilos ao redor, guardas no castelo e arame farpado sobre os muros.
Muitos fatores precisariam ser comprometidos caso alguém queira invadir o castelo, esse conceito se aplica a tecnologia e dados e isso tem tudo a ver com imutabilidade, visto que segurança é um dos principais benefícios disso, apesar de não ser o único.
Mas vamos dar um passo atrás, é importante que a gente desmistifique o termo “sistema imutável”, porque o nome não faz total sentido, afinal, os sistemas definitivamente não são completamente imutáveis, mas talvez eles sejam pouco mutáveis ou mutáveis sob certas circunstâncias.
O que são sistemas imutáveis?
É fácil imaginar que para um usuário de Linux comum, ouvir que um sistema é imutável, significa remover a liberdade de customizar as coisas, o que não necessariamente é verdade, na maioria, o que muda é a forma de customizar as coisas, e a possibilidade.
Sistemas diferentes podem tratar a imutabilidade de formas diferentes, mas, em geral, temos uma estrutura semelhante.
Considere a raiz de um sistema Linux comum. Dentro do “/”, temos uma abundância de pastas e arquivos, ao instalar um sistema qualquer como o Ubuntu, por exemplo, existe um estado padrão nesses arquivos, porém, conforme você atualiza o sistema e instala novos softwares, novos arquivos vão sendo criados e modificados dentro dessas pastas.
Caso você tenha acesso root, ou o seu usuário tenha privilégios de administrador, com o “sudo”, você pode modificar qualquer arquivo na base do sistema operacional. Em geral, é legal você poder alterar qualquer coisa, mas, na prática, você não realmente fica modificando arquivos em todas essas pastas, geralmente as pastas onde você terá maior influência, sobretudo no desktop, residem num único diretório, o home, onde fica a pasta do seu usuário e você mantém os seus arquivos.
Sistemas Linux tradicionais também costumam ser dependentes de seus gestores de pacotes, eles tem muita responsabilidade sobre a integridade do seu sistema. Os pacotes são atualizados individualmente, sendo tarefa do gestor de pacotes garantir que nenhuma dependência se quebre nesse processo.
Com a possibilidade de escrita na raiz do sistema, do ponto de vista de segurança, um atacante poderia modificar arquivos essenciais para o funcionamento do sistema e explorar algum tipo de falha. Como não existe nenhum tipo de compartimentalização dos softwares, com a permissão adequada, você pode coletar dados de outros programas, o que é um problema sério de segurança. É por isso que você deve evitar expor o usuário root a todo custo.
Poderíamos continuar descrevendo características de um sistema Linux tradicional, mas acho que isso é suficiente para gente fazer um comparativo básico com uma distro Linux imutável.
A forma de funcionamento e gestão de softwares num ambiente imutável é um pouco diferente.
Em sistemas imutáveis, a raiz está no modo “read-only”, ou seja, “apenas leitura”. Na prática, um sistema read-only significa que nada pode ser gravado na raiz do sistema permanentemente por um usuário comum. Ou seja, um hacker que estiver atacando um sistema assim não conseguirá colocar um script para iniciar com o sistema, porque é impossível criar ou modificar um arquivo da raiz de um Linux assim.
Porém, escrever arquivos na raiz não é necessariamente algo atrelado a uma atividade maliciosa, num sistema normal, quando você instala um software, alguns arquivos podem ir parar dentro de diversas outras pastas do sistema, /bin, /usr, /var, /lib, depende do programa.
Numa raiz imutável, não é possível instalar programas dessa forma, pela ideia ser usar essa mesma lógica de segurança para os aplicativos, se o sistema é read-only, os aplicativos também são. No Linux, esses são os flatpaks e Snaps no âmbito de desktop, e contêineres, especialmente docker, no caso de servidores, mas não se limitando a isso.
Nem toda a raiz de um sistema imutável pode ser read-only, especialmente onde a interação do usuário será constante, como em desktops, por isso, certas pastas como a sua home e /var pode ser passíveis de algum tipo de escrita. Os softwares serão instalados e alocarão arquivos somente nas pastas onde tem permissão.
Num processo de atualização de um sistema imutável, geralmente se trabalha com o conceito de imagens do sistema. Então, ao invés de utilizar um gestor de pacotes e atualizar arquivo por arquivo, pacote por pacote, se baixa uma nova imagem completa, na qual é possível dar boot com todas as modificações novas, assim como é possível fazer rollback, e voltar a utilizar a versão anterior, caso algo dê problemas.
Digamos então que de alguma forma um hacker conseguiu rodar algum aplicativo malicioso em tempo real em um sistema Linux, basta reiniciar o sistema, e a ameaça foi removida. Isso é vantagem imensa. Em sistemas que não requerem muita interação humana, como servidores e sistemas que vão rodar em dispositivos inteligentes, os sistemas serem imutáveis é uma vantagem sem par.
Sistemas operacionais mais confiáveis
No geral, os pontos positivos de sistemas imutáveis são, segurança, já que um sistema imutável não pode ser modificado, isso elimina o risco de modificações não desejadas acontecerem em um produto ou reduz o risco de um malware, como um ransonware, conseguir fazer algum estrago permanente.
A confiabilidade do sistema aumenta, por padrão, quando você faz o design de algo, é importante considerar que ele pode e falhará em algum momento que você não previu. Por esse motivo, o plano de contingência deve ser eficiente o suficiente para contornar qualquer dificuldade.
Sistemas imutáveis geralmente tem mecanismos que permitem rollback de aplicações e do próprio sistema, permitindo que você volte a um estado anterior em caso de necessidade, permitindo backups mais rápidos também.
Pode até não parecer a primeira vista, mas um sistema imutável tem uma gestão mais simples, tanto para usuários comuns e leigos, mas especialmente para desenvolvedores.
Exemplos de sistemas que são imutáveis e tem a sua raiz com modo read-only e talvez você não sabia incluem, o SteamOS da Valve que roda no Steamdeck, o Chrome OS, o Android e o macOS, além de vários outros sistemas que rodam em TVs, geladeiras, relógios e qualquer coisa inteligente, como robôs em fábricas.
As pessoas já usam sistemas imutáveis e nem sabem, mas para os desenvolvedores é algo ainda mais importante e útil. Para isso a gente precisa entender a lógica de contêineres como o docker.
Como sistemas imutáveis funcionam na prática?
Utilizemos como exemplo, o Alpine, um Linux muito pequeno que pode servir para várias coisas diferentes, uma imagem dele não é feita para ser modificada necessariamente, basta você instalar e usar com os recursos que ele oferece.
Porém, algumas pessoas precisam ter, digamos, o NodeJS para desenvolvimento, então em vez de instalar o Alpine e depois instalar o NodeJS nele, a lógica das imagens permite que você crie uma nova imagem já com as modificações prontas. É assim que nasce a imagem de Docker do Node, baseada no Alpine.
Esse mesmo conceito se aplica num desktop Linux imutável, como o Fedora Siverlblue, ou mesmo o Vanilla OS. Quando uma nova atualização acontecer, ao invés de atualizar cada um dos arquivos e pacotes no sistema manualmente, é mais fácil substituir a imagem base com todas as novidades, e deixar numa camada acima dela as customizações e arquivos dos usuários.
Isso não é exclusividade dessas distros, como eu disse, outros sistemas fazem isso também, o macOS da Apple tem uma mecânica bem interessante para fazer atualizações, funciona de uma forma parecida do Linux.
De uma forma simplificada, a pasta dos usuários, onde tem os arquivos das pessoas, além de serem criptografadas, fazem parte de um compartimento diferente do resto do sistema. Quando uma nova atualização acontece, ele baixa uma nova imagem inteira do macOS, por isso que os updates do macOS geralmente tem o tamanho do sistema operacional inteiro.
Desconecta o volume dos usuários do sistema, remove a imagem antiga e coloca a nova no lugar com todas as mudanças. Para os desenvolvedores, significa que todas as estações estarão rodando o mesmo software, com as mesmas configurações.
Algo que é muito mais fácil de reproduzir, caso um bug ocorra, já que não precisa ficar avaliando quais modificações os usuários eventualmente fizeram no sistema, mesmo que sem querer, para fazer um diagnóstico. Isso não tira a liberdade do usuário de customizar algo, no entanto, geralmente você pode contornar a base read-only de formas diferentes, dependendo do sistema.
O SteamOS por exemplo tem um comando simples para fazer isso, associado ao modo desenvolvedor da distro, no Fedora Silverblue, é esperado que, ou você faça package layering, ou crie uma imagem customizada com os detalhes que quer alterar, e então use ela como substituta no seu sistema.
Isso, na verdade, é exatamente o que uma comunidade no entorno do Fedora Silverblue chamada Universal Blue vem criando. Eles produzem imagens customizadas do Fedora, que pode ser usadas como alternativas. Elas podem já vir prontas com certos softwares e componentes, como drivers da NVIDIA, por exemplo.
As imagens podem vir até com outras interfaces gráficas, imagina que você pode mudar de GNOME para KDE, sem precisar se preocupar com dependências ou aplicativos duplicados, será o mesmo sistema, mesmos arquivos, mesmos programas, especialmente se eles forem Flatpaks.
Sistemas imutáveis podem ser mais eficientes
Outra vantagem da imutabilidade está na redução de downtime, e aqui você tem que lembrar que Linux é primariamente usado em servidores, onde ficar fora do ar pode representar a perda de muito dinheiro.
Foi estimado, por exemplo, em 2015 que cada minuto da Amazon fora do ar, custava para eles mais de 200 mil dólares, um valor que provavelmente aumentou quase 10 anos depois. Sistemas imutáveis são automatizados, geralmente, para manutenção, você consegue substituir uma imagem quebrada mantendo a produção, ou com o mínimo de downtime possível.
Reduzir os custos é outro benefício, um sistema read-only como o fedora silverblue ou o vanilla OS, usando pacotes flatpak, significa que é necessário gastar menos tempo na manutenção dos programas, já que eles nunca serão diferentes.
Problemas como o famigerado “na minha máquina funciona” deixam de existir, ou são, no mínimo, muito reduzidos. Já que o mesmo software é disponibilizado para todos.
Do ponto de vista empresarial, ainda é possível mencionar como algo positivo, a questão de escalabilidade, se tenho um servidor que precisa ser configurado de uma determinada forma, com determinados softwares e preciso de mais servidores desses para manter o meu site no ar, basta fazer a implementação de uma imagem customizada, já que não existe variação em sistemas imutáveis rodando containers.
Não a toda, praticamente toda gigante de tecnologia tem seus Linux imutáveis, como o Bootlerocket da Amazon, a Oracle tem uma versão do Oracle Linux, a Red Hat tem o Red Hat Core, a VMWARE tem o Photon OS, a SUSE tem o MicroOS e por aí vai. A Canonical mesmo tem o Ubuntu Core, que já é um Ubuntu imutável, só ainda não é o sistema que as pessoas chamam de Ubuntu Desktop, por enquanto, já que ano que vem, devemos ter a primeira versão do Ubuntu Desktop usando tecnologia Snap para imutabilidade.
Desvantagens de sistemas imutáveis
Apesar de várias vantagens, especialmente do ponto de engenharia e segurança, existem alguns contras em sistemas imutáveis que é importante a gente pontuar também.
O primeiro ponto é a curva de aprendizado, inegavelmente, eles funcionam de forma diferente, mas esse ponto só é relevante para quem é um usuário a avançado ou profissional, afinal, são poucos os usuários de Android que estão reclamando do sistema ser imutável, se é que existe algum. Para quem é profissional, a realidade é que a gente precisa se adaptar, não dá para esperar que a tecnologia não evolua com o tempo.
Existe uma limitação nas customizações, ou ao menos, a forma de customizar se modifica. Talvez fazer ajustes em imagens de sistemas operacionais seja menos amigável do que simplesmente modificar o sistema diretamente, te obrigando a aprender a nova forma de fazer as coisas, o que acaba voltando à questão de curva de aprendizado.
Um sistema imutável também requer que os aplicativos sejam transformados em algum tipo de container, como Flatpak, Docker, Snap ou até Appimage. Naturalmente nem todos os aplicativos vão seguir essa lógica instantaneamente, especialmente num momento transitório como este, é bem possível que algum software que você precise, ainda não esteja disponível nesses formatos.
Isso pode ser um real problema para alguns, enquanto para outros não, tudo depende de quais softwares você depende ou gosta de usar.
Outra desvantagem é que ter redundância e ser resiliente assim também consome mais espaço em disco, uma atualização de sistema que envolve o download de uma imagem completamente nova, pode acabar sendo bem maior do que se fosse apenas atualizações individuais.
Mas aqui existem considerações a serem feitas, não só existe o conceito de atualizações Delta, onde somente as partes modificadas das imagens e pacotes são baixadas, como mesmo que não tivéssemos um recurso assim, a benefício de garantir que o update seja perfeito e igual para todos os usuários, o malefício do espaço será relevado por basicamente todos os desenvolvedores.
Uma coisa que deve ser considerada também, é que todas as inconveniências que você eventualmente encontre atualmente ao utilizar um software por ser um Flatpak, um Snap, ou pelo sistema ser imutável, tirando as restrições envolvendo segurança, devem ser consideradas um bug, algo que deve ser corrigido e melhorado conforme essas tecnologias recebem adesão.
Um tema não funcionar, um ícone ficar quebrado, ou qualquer coisa assim, não é o comportamento esperado. Quanto antes as pessoas voltarem os seus olhos para esses formatos novos e usarem no dia a dia, antes esses problemas devem receber atenção também.
Uma forma de imaginar a praticidade de um sistema imutável versus um modelo tradicional, é imaginar um bolo com umas velinhas sobre ele. O bolo e suas camadas é o sistema operacional, as velinhas no topo são os seus arquivos e softwares instalados.
Imagine agora que quero atualizar o meu bolo, eu quero que o meu bolo de chocolate seja um bolo de morangos. Num sistema tradicional, seria necessário tirar a camada de chocolate e tentar colocar a camada de morango com o bolo já montado, provavelmente não iria dar muito certo.
No modelo de sistemas imutáveis, basicamente você tira as velinhas, troca o bolo por completo por um que já tem a camada de morango e coloca as velinhas de volta, um processo com muito menos bagunça e com muito menos chance de dar errado.
Se você quer participar do quadro Diolinux Responde e ter a chance de ter sua pergunta respondida, tal como a do Renan, ou num vídeo exclusivo para membros, seja membro do canal Diolinux e receba vários outros benefícios, como acesso a um servidor secreto do Discord e vários cursos!