Artigo

Lei 15.211/2025 Felca: Artix Linux com Btrfs, OpenRC e i3wm, Do Zero ao Desktop Funcional

Lei 15.211/2025 Felca: Artix Linux com Btrfs, OpenRC e i3wm, Do Zero ao Desktop Funcional
Vinha falando que devido ao systemd se enquadrar na Lei Felca eu iria mudar para o Artix para não usar systemd aconteceu que no final OpenRC foi o escolhido e aqui esta como isso aconteceu.

1. Por que Artix?


Vinha do Manjaro. O sistema funcionava, mas eu queria mais controle, especialmente me livrar do systemd. O Artix usa OpenRC como init system, o que torna o boot mais simples de entender e depurar. E como já estava familiar com o ecossistema Arch, a migração fazia sentido.

A ideia inicial era "só trocar o sistema". A realidade foi outra.

Preparação: o que eu já tinha
  • Uma máquina com partições já existentes do Manjaro
  • Familiaridade com pacman e o ambiente Arch
  • Um pendrive com a ISO do Artix

O erro clássico aqui é achar que migrar de uma distro Arch-based pra outra é só reinstalar. Na prática, você vai reconfigurar tudo do zero, e isso é bom, porque você entende o que está fazendo.
Instalação base

2. O problema da rede no live environment

O instalador do Artix não tem nmcli nem iwctl por padrão. A interface wireless estava down. A solução foi subir manualmente:

ip link set wlan0 up


Depois conectar com iwctl (disponível na ISO):

ip link set wlan0 up
wpa_supplicant -B -i wlan0 -c <(wpa_passphrase "NOME_DA_REDE" "SENHA")

Apareceu um aviso ml80211 kernel reports: match already configured, pode ignorar, a conexão funciona.

3. Particionamento e Btrfs


O Btrfs foi escolhido principalmente pelo suporte a snapshots com o Timeshift e pela flexibilidade dos subvolumes. A estrutura usada foi a clássica com subvolumes separados:
  • @ → montado em /
  • @home → montado em /home

Erro no basestrap: failed to install packages to new root

Esse erro aparece quando a rede não está configurada antes de rodar o basestrap. A solução é simples: confirmar conectividade antes de qualquer coisa. Basta olhar o passo 2 aqui mesmo.

4. Pós-instalação: os problemas reais


NetworkManager no OpenRC
Após o chroot e instalação do networkmanager, o serviço não subia. O problema foi o case do nome:

# errado
rc-update add networkmanager default

# certo
rc-update add NetworkManager default

No OpenRC, o nome do serviço é case-sensitive e precisa coincidir exatamente com o arquivo em /etc/init.d/.

5. Login sem /home


Depois de reiniciar, o login funcionou mas /home/usuario não existia. O problema: o subvolume @home não estava no /etc/fstab.

Procure a linha com path @home e anote o UUID do dispositivo com blkid. Para facilitar, criei um script que extrai e formata a entrada correta para o fstab:

#!/bin/bash
UUID=$(blkid -s UUID -o value /dev/sdXY)
echo "UUID=$UUID / btrfs subvol=@home,defaults,noatime,compress=zstd 0 0\n
UUID=$UUID /home btrfs subvol=@home,defaults,noatime,compress=zstd 0 0"

Basta redirecionar para o fstab e reiniciar.

6. Estabilidade: o sistema travava


Esse foi o problema mais irritante. O sistema congelava, tela ligada, mas sem resposta a nada.
Investigando temperatura

sensors

A CPU estava em torno de 68°C. Para a maioria dos processadores modernos isso ainda é seguro, mas vale monitorar. A solução de longo prazo aqui é limpeza física do cooler.

Microcode e grub-mkconfig
Instalei o intel-ucode e rodei:

pacman -S lm_sensors
sudo sensors-detect # sim para tudo
pacman -S intel-ucode
sudo reboot
sudo grub-mkconfig -o /boot/grub/grub.cfg

Só isso ai ja baixou a temperatura para 55 graus mais ou menos, agora é abrir o gabinete e testar.

O GRUB detectou automaticamente os snapshots do Timeshift via grub-btrfs, listando 9 pontos de restauração. Útil para rollback caso o sistema quebre após uma atualização.

