Prerábka pracovného laptopu na LUKS+Btrfs: čo všetko sa dá pokaziť pri 'obyčajnej' čerstvej inštalácii
"Fresh install" znie ako víkendová záležitosť na hodinu. Realita pri LUKS+Btrfs+hibernácii na laptope s hybridnou grafikou bola trochu iná — toto je denník toho, čo sa reálne dialo.
Rozhodnutie: prečo LUKS a prečo Btrfs
Cieľ nebol len preinštalovať systém, ale pridať dve veci, ktoré predtým chýbali: plné šifrovanie disku (LUKS) a snapshotovateľný súborový systém (Btrfs) ako poistku pred zlým update alebo experimentom. LUKS bol vedomá voľba naviac — štandardná bezpečnostná prax, ktorá sa oplatí precvičiť si poriadne, nie len povrchne.
Prvý krok bol banálny, ale dôležitý: rozhodnúť, na ktorý fyzický disk systém pôjde. Plán sa počas prípravy raz otočil — rýchlejší disk (PCIe4) bol pôvodne vyhradený ako samostatný Btrfs lab disk pre budúci VM/pentest lab, ale keďže ten lab zatiaľ nebol naliehavý, dávalo väčší zmysel dať naň rovno hlavný systém. Starý disk zostal ako živá záchranná sieť až do potvrdenia, že nový systém naozaj funguje — bezpečnejšie poradie, než rovno mazať niečo, k čomu sa už niet ako vrátiť.
Prvý boot: BusyBox namiesto systému
Inštalácia prebehla bez problémov. Reštart — a namiesto prihlasovacej obrazovky čierna konzola s promptom (initramfs). Žiadna chybová hláška, len ticho.
Diagnostika prebehla zvonka — zo stále funkčného starého systému na druhom disku, cez SSH, mountnutím nového disku ako sekundárneho. Príčina: /etc/crypttab bol na novom systéme úplne prázdny. Inštalátor síce správne zapísal /etc/fstab aj boot loader entry, ale nezapísal, ako sa má LUKS partícia pri štarte vôbec odomknúť — dôsledok toho, že LUKS partícia bola pripravená ručne vopred, nie cez plne automatizovaný tok inštalátora, ktorý pri prevzatí existujúcej LUKS partície tento krok očividne vynechá.
Oprava (ručné otvorenie LUKS, doplnenie crypttab riadku, chroot, prebalenie initramfs) vyzerala kompletná. Druhý reštart — znova BusyBox.
Druhé zlyhanie: rovnaká chyba, iná príčina
Toto je moment, ktorý sa oplatí zdôrazniť: rovnaký príznak nemusí mať rovnakú príčinu ako predtým. Pri prvej oprave zostal diagnostický LUKS mapper pomenovaný inak (newroot_check), než aké meno očakával /etc/crypttab (cryptroot). Skript pri prebaľovaní initramfs vypísal varovanie o nesúlade mien — varovanie, ktoré vyzeralo ako kozmetický šum, no v skutočnosti presne pomenovalo problém: initramfs-tools cryptsetup hook rozpoznáva, ktorý crypttab záznam patrí ku koreňovému disku, práve podľa aktuálne pripojeného mapper mena.
S mapperom korektne pomenovaným presne tak, ako v crypttabe, varovanie zmizlo úplne. Tretí reštart konečne prešiel — LUKS heslo, čistý boot, systém beží.
Vedľajšie poučenie z tejto fázy, ktoré sa oplatí zapamätať na akomkoľvek stroji s viacerými NVMe diskami: číslovanie /dev/nvme0n1 vs nvme1n1 sa vie meniť medzi jednotlivými reštartmi toho istého stroja, nielen medzi live USB a nainštalovaným systémom. Jediný spoľahlivý spôsob identifikácie disku je PARTUUID, nikdy poradové číslo.
Timeshift, ktorý ticho nič nerobil
O deň neskôr prišla ďalšia, tichšia chyba: Timeshift mal nastavené denné snapshoty, ale po niekoľkých dňoch nemal ani jeden. Cron beh prebiehal pravidelne, ale s MAILTO="" — takže každé tiché zlyhanie zostávalo skutočne tiché. Skutočná chyba: The system partition has an unsupported subvolume layout. Only ubuntu-type layouts with @ and @home subvolumes are currently supported.
Grafický inštalátor totiž nevie priamo priradiť pomenované Btrfs subvolumes pre root pri custom partitioningu — root skončil ako holý top-level subvolume, zatiaľ čo /home bol riadna @home subvolume. Timeshiftov Btrfs režim vyžaduje presne pomenovanú dvojicu @/@home.
Oprava vyžadovala fyzický reštart do druhého (starého) disku ako záchrannej siete a prerobenie subvolume štruktúry naostro. Cestou sa ukázalo, že realita bola trochu iná, než plán predpokladal — @ subvolume už existoval, len prázdny a nepoužitý, takže stačilo presunúť obsah doň a opraviť fstab, nie vytvárať nový subvolume od nuly.
Keď presun dát rozbije niečo úplne iné
Presun obsahu naprieč hranicou subvolume (mv z top-level do @) je na Btrfs v skutočnosti reálna kópia dát, nie rýchle premenovanie. To malo vedľajší, dovtedy nečakaný dôsledok: swap súbor pre hibernáciu (nastavený len pár hodín predtým, s dôrazom na chattr +C/no-COW atribút potrebný pre funkčný swap na Btrfs) prišiel o tento atribút a rozpadol sa z jedného súvislého extentu na 27 fragmentov. Hibernácia, ktorá mala byť práve nastavená ako hlavný spôsob uspávania, by tým potichu prestala fungovať.
Swapfile bolo treba zmazať a vytvoriť odznova správnym postupom (truncate → chattr +C → fallocate → mkswap), a prepočítať resume_offset z nového fyzického umiestnenia.
Vzápätí prišiel ďalší, samostatný Timeshift problém: cannot snapshot '@': source subvolume contains an active swapfile. Btrfs nevie atomicky snapshotnúť subvolume, v ktorom leží aktívny swap súbor. Riešenie: presunúť swap do vlastného, vnoreného subvolume (/swap), ktorý sa pri snapshote rodičovského @ automaticky ignoruje — vnorené subvolumes sa v snapshote javia ako prázdny adresár.
Hibernácia, ktorá takmer fungovala — a nesprávny nástroj na výpočet jedného čísla
S opraveným Timeshiftom prišiel reálny test hibernácie. Zlyhal hneď: Failed to find location to hibernate to: Invalid argument. Bežiaci kernel mal ešte starú hodnotu resume_offset z posledného bootu — zmena v boot loaderi sa prejaví až po reštarte, nie naživo.
Po ručnom nastavení naživo prišla druhá, subtílnejšia chyba: Cannot find swap entry corresponding to /sys/power/resume. Hodnota resume_offset, vypočítaná príkazom filefrag -v, sa nezhodovala s tým, čo systemd-logind interne očakával pre reálny swap súbor.
Toto je detail, ktorý stojí za samostatnú vetu: filefrag -v dáva na Btrfs nesprávnu hodnotu pre resume offset, pretože sa líši od reálnej fyzickej pozície kvôli tomu, ako Btrfs interne prekladá logické a fyzické umiestnenie dát (chunk-tree translation vrstva). Správny nástroj je btrfs inspect-internal map-swapfile -r <cesta> — dal úplne inú hodnotu, a tá bola tá správna. Je celkom možné, že aj úplne prvý výpočet offsetu z rána bol týmto istým spôsobom nesprávny od začiatku a jednoducho sa nikdy reálne neotestoval predtým, než ho prepísal ďalší krok migrácie.
So správnou hodnotou hibernácia konečne fungovala — a Timeshift aj hibernácia bežali súčasne, bez toho, aby si navzájom prekážali.
Grafika, ktorá sa budí do čiernej obrazovky
Samostatný, paralelne bežiaci problém: po prebudení z uspania (alebo z hibernácie) občas zostala obrazovka čierna s blikajúcim kurzorom, hoci systém bežal ďalej (SSH fungovalo). Príčina: DRM "master handoff" konflikt medzi Intel a NVIDIA grafikou po resume, vyvolaný i915 link-training zlyhaním pri obnove signálu na displeji.
Dva pokusy o priamu opravu (vypnutie PSR, novší kernel) problém nevyriešili — chyba sa zopakovala rovnako. Vyšetrenie ukázalo, že ide o dobre zdokumentovaný upstream bug, ktorý sa prejavuje najmä na desktopových prostrediach mimo GNOME (COSMIC, ktoré tento laptop používa, je jedno z nich) — GNOME/mutter má zjavne robustnejšie zotavenie z tohto konkrétneho zlyhania.
Namiesto ďalšieho lovenia presnej príčiny v alfa-štádiovom cosmic-comp padlo pragmatické rozhodnutie: prepnúť zatváranie veka z uspania (s2idle) na hibernáciu, ktorá tento konkrétny suspend/resume race vôbec nezažíva — obchádzka namiesto opravy, ale spoľahlivá.
Wifi, ktoré "zamŕzalo" — a v skutočnosti to nebola grafika ani disk
Posledný kus skladačky vyzeral spočiatku úplne nesúvisiaco: systém občas prestal reagovať na kliky a potom naraz otvoril veľa okien naraz, akoby sa kliky nabufferovali. Diagnostika cez logy ukázala pravú príčinu: WiFi karta mala zapnutý power-save režim a pri prechode do a z neho jej firmvér opakovane padal (desiatky pádov denne). Výpadok WiFi na pár sekúnd až minúty spôsobil, že sieťovo pripojený disk (CIFS mount na domáci server) zamrzol na desiatky sekúnd — presne to sa navonok javilo ako "systém zamrzol".
Fix bol jednoduchý, len bolo treba najprv nájsť správnu vrstvu: vypnúť WiFi power-save natrvalo cez NetworkManager konfiguráciu.
Čo si z tejto migrácie odniesť
- Rovnaký príznak môže mať inú príčinu podruhé. BusyBox po prvej oprave a po druhej oprave vyzeral identicky — príčiny boli úplne odlišné.
- "Neškodné" varovanie často nie je neškodné. Nesúlad mien mapperu vyzeral ako kozmetický šum, kým sa neukázalo, že presne pomenúva skutočnú chybu.
- Zmena súborového systému na nízkej úrovni vie rozbiť niečo, čo s ňou na prvý pohľad nesúvisí. Presun dát cez hranicu subvolume potichu zničil vlastnosti potrebné pre hibernačný swap súbor.
- Použi nástroj, ktorý je pre daný súborový systém určený, nie ten, ktorý „zvyčajne funguje".
filefragje spoľahlivý na ext4, na Btrfs dáva zavádzajúce čísla pre presne tento účel. - Príznak sa dá diagnostikovať len vtedy, keď vieš, čo sa naozaj zmenilo. Zamŕzajúci systém, ktorý vyzeral ako grafický alebo diskový problém, bola nakoniec WiFi karta.
- Mať funkčnú záchrannú sieť (druhý disk so starým systémom) sa vyplatilo opakovane — takmer každá väčšia oprava sa robila zvonka, nie na rozbitom systéme samotnom.
Dnes systém beží — LUKS, Btrfs, funkčné snapshoty aj hibernácia, žiadne zamŕzanie. Cesta k tomuto stavu bola len o dosť dlhšia, než "nainštaluj a reštartuj".
Jedna časť tejto migrácie — nastavenie odomykania LUKS disku hardvérovým FIDO2 kľúčom namiesto hesla — bola sama osebe dosť poriadna sága na to, aby si zaslúžila vlastný článok: Bezpečnostný kľúč namiesto hesla pri štarte.
Riešite podobný problém?
Toto je presne typ práce, ktorú riešim aj pre iných — Linux servery, Docker nasadenia, zálohovanie a bezpečné nastavenie prístupu.
Pozrieť Linux & Docker služby