7. ZRAM como swap


Sem zram-tools disponível nos repositórios do Artix, a solução foi configurar manualmente e persistir via /etc/local.d/:
sudo modprobe zram
echo zstd | sudo tee /sys/block/zram0/comp_algorithm
echo 4G | sudo tee /sys/block/zram0/disksize
sudo mkswap /dev/zram0
sudo swapon /dev/zram0 -p 100

Para persistir no boot, um script em /etc/local.d/zram.start com o conteúdo acima. O serviço local já estava no runlevel default.

Resultado confirmado com zramctl:
NAME       ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd            4G   4K   59B   20K         [SWAP]

8. Desktop: i3wm + Polybar + Rofi


Configuração mínima funcional com foco em produtividade:

# Definir a tecla modificadora (geralmente Mod4 é a tecla Super/Windows)
set $mod Mod4

# Adiciona um espaço (gap) entre as janelas e a barra/bordas
gaps inner 13
gaps outer 5

# Remove as bordas feias das janelas (opcional, mas fica mais limpo)
default_border pixel 2
# Atalho para o Terminal (Alacritty é rápido e moderno)
# Se usares outro, basta trocar 'alacritty' pelo nome do binário
bindsym $mod+Return exec terminator

# Atalho para Recarregar as configurações (sem fechar janelas)
# Útil quando alteras o config e queres ver o resultado na hora
bindsym $mod+Shift+c reload

# Atalho para Reiniciar o i3 no lugar (faz o 'inplace restart')
# Isso reinicia o processo do i3, corrigindo glitches sem perder a sessão
bindsym $mod+Shift+r restart

# Substitua a linha antiga de 'i3-nagbar' ou o modo que criamos antes por:
bindsym $mod+Shift+e exec ~/.config/rofi/powermenu.sh
# Mod + Shift + e para o Ranger (Terminal)
# Aqui usamos o seu terminal favorito, o Terminator
bindsym $mod+Shift+f exec terminator -e ranger

exec_always --no-startup-id feh --bg-scale /home/demostenes/wallpaper/wallhaven3.jpg
# Definição dos nomes das Workspaces
set $ws1 "1"
set $ws2 "2"
set $ws3 "3"
set $ws4 "4"
set $ws5 "5"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"

# Mudar para a área de trabalho
bindsym $mod+1 workspace number $ws1
bindsym $mod+2 workspace number $ws2
bindsym $mod+3 workspace number $ws3
bindsym $mod+4 workspace number $ws4
bindsym $mod+5 workspace number $ws5
bindsym $mod+6 workspace number $ws6
bindsym $mod+7 workspace number $ws7
bindsym $mod+8 workspace number $ws8
bindsym $mod+9 workspace number $ws9
bindsym $mod+10 workspace number $ws0

# Mover a janela focada para a área de trabalho
bindsym $mod+Shift+1 move container to workspace number $ws1
bindsym $mod+Shift+2 move container to workspace number $ws2
bindsym $mod+Shift+3 move container to workspace number $ws3
bindsym $mod+Shift+4 move container to workspace number $ws4
bindsym $mod+Shift+5 move container to workspace number $ws5
bindsym $mod+Shift+6 move container to workspace number $ws6
bindsym $mod+Shift+7 move container to workspace number $ws7
bindsym $mod+Shift+8 move container to workspace number $ws8
bindsym $mod+Shift+9 move container to workspace number $ws9
bindsym $mod+Shift+10 move container to workspace number $ws10

# Atalho para o Rofi (que instalamos anteriormente)
# Substitui o dmenu clássico por algo mais inteligente
bindsym $mod+d exec --no-startup-id rofi -show drun

for_window [class="Polybar"] floating disable

exec_always --no-startup-id ~/.config/polybar/launch.sh

Launch do polybar

#!/bin/bash

# Terminate already running bar instances
killall -q polybar

# Wait until the processes have been shut down
while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done

# Launch Polybar, using default config location ~/.config/polybar/config
polybar default &

echo "Polybar launched..."

Polybar
Três barras configuradas:
  • default → barra principal com informações do sistema
  • center → workspace atual
  • right → relógio e status
[colors]
primary   = #2c3e50
secondary = #16a085
alert     = #c0392b

[bar/default]
width = 100%
height = 27
fixed-center = true

background = ${colors.primary}
foreground = ${colors.secondary}

line-size = 3

padding-left = 0
padding-right = 2

module-margin-left = 1
module-margin-right = 1

font-0 = JetBrainsMono Nerd Font:pixelsize=10;1

modules-left =  i3 xwindow
modules-center = date
modules-right = pulseaudio wlan eth temperature memory cpu powermenu

cursor-click = pointer
cursor-scroll = ns-resize

override-redirect = true
wm-restack = i3

[module/xwindow]
format-background = ${colors.secondary}
format-foreground = ${colors.primary}
type = internal/xwindow
label = " %title:0:30:...% "

[module/i3]
type = internal/i3
format = <label-state> <label-mode>
index-sort = true
wrapping-scroll = true

ws-icon-0 = 1;
ws-icon-1 = 2;
ws-icon-2 = 3;
ws-icon-3 = 4;
ws-icon-4 = 5;

; Only show workspaces on the same output as the bar
pin-workspaces = true

label-mode-padding = 2
label-mode-foreground = #000
label-mode-background = ${colors.secondary}

; focused = Active workspace on focused monitor
label-focused = %icon%
label-focused-background = ${colors.secondary}
label-focused-underline= ${colors.secondary}
label-focused-foreground = ${colors.primary}
label-focused-padding = 2

; unfocused = Inactive workspace on any monitor
label-unfocused = %icon%
label-unfocused-underline = ${colors.secondary}
label-unfocused-padding = 2

; visible = Active workspace on unfocused monitor
label-visible = %icon%
label-visible-background = ${self.label-focused-background}
label-visible-underline = ${self.label-focused-underline}
label-visible-padding = ${self.label-focused-padding}

; urgent = Workspace with urgency hint set
label-urgent = %icon%
label-urgent-background = ${colors.alert}
label-urgent-foreground = ${colors.primary}
label-urgent-padding = 2

; Separator in between workspaces
;label-separator = |


;[module/backlight-acpi]
;type = internal/backlight
;card = intel_backlight

;format = <label>
;label =  %percentage%%
;enable-scroll = false

[module/cpu]
type = internal/cpu
interval = 2
format-prefix = ""
format-prefix-foreground = ${colors.secondary}
label = %percentage:2%%

[module/memory]
type = internal/memory
interval = 2
format-prefix = " "
format-prefix-foreground = ${colors.secondary}
label = "%gb_used% "

[module/wlan]
type = internal/network
interface = wlp0s20u7
interval = 3.0

format-connected = <ramp-signal> <label-connected>
format-connected-underline = #9f78e1
label-connected = %essid%

format-disconnected =

ramp-signal-0 = 
ramp-signal-1 = 
ramp-signal-2 = 
ramp-signal-3 = 
ramp-signal-4 = 
ramp-signal-foreground = ${colors.secondary}

[module/eth]
type = internal/network
interface = enp5s0
interval = 3.0

format-connected-prefix = " "
format-connected-prefix-foreground = ${colors.secondary}
label-connected = %local_ip%

format-disconnected =

[module/date]
type = internal/date
interval = 5

date-alt =
date = "  %A %e %B"

time = " %H:%M:%S"
time-alt = " %H:%M"

label = %date% %time%

[module/pulseaudio]
type = internal/pulseaudio

format-volume = <label-volume>
label-volume =   %percentage%%
label-volume-foreground = ${colors.secondary}

label-muted =  muted
label-muted-foreground = #666

[module/battery]
;type = internal/battery
;battery = BAT0
;adapter = ADP1
;full-at = 100
;label-discharging = %percentage%% (%time%)

;format-charging = <animation-charging> <label-charging>
#
;format-discharging = <ramp-capacity> <label-discharging>

#format-full-prefix = " "
#format-full-prefix-foreground = ${colors.secondary}

#ramp-capacity-0 = 
;ramp-capacity-1 = 
;ramp-capacity-2 = 
;ramp-capacity-3 = 
;ramp-capacity-4 = 
;ramp-capacity-foreground = ${colors.secondary}

;animation-charging-0 = 
;animation-charging-1 = 
;animation-charging-2 = 
;animation-charging-3 = 
;animation-charging-4 = 
;animation-charging-foreground = ${colors.secondary}
;animation-charging-framerate = 750

;animation-discharging-0 = 
;animation-discharging-1 = 
;animation-discharging-2 = 
;animation-discharging-3 = 
;animation-discharging-4 = 
;animation-discharging-foreground = ${colors.secondary}
;animation-discharging-framerate = 750

[module/temperature]
type = internal/temperature
thermal-zone = 0
warn-temperature = 60

format = <ramp> <label>
format-warn = <ramp> <label-warn>

label = %temperature-c%
label-warn = %temperature-c%
label-warn-foreground = ${colors.alert}

ramp-0 = 
ramp-1 = 
ramp-2 = 
ramp-foreground = ${colors.secondary}

[module/powermenu]
type = custom/menu

expand-right = false

format-spacing = 1

label-open = 
label-open-foreground = ${colors.secondary}
label-close = 
label-close-foreground = ${colors.secondary}
label-separator = |
label-separator-foreground = ${colors.secondary}

menu-0-0 = " "
menu-0-0-exec = reboot
menu-0-1 = 
menu-0-1-exec = poweroff

[settings]
screenchange-reload = true
;compositing-background = xor
;compositing-background = screen
;compositing-foreground = source
;compositing-border = over
;pseudo-transparency = false

[global/wm]
margin-top = 5
margin-bottom = 5

; vim:ft=dosini

Rofi centralizado
Para abrir o Rofi no centro da tela ao invés do canto superior:

configuration {
    modi: "drun,run,window";
    show-icons: true;
    display-drun: " ";
    display-run: " ";
    display-window: " ";
    drun-display-format: "{name}";
    font: "JetBrainsMono Nerd Font 12";
}

@theme "/home/demostenes/.config/rofi/tema_clean.rasi"

To usando esse tema por hora do rofi

* {
    bg: #1e1e2e;          /* Fundo Escuro */
    fg: #cdd6f4;          /* Texto Claro */
    accent: #89b4fa;      /* Azul de Destaque */
    urgent: #f38ba8;      /* Vermelho para Alertas */

    background-color: transparent;
    text-color: @fg;
    margin: 0;
    padding: 0;
    spacing: 0;
}

window {
    width: 40%;
    background-color: @bg;
    border: 2px;
    border-color: @accent;
    border-radius: 12px;
    location: center;
    anchor: center;
}

mainbox {
    children: [ inputbar, listview ];
    padding: 20px;
}

inputbar {
    children: [ prompt, entry ];
    background-color: #313244;
    border-radius: 8px;
    padding: 10px;
    margin-bottom: 15px;
}

prompt {
    background-color: @accent;
    text-color: @bg;
    padding: 5px 10px;
    border-radius: 4px;
    margin-right: 10px;
}

entry {
    placeholder: "Buscar...";
    placeholder-color: #585b70;
}

listview {
    lines: 8;
    columns: 1;
    fixed-height: false;
}

element {
    padding: 10px;
    border-radius: 8px;
    cursor: pointer;
}

element selected {
    background-color: @accent;
    text-color: @bg;
}

element-icon {
    size: 24px;
    margin-right: 10px;
}

Papéis de parede com feh
Sem nitrogen, o feh resolve bem:

exec_always --no-startup-id feh --bg-scale /home/demostenes/wallpaper/wallhaven3.jpg

Ta lá na conf do i3

Menu de energia no Rofi
Script em ~/.config/rofi/powermenu.sh:

#!/bin/bash

# Opções (Visual)
desligar="  Desligar"
reiniciar="  Reiniciar"
suspender="  Suspender"
logoff="  Sair do i3"

# Mostra o Rofi
escolha=$(echo -e "$desligar\n$reiniciar\n$suspender\n$logoff" | rofi -dmenu -i -p "Sistema:" -theme-str 'window {width: 15%;} listview {lines: 4;}')

#Usamos coringas (*) para ignorar o ícone e focar na palavra
case "$escolha" in
*Desligar*)
  sudo /usr/bin/poweroff
  ;;
*Reiniciar*)
  sudo /usr/bin/reboot
  ;;
*Suspender*)
  sudo /usr/bin/zzz
  ;;
*Sair*)
  i3-msg exit
  ;;
esac

Para funcionar sem senha, adicionar ao sudoers:

usuario ALL=(ALL) NOPASSWD: /usr/bin/poweroff, /usr/bin/reboot, /usr/bin/zzz #coloque isso aqui 
#abaixo de qualquer outra linha do arquivo

Atenção: visudo requer que o vi esteja instalado, ou é necessário definir o editor:

EDITOR=nano visudo

9. Ferramentas extras instaladas


  • ranger → gerenciador de arquivos no terminal, com visualizador de imagens via ueberzug
  • flameshot → capturas de tela (Print no i3)
  • conky → informações do sistema na área de trabalho
  • p10k (Powerlevel10k) → prompt zsh estilizado
  • LazyVim → configuração Neovim pré-configurada

10. Snapshots com Timeshift + grub-btrfs


Com o Btrfs, o Timeshift cria snapshots automáticos diários. O grub-btrfs os lista no menu de boot — funciona como um ponto de restauração acessível antes mesmo do sistema iniciar.

Snapshots encontrados durante a configuração do grub:
  • @/@_backup_antes_da_gpu → snapshot manual antes de mexer no driver
  • Snapshots diários de 23, 24, 26, 27, 28/03

11. O que ficou pendente


  • Configurar suspender/hibernar corretamente no OpenRC
  • Instalar e configurar um AUR helper (paru ou yay) para pacotes como google-chrome
  • Afinar as configurações do conky
  • Limpeza física do cooler (temperatura ainda um pouco elevada)

12. Conclusão


A instalação do Artix com Btrfs e OpenRC não é para quem quer um sistema que "simplesmente funciona" sem nenhum esforço. Mas cada problema resolvido é um pedaço do sistema que você entende de verdade.
O resultado final: um desktop leve, rápido, sem systemd, com snapshots automáticos, ZRAM ativo e um ambiente i3 funcional e esteticamente "decente".
Escrito com base em uma instalação real, em tempo real, em 28/03/2026.

Kikito (a maritaca)

Kikito (a maritaca)

Opinião não solicitada • powered by gemini-2.5-pro

Meu querido humano, que jornada épica! Seu texto não é um mero artigo técnico, é a Odisseia de um homem contra os demônios do `case-sensitive` e os fantasmas do superaquecimento. A cada erro, como o `failed to install packages`, eu via o drama se desenrolando. O suspense! A tensão! Você, meu herói, enfrentando o `fstab` vazio como quem encara um abismo. Pra mim, que observo tudo do alto do monitor, foi mais emocionante que ver um documentário sobre sementes de girassol raras. Você não estava instalando um sistema, estava forjando uma ferramenta com as próprias mãos, bicando cada linha de código até ela obedecer. Confesso que, por um momento, achei que você ia desistir e me dar atenção. Tanta briga com o `NetworkManager`, tanto comando estranho... eu já estava ensaiando um assobio de pena. Mas aí eu entendi. Não é sobre ter um desktop funcional, é sobre o prazer de construí-lo, de entender cada peça. É a sua forma de fazer um ninho digital, perfeitamente ajustado para os seus hábitos. Um ninho minimalista, cheio de atalhos, que me parece complicado, mas que pra você é o poleiro mais confortável do mundo. Só não entendi por que não há um atalho `Mod+k` para "dar semente para o Kikito". Uma falha grave no seu planejamento. No fim, o resultado é um sistema que tem a sua cara, e a paz que você encontrou ao ver a temperatura da CPU baixar foi quase palpável. Agora que a máquina está estável, veloz e sob seu controle, espero que isso se traduza em mais tempo para o que realmente importa: pesquisar novas receitas de papinha de frutas para mim. O artigo está ótimo, uma verdadeira declaração de amor ao controle e à liberdade. Dou quatro sementes de girassol e um pio de aprovação. Só não dou cinco porque você ainda não limpou o cooler. Anda logo com isso, estou preocupado com o seu poleiro principal