-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfeed.xml
2471 lines (1849 loc) · 209 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://www.baioc.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.baioc.dev/" rel="alternate" type="text/html" /><updated>2024-11-17T19:25:20+00:00</updated><id>https://www.baioc.dev/feed.xml</id><title type="html">baioc</title><author><name>Gabriel B. Sant'Anna</name></author><entry><title type="html">How to set up an X-based desktop from scratch</title><link href="https://www.baioc.dev/tutorial/arch-awesomewm/" rel="alternate" type="text/html" title="How to set up an X-based desktop from scratch" /><published>2024-07-27T00:00:00+00:00</published><updated>2024-07-27T00:00:00+00:00</updated><id>https://www.baioc.dev/tutorial/arch-awesomewm</id><content type="html" xml:base="https://www.baioc.dev/tutorial/arch-awesomewm/"><![CDATA[<p>In the final post of this dual-boot series, I’ll show how to go from a base Arch install:</p>
<figure class=""><a href="/assets/images/dual-boot/arch-base.png" class="image-popup" title="Base Arch tty, after booting for the first time - at least all peripherals (monitor, keyboard, mouse) were working out of the box.
"><img src="/assets/images/dual-boot/arch-base.png" alt="arch-base" /></a><figcaption>
Base Arch tty, after booting for the first time - at least all peripherals (monitor, keyboard, mouse) were working out of the box.
</figcaption></figure>
<p>To a simple <a href="https://awesomewm.org/">awesomeWM</a> desktop environment:</p>
<figure class=""><a href="/assets/images/dual-boot/arch-rice.png" class="image-popup" title="This is a screenshot of my personal install. We’ll be going in this direction.
"><img src="/assets/images/dual-boot/arch-rice.png" alt="arch-rice" /></a><figcaption>
This is a screenshot of my personal install. We’ll be going in this direction.
</figcaption></figure>
<h2 id="0-manual-btrfs-snapshot">0. Manual btrfs snapshot</h2>
<p>Btrfs’s snapshot capability is one of the reasons I chose this file system, so before anything else I’ll use that to make a backup of the entire root partition.
While I’ll create the snapshot manually this time, later in this tutorial I’m going to show how to set up automatic backups.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>mount <span class="nt">-o</span> <span class="nv">subvolid</span><span class="o">=</span>5 /dev/mapper/arch-root /mnt
<span class="nv">$ </span>btrfs subvolume snapshot /mnt/@ /mnt/@snapshot-baseline
<span class="nv">$ </span>umount /mnt
</code></pre></div></div>
<p>That’s all it takes, and you’ll notice it’s also instant thanks to btrfs copy-on-write.</p>
<figure class=""><a href="/assets/images/dual-boot/arch-btrfs-snapshot.png" class="image-popup" title="After creating the snapshot, we can also mount it and check its contents.
"><img src="/assets/images/dual-boot/arch-btrfs-snapshot.png" alt="arch-btrfs-snapshot" /></a><figcaption>
After creating the snapshot, we can also mount it and check its contents.
</figcaption></figure>
<h2 id="1-network-and-time">1. Network and time</h2>
<p>During installation, I made sure that the <a href="https://wiki.archlinux.org/title/NetworkManager"><code class="language-plaintext highlighter-rouge">NetworkManager</code></a> systemd service would auto-start.
In case you forgot to do that before, this is a good time to run:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>systemctl <span class="nb">enable </span>NetworkManager
<span class="nv">$ </span>systemctl start NetworkManager
</code></pre></div></div>
<p>I also like to always resolve <code class="language-plaintext highlighter-rouge">localhost</code> to … well … the local host.
So I make sure that my <code class="language-plaintext highlighter-rouge">/etc/hosts</code> file contains the following entries:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>127.0.0.1 localhost
::1 localhost
</code></pre></div></div>
<p>Since I also want my system time to be correct, I’ll also enable the built-in NTP service:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>timedatectl set-ntp <span class="nb">true</span>
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/arch-network.png" class="image-popup"><img src="/assets/images/dual-boot/arch-network.png" alt="arch-network" /></a></figure>
<h2 id="2-firewall">2. Firewall</h2>
<p>The first thing to do after connecting to the internet is setting up protection - a firewall, in this case.
I like <a href="https://wiki.archlinux.org/title/Uncomplicated_Firewall">ufw</a>, which is pretty easy to install and enable by default:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>pacman <span class="nt">-S</span> ufw
<span class="nv">$ </span>systemctl <span class="nb">enable </span>ufw
<span class="nv">$ </span>systemctl start ufw
<span class="nv">$ </span>ufw <span class="nb">enable</span>
<span class="nv">$ </span>ufw status verbose
Status: active
Logging: on <span class="o">(</span>low<span class="o">)</span>
Default: deny <span class="o">(</span>incoming<span class="o">)</span>, allow <span class="o">(</span>outgoing<span class="o">)</span>, deny <span class="o">(</span>routed<span class="o">)</span>
New profiles: skip
</code></pre></div></div>
<p>The default configuration is already the best option for most desktop users: deny all incoming traffic (connections initiated in the network) and allow all outgoing traffic.</p>
<p>Personally, I also like to use <a href="https://github.com/evilsocket/opensnitch">OpenSnitch</a> to block all outgoing traffic by default, then handpick exceptions based on program, protocol and target address & port.
I know this is too much of a nuisance for most people, so I’ll leave this out of the tutorial.</p>
<h2 id="3-non-root-user">3. Non-root user</h2>
<p>Even if I’m the only person using this system, it’s more secure to do it from a non-root user by default.
The following commands create a user called <code class="language-plaintext highlighter-rouge">user</code> with their own home directory, sets a password, then installs <code class="language-plaintext highlighter-rouge">zsh</code> and sets that as <code class="language-plaintext highlighter-rouge">user</code>’s default shell.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>useradd <span class="nt">--create-home</span> user
<span class="nv">$ </span>passwd user
<span class="nv">$ </span>pacman <span class="nt">-S</span> zsh
<span class="nv">$ </span>chsh <span class="nt">-s</span> /usr/bin/zsh user
</code></pre></div></div>
<p>Then, in order to be able to perform administrative actions through <code class="language-plaintext highlighter-rouge">sudo</code> or Polkit, I’ll add <code class="language-plaintext highlighter-rouge">user</code> to the <code class="language-plaintext highlighter-rouge">wheel</code> group:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>usermod <span class="nt">-aG</span> wheel user
</code></pre></div></div>
<p>And also update the sudoers file with <code class="language-plaintext highlighter-rouge">EDITOR=nano visudo</code>, making sure to uncomment the line that reads:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%wheel ALL=(ALL:ALL) ALL
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/arch-security.png" class="image-popup" title="Using a non-privileged user by default is a security control, just like setting up a local firewall.
"><img src="/assets/images/dual-boot/arch-security.png" alt="arch-security" /></a><figcaption>
Using a non-privileged user by default is a security control, just like setting up a local firewall.
</figcaption></figure>
<p>You can now exit the current shell and log back in as the new user.
If you changed the default shell to <code class="language-plaintext highlighter-rouge">zsh</code>, you may also be prompted to do some initial configuration.</p>
<h2 id="4-x-initialization">4. X initialization</h2>
<p>We’re going to use X.Org as our window system, with awesome as a window manager.
Furthermore, in order to access the shell from an X(11) session, we’ll also need to install a terminal emulator.
We can get started by installing the necessary packages:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>pacman <span class="nt">-S</span> xorg-server xorg-xinit awesome alacritty
</code></pre></div></div>
<p>I want the Xorg server to start whenever I log in as <code class="language-plaintext highlighter-rouge">user</code> from the default <code class="language-plaintext highlighter-rouge">tty1</code>.
Implementing this is as simple as configuring the <code class="language-plaintext highlighter-rouge">zsh</code> login shell (<code class="language-plaintext highlighter-rouge">~/.zprofile</code>) to run <a href="https://wiki.archlinux.org/title/Xinit"><code class="language-plaintext highlighter-rouge">startx</code></a>:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># /home/user/.zprofile</span>
<span class="k">if</span> <span class="o">[</span> <span class="nt">-z</span> <span class="s2">"</span><span class="nv">$DISPLAY</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> <span class="o">[</span> <span class="s2">"</span><span class="nv">$XDG_VTNR</span><span class="s2">"</span> <span class="nt">-le</span> 1 <span class="o">]</span><span class="p">;</span> <span class="k">then
</span><span class="nb">exec </span>startx
<span class="k">fi</span>
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">startx</code> program will then run the <code class="language-plaintext highlighter-rouge">~/.xinitrc</code> script to start up client programs, including our window manager of choice.
We just need to copy the default script to the user’s home folder, remove the last few lines running programs we don’t have, and append <code class="language-plaintext highlighter-rouge">exec awesome</code>:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cp</span> /etc/X11/xinit/xinitrc ~/.xinitrc
<span class="nv">$ </span>nano ~/.xinitrc
<span class="nv">$ </span><span class="nb">cat</span> ~/.xinitrc
<span class="c">#!/bin/sh</span>
<span class="c"># merge in defaults and keymaps</span>
<span class="nv">userresources</span><span class="o">=</span><span class="nv">$HOME</span>/.Xresources
<span class="nv">usermodmap</span><span class="o">=</span><span class="nv">$HOME</span>/.Xmodmap
<span class="nv">sysresources</span><span class="o">=</span>/etc/X11/xinit/.Xresources
<span class="nv">sysmodmap</span><span class="o">=</span>/etc/X11/xinit/.Xmodmap
<span class="k">if</span> <span class="o">[</span> <span class="nt">-f</span> <span class="nv">$sysresources</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span>xrdb <span class="nt">-merge</span> <span class="nv">$sysresources</span>
<span class="k">fi
if</span> <span class="o">[</span> <span class="nt">-f</span> <span class="nv">$sysmodmap</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span>xmodmap <span class="nv">$sysmodmap</span>
<span class="k">fi
if</span> <span class="o">[</span> <span class="nt">-f</span> <span class="s2">"</span><span class="nv">$userresources</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span>xrdb <span class="nt">-merge</span> <span class="s2">"</span><span class="nv">$userresources</span><span class="s2">"</span>
<span class="k">fi
if</span> <span class="o">[</span> <span class="nt">-f</span> <span class="s2">"</span><span class="nv">$usermodmap</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then
</span>xmodmap <span class="s2">"</span><span class="nv">$usermodmap</span><span class="s2">"</span>
<span class="k">fi</span>
<span class="c"># start some nice programs</span>
<span class="k">if</span> <span class="o">[</span> <span class="nt">-d</span> /etc/X11/xinit/xinitrc.d <span class="o">]</span> <span class="p">;</span> <span class="k">then
for </span>f <span class="k">in</span> /etc/X11/xinit/xinitrc.d/?<span class="k">*</span>.sh <span class="p">;</span> <span class="k">do</span>
<span class="o">[</span> <span class="nt">-x</span> <span class="s2">"</span><span class="nv">$f</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> <span class="nb">.</span> <span class="s2">"</span><span class="nv">$f</span><span class="s2">"</span>
<span class="k">done
</span><span class="nb">unset </span>f
<span class="k">fi
</span><span class="nb">exec </span>awesome
</code></pre></div></div>
<p>Since I’m the only one who’ll be using this system, I’ll also enable <a href="https://wiki.archlinux.org/title/Getty#Automatic_login_to_virtual_console">auto-login</a> - this means I’ll only have to type in the disk decryption password before getting to my desktop.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo mkdir</span> <span class="nt">-p</span> /etc/systemd/system/getty@tty1.service.d
<span class="nv">$ </span><span class="nb">sudo </span>nano /etc/systemd/system/getty@tty1.service.d/autologin.conf
<span class="nv">$ </span><span class="nb">cat</span> /etc/systemd/system/getty@tty1.service.d/autologin.conf
<span class="o">[</span>Service]
<span class="nv">Type</span><span class="o">=</span>simple
<span class="nv">ExecStart</span><span class="o">=</span>
<span class="nv">ExecStart</span><span class="o">=</span>-/sbin/agetty <span class="nt">-o</span> <span class="s1">'-p -f -- \\u'</span> <span class="nt">--noclear</span> <span class="nt">--autologin</span> user %I <span class="nv">$TERM</span>
<span class="nv">Environment</span><span class="o">=</span><span class="nv">XDG_SESSION_TYPE</span><span class="o">=</span>x11
</code></pre></div></div>
<p>That’s it!
We can now reboot and drop into a barebones graphical desktop:</p>
<figure class=""><a href="/assets/images/dual-boot/arch-awesome.png" class="image-popup" title="A fresh install of awesomeWM. I have to say, getting to this point was easier than I thought it would be.
"><img src="/assets/images/dual-boot/arch-awesome.png" alt="arch-awesome" /></a><figcaption>
A fresh install of awesomeWM. I have to say, getting to this point was easier than I thought it would be.
</figcaption></figure>
<h2 id="5-awesomewm-configuration">5. awesomeWM configuration</h2>
<p>One of the first things you may notice if you’re following this tutorial is that the “open terminal” buttons and shortcuts are not working.
That’s because, by default, awesome is configured to use <code class="language-plaintext highlighter-rouge">xterm</code>, whereas we installed Alacritty.
You can still open Alacritty “manually”, either by typing <code class="language-plaintext highlighter-rouge">alacritty</code> in the command prompt (<code class="language-plaintext highlighter-rouge">Super + R</code>) or choosing it in the built-in application menu (<code class="language-plaintext highlighter-rouge">Super + P</code>).</p>
<p>After getting to a terminal, I suggest overriding the default configuration:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">mkdir</span> <span class="nt">-p</span> ~/.config/awesome/
<span class="nv">$ </span><span class="nb">cp</span> /etc/xdg/awesome/rc.lua ~/.config/awesome/
<span class="nv">$ </span>nano ~/.config/awesome/rc.lua
</code></pre></div></div>
<p>Make sure to change the line that reads <code class="language-plaintext highlighter-rouge">terminal = "xterm"</code> to <code class="language-plaintext highlighter-rouge">terminal = "alacritty"</code>.
In order to apply any changes, we need to reload awesome (<code class="language-plaintext highlighter-rouge">Super + Ctrl + R</code>).
We should now be able to open our terminal of choice with <code class="language-plaintext highlighter-rouge">Super + Enter</code>.</p>
<p>After that, I suggest taking a look at <a href="https://awesomewm.org/recipes/">some awesomeWM configuration recipes</a> in order to understand how to configure it, edit keybindings to your liking or add useful widgets.
Note that, at this point, you can use <code class="language-plaintext highlighter-rouge">pacman</code> to install your web browser of choice and use that to read the documentation directly from your just-configured graphical system.</p>
<p>For example, one of the first things I did was adding a blurry screen lock script:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/sh</span>
<span class="nb">set</span> <span class="nt">-e</span>
<span class="nv">screenshot</span><span class="o">=</span><span class="si">$(</span><span class="nb">mktemp</span> /tmp/lock-screen-scrot-XXXXXXXXXX<span class="si">)</span>
scrot <span class="nt">--overwrite</span> <span class="nt">--format</span> png <span class="nt">-F</span> <span class="s2">"</span><span class="nv">$screenshot</span><span class="s2">"</span>
magick <span class="s2">"</span><span class="nv">$screenshot</span><span class="s2">"</span> <span class="nt">-blur</span> 0x8 <span class="s2">"</span><span class="k">${</span><span class="nv">screenshot</span><span class="k">}</span><span class="s2">-blur.png"</span>
i3lock <span class="nt">--image</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">screenshot</span><span class="k">}</span><span class="s2">-blur.png"</span> <span class="nt">--pointer</span><span class="o">=</span>default <span class="nt">--ignore-empty-password</span> <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span>
</code></pre></div></div>
<p>After saving this to a file called <code class="language-plaintext highlighter-rouge">lock-screen</code>, we need to:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>pacman <span class="nt">-S</span> i3lock scrot imagemagick <span class="c"># install programs used in the script</span>
<span class="nv">$ </span><span class="nb">chmod</span> +x lock-screen <span class="c"># make the script executable</span>
<span class="nv">$ </span><span class="nb">mkdir</span> <span class="nt">-p</span> ~/.local/bin <span class="c"># create a ~/.local/bin/ folder</span>
<span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'export PATH=$PATH:$HOME/.local/bin'</span> <span class="o">>></span> .zshenv <span class="c"># append it to our user's PATH</span>
<span class="nv">$ </span><span class="nb">mv </span>lock-screen ~/.local/bin/ <span class="c"># put the lock screen script there</span>
</code></pre></div></div>
<p>Then, in order to launch it with <code class="language-plaintext highlighter-rouge">Super + L</code>, add the following snippet to the global keys section of <code class="language-plaintext highlighter-rouge">~/.config/awesome/rc.lua</code>.
After restarting awesome, the new shortcut will also show up in the hotkeys help popup (<code class="language-plaintext highlighter-rouge">Super + S</code>), and will blur & lock the screen when activated.</p>
<div class="language-lua highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">awful</span><span class="p">.</span><span class="n">key</span><span class="p">(</span>
<span class="p">{</span> <span class="n">modkey</span><span class="p">,</span> <span class="p">},</span> <span class="s2">"l"</span><span class="p">,</span>
<span class="k">function</span><span class="p">()</span> <span class="n">awful</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="s2">"lock-screen"</span><span class="p">)</span> <span class="k">end</span><span class="p">,</span>
<span class="p">{</span> <span class="n">description</span> <span class="o">=</span> <span class="s2">"lock the current session"</span><span class="p">,</span> <span class="n">group</span> <span class="o">=</span> <span class="s2">"launcher"</span> <span class="p">}</span>
<span class="p">),</span>
</code></pre></div></div>
<p>Another thing you might want to do is load a prettier built-in theme (before overriding it to your own tastes) - you can list the contents of <code class="language-plaintext highlighter-rouge">/usr/share/awesome/themes</code> to check what alternatives came preinstalled with awesome.
Then, you can change the <code class="language-plaintext highlighter-rouge">beautiful.init()</code> line in <code class="language-plaintext highlighter-rouge">~/.config/awesome/rc.lua</code>, like so:</p>
<div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gd">- beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
</span><span class="gi">+ beautiful.init(gears.filesystem.get_themes_dir() .. "xresources/theme.lua")
</span></code></pre></div></div>
<h2 id="6-pipewire-audio">6. Pipewire audio</h2>
<p>A basic installation like the one we just went through mostly just works out of the box.
I didn’t have to do anything other than plug in my HDMI monitor, wireless mouse and USB keyboard.</p>
<p>Soon enough, however, I realized that audio was missing.
Desktop Linux is somewhat infamous for having audio issues, but I think <a href="https://wiki.archlinux.org/title/PipeWire">PipeWire</a> has made that a thing of the past.
All we need to do is install a few packages (and possibly reboot), then it all just works:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>pacman <span class="nt">-S</span> pipewire <span class="se">\</span>
pipewire-audio pipewire-alsa pipewire-pulse pipewire-jack <span class="se">\</span>
wireplumber alsa-utils
</code></pre></div></div>
<p>You might want to set up keybindings for the following audio related commands:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>alsamixer <span class="nt">-V</span> all <span class="c"># control audio in terminal</span>
<span class="nv">$ </span>pactl set-sink-volume @DEFAULT_SINK@ <span class="nt">-5</span>% <span class="c"># lower volume by 5%</span>
<span class="nv">$ </span>pactl set-sink-volume @DEFAULT_SINK@ +5% <span class="c"># increase volume by 5%</span>
<span class="nv">$ </span>pactl set-sink-mute @DEFAULT_SINK@ toggle <span class="c"># toggle audio mute</span>
<span class="nv">$ </span>pactl set-source-mute @DEFAULT_SOURCE@ toggle <span class="c"># toggle microphone mute</span>
</code></pre></div></div>
<h2 id="7-pacman-and-snapshots">7. Pacman and snapshots</h2>
<p>As promised, we’ll now set up automatic system backups, making use of btrfs snapshots.
These are SYSTEM backups (of the root partition) and not DATA backups (does not include the home partition), intented to enable undoing a bad update or a breaking config change.
You should configure additional backup schemes for user data.</p>
<p>With that disclaimer out of the way, let’s install <a href="https://wiki.archlinux.org/title/Snapper">snapper</a>:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>pacman <span class="nt">-S</span> snapper
<span class="nv">$ </span><span class="nb">sudo </span>snapper <span class="nt">-c</span> root create-config /
</code></pre></div></div>
<p>Snapper saves snapshots under the <code class="language-plaintext highlighter-rouge">/.snapshots</code> mount point; that’s OK.
The issue is that, by default, it creates a subvolume under whatever is currently mounted at <code class="language-plaintext highlighter-rouge">/</code>, but I would rather keep snapshots in the top-level of the btrfs volume structure.
Therefore, I’ll delete the just-created <code class="language-plaintext highlighter-rouge">.snapshots</code> SUBVOLUME and make a new one, mounted at <code class="language-plaintext highlighter-rouge">/.snapshots</code>:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>btrfs subvolume delete /.snapshots
<span class="nv">$ </span><span class="nb">sudo </span>mount <span class="nt">-o</span> <span class="nv">subvolid</span><span class="o">=</span>5 /dev/mapper/arch-root /mnt
<span class="nv">$ </span><span class="nb">sudo </span>btrfs subvolume create /mnt/@snapshots
<span class="nv">$ </span><span class="nb">sudo </span>umount /mnt
<span class="nv">$ </span><span class="nb">sudo mkdir</span> /.snapshots
<span class="nv">$ </span><span class="nb">sudo chmod </span>750 /.snapshots
<span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'UUID=${same_UUID_as_other_subvolumes} /.snapshots btrfs subvol=@snapshots,rw,relatime,space_cache=v2,compress=zstd:1 0 0'</span> | <span class="nb">sudo tee</span> <span class="nt">-a</span> /etc/fstab
<span class="nv">$ </span><span class="nb">sudo </span>mount /.snapshots
</code></pre></div></div>
<p>Then, I’ll disable snapper’s default time-based backups:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo sed</span> <span class="nt">-i</span> <span class="s1">'s/TIMELINE_CREATE="no"/TIMELINE_CREATE="yes"/'</span> /etc/snapper/configs/root
<span class="nv">$ </span><span class="nb">sudo </span>systemctl stop snapper-timeline.timer
<span class="nv">$ </span><span class="nb">sudo </span>systemctl disable snapper-timeline.timer
</code></pre></div></div>
<p>In order to create a snapshot manually, we can run <code class="language-plaintext highlighter-rouge">snapper create</code>.
To list existing snapshots, just use <code class="language-plaintext highlighter-rouge">snapper list</code>.
Each snapshot is a btrfs subvolume and can be mounted as such.</p>
<p>Now, in order to run backups every time we make a potentially breaking change, we’ll install <a href="https://barnettphd.com/snap-pac/configuration.html"><code class="language-plaintext highlighter-rouge">snap-pac</code></a>.
By default, it is configured to create a snapshot of the root partition before and after every time we modify the system with <code class="language-plaintext highlighter-rouge">pacman</code> (installing a package, updating the system, etc).</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>pacman <span class="nt">-S</span> snap-pac
</code></pre></div></div>
<p>You can run <code class="language-plaintext highlighter-rouge">snapper list</code> to see the snapshot which was automatically created after installing <code class="language-plaintext highlighter-rouge">snap-pac</code> itself.
Personally, I preferred to <code class="language-plaintext highlighter-rouge">snapper delete</code> this initial one, just to make sure every change has a <code class="language-plaintext highlighter-rouge">pre</code> and <code class="language-plaintext highlighter-rouge">post</code> snapshot.</p>
<figure class=""><a href="/assets/images/dual-boot/arch-snapper.png" class="image-popup" title="Setting up snapper as an automatic system backup tool for Arch.
"><img src="/assets/images/dual-boot/arch-snapper.png" alt="arch-snapper" /></a><figcaption>
Setting up snapper as an automatic system backup tool for Arch.
</figcaption></figure>
<p>Although the current setup covers changes to the root partition, we might not be able to fully restore the system without kernel backups as well.
The kernel is not currently being backed up, since it lives in the boot partition.
Thankfully, the <a href="https://wiki.archlinux.org/title/System_backup#Snapshots_and_/boot_partition">Arch Wiki has this covered</a> by teaching us how to set up pacman hooks to copy the kernel from the boot partition to our snapshot-able root:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>pacman <span class="nt">-S</span> rsync
<span class="nv">$ </span><span class="nb">sudo mkdir</span> /.bootbackup
<span class="nv">$ </span><span class="nb">sudo mkdir</span> <span class="nt">-p</span> /etc/pacman.d/hooks
<span class="nv">$ </span>nano /etc/pacman.d/hooks/95-bootbackup_pre.hook
<span class="nv">$ </span><span class="nb">cat</span> /etc/pacman.d/hooks/95-bootbackup_pre.hook
<span class="o">[</span>Trigger]
Operation <span class="o">=</span> Upgrade
Operation <span class="o">=</span> Install
Operation <span class="o">=</span> Remove
Type <span class="o">=</span> Path
Target <span class="o">=</span> usr/lib/modules/<span class="k">*</span>/vmlinuz
<span class="o">[</span>Action]
Depends <span class="o">=</span> rsync
Description <span class="o">=</span> Backing up pre /boot...
When <span class="o">=</span> PreTransaction
Exec <span class="o">=</span> /usr/bin/bash <span class="nt">-c</span> <span class="s1">'rsync -a --mkpath --delete /boot/ "/.bootbackup/$(date +%Y-%m-%d.%Hh%Mm%Ss).pre"/'</span>
<span class="nv">$ </span>nano /etc/pacman.d/hooks/95-bootbackup_post.hook
<span class="nv">$ </span><span class="nb">cat</span> /etc/pacman.d/hooks/95-bootbackup_post.hook
<span class="o">[</span>Trigger]
Operation <span class="o">=</span> Upgrade
Operation <span class="o">=</span> Install
Operation <span class="o">=</span> Remove
Type <span class="o">=</span> Path
Target <span class="o">=</span> usr/lib/modules/<span class="k">*</span>/vmlinuz
<span class="o">[</span>Action]
Depends <span class="o">=</span> rsync
Description <span class="o">=</span> Backing up post /boot...
When <span class="o">=</span> PostTransaction
Exec <span class="o">=</span> /usr/bin/bash <span class="nt">-c</span> <span class="s1">'rsync -a --mkpath --delete /boot/ "/.bootbackup/$(date +%Y-%m-%d.%Hh%Mm%Ss).post"/'</span>
</code></pre></div></div>
<p>We can now run a full system update, with confidence that we can revert it in case things break.
(In fact, it is a good idea to keep you Arch ISO live USB around, since <a href="https://bbs.archlinux.org/viewtopic.php?pid=1508842#p1508842">restoring your system from these snapshots</a> may require manual intervention).</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>pacman <span class="nt">-Syu</span>
</code></pre></div></div>
<h2 id="8-other-customizations">8. Other customizations</h2>
<p>In the previous Arch tutorial, we went from a live USB to a minimal installation, with not much other than network connectivity.
In this one, we moved from a TTY login to a graphical desktop environment, with auto-login, a terminal emulator, a working audio system, automatic backups and a fully customizable window manager; with a web browser being just a <code class="language-plaintext highlighter-rouge">pacman -S</code> away.</p>
<p>The result might still look and feel too barebones for some people, but after this point each one can customize the system however they like.
That’s the beauty of (Arch) Linux: this system is now yours, do with it whatever you want.
Enjoy!</p>]]></content><author><name>Gabriel B. Sant'Anna</name></author><category term="tutorial" /><category term="linux" /><summary type="html"><![CDATA[Advanced dual-boot setup - Part 4: From TTY to graphical desktop]]></summary></entry><entry><title type="html">How to set up lvmcache across LUKS-encrypted partitions</title><link href="https://www.baioc.dev/tutorial/ubuntu-lvmcache/" rel="alternate" type="text/html" title="How to set up lvmcache across LUKS-encrypted partitions" /><published>2024-07-14T00:00:00+00:00</published><updated>2024-07-21T00:00:00+00:00</updated><id>https://www.baioc.dev/tutorial/ubuntu-lvmcache</id><content type="html" xml:base="https://www.baioc.dev/tutorial/ubuntu-lvmcache/"><![CDATA[<p>In this tutorial, I’ll set up an <code class="language-plaintext highlighter-rouge">lvmcache</code> across LUKS-encrypted partitions in a Debian-based system.
This was the solution I chose to increase the performance of hybrid storage - in which part of the SSD acts as a cache to the HDD - in a fully-encrypted setup.</p>
<p>Starting from a fresh <a href="../ubuntu-24.04-encrypted">Ubuntu 24.04 LTS encrypted install</a>, we’ll:</p>
<ul>
<li>Shrink the root volume in order to free disk space in the primary disk (SSD)</li>
<li>Create an encrypted partition in the secondary disk (HDD)</li>
<li>Configure a volume in the SSD as a cache for the HDD volume</li>
<li>Set up initramfs hooks to mount everything on boot, with a single decryption password</li>
</ul>
<h2 id="0-prepare-operating-environment">0. Prepare operating environment</h2>
<p>While I’m sure some of the operations we’re about to perform could be applied to a live system, I prefer to do these things from a live USB.
I’ll use an Arch Linux ISO for this, since it is lightweight and includes all the tools we need.</p>
<h2 id="1-reduce-root-ssd-volume">1. Reduce root SSD volume</h2>
<p>After flashing the ISO to a USB and booting into it, we start by decrypting the Ubuntu LUKS partition (<code class="language-plaintext highlighter-rouge">/dev/sda3</code> in this case).
Then, we can resize the filesystem and reduce the logical volume in one go (in this case, freeing up 5GiB in the primary LVM physical volume):</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>cryptsetup open /dev/sda3 ubuntu-root
<span class="nv">$ </span>lvreduce <span class="nt">-v</span> <span class="nt">--resizefs</span> <span class="nt">-L</span> <span class="nt">-5G</span> /dev/ubuntu-vg/ubuntu-lv
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-lvreduce.png" class="image-popup" title="Shrinking the Ubuntu root logical volume.
"><img src="/assets/images/dual-boot/lvmcache-lvreduce.png" alt="lvmcache-lvreduce" /></a><figcaption>
Shrinking the Ubuntu root logical volume.
</figcaption></figure>
<h2 id="2-create-an-encrypted-partition">2. Create an encrypted partition</h2>
<p>Let’s set up the HDD LUKS-encrypted partition, making sure that:</p>
<ul>
<li>We use the same encryption password as in the root volume (this is optional, but allows us to use the <code class="language-plaintext highlighter-rouge">decrypt_keyctl</code> script to unlock both partitions with a single password prompt)</li>
<li>The sector size used in the HDD partition matches the one in the SSD (this is mandatory as far as I’m aware, otherwise LVM won’t let us extend the volume group, issuing an error like <code class="language-plaintext highlighter-rouge">Devices have inconsistent logical block sizes</code>)</li>
</ul>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-luksFormat.png" class="image-popup" title="Setting up a new LUKS-encrypted partition with the right sector size, as verified with lsblk -t
"><img src="/assets/images/dual-boot/lvmcache-luksFormat.png" alt="lvmcache-luksFormat" /></a><figcaption>
Setting up a new LUKS-encrypted partition with the right sector size, as verified with lsblk -t
</figcaption></figure>
<h2 id="3-extend-lvm-volume-group">3. Extend LVM volume group</h2>
<p>Next, we layer an LVM physical volume on top of the new LUKS partition, then add it to the existing LVM volume group.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>pvcreate /dev/mapper/ubuntu-data
<span class="nv">$ </span>vgextend ubuntu-vg /dev/mapper/ubuntu-data
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-vgextend.png" class="image-popup" title="Extending an existing LVM volume group with a new physical volume.
"><img src="/assets/images/dual-boot/lvmcache-vgextend.png" alt="lvmcache-vgextend" /></a><figcaption>
Extending an existing LVM volume group with a new physical volume.
</figcaption></figure>
<p>NOTE: if you need to close a LUKS+LVM partition for any reason, you many need to stop the volume group with <code class="language-plaintext highlighter-rouge">vgchange -a n ubuntu-vg</code> before <code class="language-plaintext highlighter-rouge">cryptsetup close</code>ing the partition.</p>
<h2 id="4-set-up-the-lvmcache">4. Set up the lvmcache</h2>
<p>In order to create the cache, we’ll need a logical volume in each device:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>lvcreate <span class="nt">-n</span> work-hdd <span class="nt">-l</span> 100%PVS ubuntu-vg /dev/mapper/ubuntu-data
<span class="nv">$ </span>lvcreate <span class="nt">-n</span> work-ssd <span class="nt">-l</span> 100%PVS ubuntu-vg /dev/mapper/ubuntu-root
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-lvcreate.png" class="image-popup" title="Creating a logical volume in each device.
"><img src="/assets/images/dual-boot/lvmcache-lvcreate.png" alt="lvmcache-lvcreate" /></a><figcaption>
Creating a logical volume in each device.
</figcaption></figure>
<p>Then, we follow <a href="https://www.man7.org/linux/man-pages/man7/lvmcache.7.html">the documentation</a> in order to create the cache as either a <code class="language-plaintext highlighter-rouge">--cachepool</code> or a <code class="language-plaintext highlighter-rouge">--cachevol</code> (see <a href="https://unix.stackexchange.com/questions/647225/lvmcache-why-use-a-cachepool-instead-of-a-cachevol/767061#767061">this StackOverflow question</a> for more information on the choice):</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>lvconvert <span class="nt">--type</span> cache <span class="nt">--cachepool</span> work-ssd ubuntu-vg/work-hdd
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-lvconvert.png" class="image-popup" title="Converting volumes to an lvmcache. Notice that, like me, you may need to shrink the slower volume to accommodate LVM metadata.
"><img src="/assets/images/dual-boot/lvmcache-lvconvert.png" alt="lvmcache-lvconvert" /></a><figcaption>
Converting volumes to an lvmcache. Notice that, like me, you may need to shrink the slower volume to accommodate LVM metadata.
</figcaption></figure>
<p>In order to make use of the cache, just use the <code class="language-plaintext highlighter-rouge">work-hdd</code> logical volume normally.
For example, this would be a good time to add a filesystem to the cached volume:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>mkfs.ext4 /dev/ubuntu-vg/work-hdd
</code></pre></div></div>
<h2 id="5-reboot-to-ubuntu">5. Reboot to Ubuntu</h2>
<p>We should now be able to reboot into Ubuntu, albeit with a small hiccup: after entering our decryption password, the boot process may drop into a BusyBox recovery shell.
There’s no need to panic, a first <code class="language-plaintext highlighter-rouge">exit</code> command will tip us that the reason for failure is that something went wrong when mounting the root volume.</p>
<p>In this case, that’s because we never told the system that it needed to decrypt the HDD partition, and LVM fails by default when a volume group is incomplete.
We can run <code class="language-plaintext highlighter-rouge">lvm lvdisplay</code> to check that, while the new logical volume is not available, the old one (containing the system root) still is.
Therefore, we just activate the volume group in partial mode with <code class="language-plaintext highlighter-rouge">lvm vgchange -a y --partial ubuntu-vg</code>, then <code class="language-plaintext highlighter-rouge">exit</code> again to finish the boot process.</p>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-busybox.png" class="image-popup" title="Continuing a failed boot process with a partial LVM volume group.
"><img src="/assets/images/dual-boot/lvmcache-busybox.png" alt="lvmcache-busybox" /></a><figcaption>
Continuing a failed boot process with a partial LVM volume group.
</figcaption></figure>
<h2 id="6-setting-up-decryption">6. Setting up decryption</h2>
<p>Once the boot process is done, open a terminal to decrypt the remaining partition - the LVM volumes inside should also get recognized automatically.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>cryptsetup open /dev/sdb1 ubuntu-data
</code></pre></div></div>
<p>We’ll now set up <a href="https://unix.stackexchange.com/questions/392284/using-a-single-passphrase-to-unlock-multiple-encrypted-disks-at-boot/392286#392286">a script</a> which will cache our decryption password in order to open both of our LUKS partitions during the boot process (more specifically, by the initramfs image which is loaded from the boot partition).</p>
<p>We begin by installing the <code class="language-plaintext highlighter-rouge">keyutils</code> package.
Then, edit the <code class="language-plaintext highlighter-rouge">/etc/crypttab</code> file in order to add the <code class="language-plaintext highlighter-rouge">keyscript</code> option and set up the same <code class="language-plaintext highlighter-rouge">CRYPTTAB_KEY</code> for both entries.
We also add the <code class="language-plaintext highlighter-rouge">initramfs</code> options and <a href="https://unix.stackexchange.com/questions/206754/difference-between-cryptopts-and-crypttab/447676#447676">make sure it will be handled there</a> by setting <code class="language-plaintext highlighter-rouge">CRYPTSETUP=y</code> in <code class="language-plaintext highlighter-rouge">/etc/cryptsetup-initramfs/conf-hook</code>.
Finally, re-generate the initramfs with <code class="language-plaintext highlighter-rouge">update-initramfs</code>.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>apt <span class="nb">install </span>keyutils
<span class="nv">$ </span><span class="nb">sudo </span>nano /etc/crypttab
<span class="nv">$ </span><span class="nb">sudo </span>nano /etc/cryptsetup-initramfs/conf-hook
<span class="nv">$ </span><span class="nb">sudo </span>update-initramfs <span class="nt">-k</span> all <span class="nt">-u</span>
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-keyscript.png" class="image-popup" title="Setting up the decrypt_keyctl script after some sanity checks.
"><img src="/assets/images/dual-boot/lvmcache-keyscript.png" alt="lvmcache-keyscript" /></a><figcaption>
Setting up the decrypt_keyctl script after some sanity checks.
</figcaption></figure>
<p>After those steps, we can reboot to check that we’ll no longer drop to a BusyBox recovery shell.
Furthermore, from now on, both partitions will be unlocked by a single boot password prompt.</p>
<h2 id="7-mount-the-cached-partition">7. Mount the cached partition</h2>
<p>Finally, we can set up an entry in <code class="language-plaintext highlighter-rouge">/etc/fstab</code> in order to automatically mount our cached partition.
In my case, I’ll create an <code class="language-plaintext highlighter-rouge">/hdd</code> folder that’s owned by my main user, but another possibility would be mounting to <code class="language-plaintext highlighter-rouge">/home</code> directly (make sure to have backups, if you do).</p>
<p>I should note that, in order to use UUIDs to reference an LVM logical volume in fstab, we need to combine the volume group (VG) UUID and the logical volume (LV) UUID.
We can acquire those with <code class="language-plaintext highlighter-rouge">vgdisplay</code> and <code class="language-plaintext highlighter-rouge">lvdisplay</code>, respectively, then remove the hyphens and concatenate them to get the full LVM device mapper UUID path.</p>
<figure class=""><a href="/assets/images/dual-boot/lvmcache-fstab.png" class="image-popup" title="Setting up fstab to auto-mount the cached volume.
"><img src="/assets/images/dual-boot/lvmcache-fstab.png" alt="lvmcache-fstab" /></a><figcaption>
Setting up fstab to auto-mount the cached volume.
</figcaption></figure>
<p>In the end, we have most of the system stored in the faster SSD, while our user data can stay in the bigger (but slower) HDD - both devices using LUKS encryption.
The LVM subsystem will then take care of moving frequently accessed HDD data into the SSD cache - automatically improving performance for the data that’s actually being used.
Victory!</p>]]></content><author><name>Gabriel B. Sant'Anna</name></author><category term="tutorial" /><category term="linux" /><summary type="html"><![CDATA[Advanced dual-boot setup - Part 3: Encrypted hybrid storage]]></summary></entry><entry><title type="html">How to install Arch on Btrfs with LUKS encryption and software RAID1</title><link href="https://www.baioc.dev/tutorial/arch-btrfs-luks-raid/" rel="alternate" type="text/html" title="How to install Arch on Btrfs with LUKS encryption and software RAID1" /><published>2024-05-17T00:00:00+00:00</published><updated>2024-07-27T00:00:00+00:00</updated><id>https://www.baioc.dev/tutorial/arch-btrfs-luks-raid</id><content type="html" xml:base="https://www.baioc.dev/tutorial/arch-btrfs-luks-raid/"><![CDATA[<p>This tutorial is written for my own future reference, but I’m also posting it online in case it helps someone else looking for a similar setup.
While the <a href="../dual-boot-linux-encrypted-hybrid-storage">first post on this series</a> already laid out my specs, motivations and technological choices, this one will focus on implementing the core parts of my personal subsystem: an encrypted Arch Linux installation on top of Btrfs, with RAID1.</p>
<h2 id="0-overview">0. Overview</h2>
<p>Here’s a sketch of what I’m aiming for:</p>
<p><img src="/assets/images/dual-boot/os-arch.png" alt="sketch-arch" /></p>
<p>During <a href="../ubuntu-24.04-encrypted">the previous part of this series</a>, I’ve used the Ubuntu 24.04 LTS guided installer to create an ESP partition (<code class="language-plaintext highlighter-rouge">sda1</code>, in green) and the core parts of my work subsystem (<code class="language-plaintext highlighter-rouge">sda4</code> and <code class="language-plaintext highlighter-rouge">sda5</code>, in orange).
This post will set up the remaining SSD partitions, as well as the HDD RAID1 mirror.</p>
<p>I’ll follow the general structure of <a href="https://wiki.archlinux.org/title/Installation_guide">the Arch wiki’s installation guide</a>, with a few added comments and highlighting deviations from the standard route for my customizations.</p>
<h2 id="1-pre-installation">1. Pre-installation</h2>
<h3 id="11-acquire-an-installation-image">1.1. Acquire an installation image</h3>
<p>Just download the latest ISO image from the <a href="https://archlinux.org/download/">official Arch download page</a>.</p>
<h3 id="12-verify-image-hashes">1.2. Verify image hashes</h3>
<p>Make sure the ISO’s <code class="language-plaintext highlighter-rouge">sha256sum</code> matches the expected hash (<code class="language-plaintext highlighter-rouge">1b4a04ef8a7350852a13070ee498442b087a607a18840b4dd7d99867eb5f6a4c</code> for 2024.05.01).</p>
<h3 id="13-prepare-installation-medium">1.3. Prepare installation medium</h3>
<p><a href="https://wiki.archlinux.org/title/USB_flash_installation_medium">Flash the image on a USB stick</a>.</p>
<h3 id="14-boot-the-live-environment">1.4. Boot the live environment</h3>
<p>You’ll find yourself logged as root in a Zsh shell.
<a href="https://geo.mirror.pkgbuild.com/iso/latest/arch/pkglist.x86_64.txt">These pacakges</a> come pre-installed.</p>
<figure class=""><a href="/assets/images/dual-boot/arch-tty.png" class="image-popup" title="Arch install live environment, after a few sanity checks.
"><img src="/assets/images/dual-boot/arch-tty.png" alt="arch-tty" /></a><figcaption>
Arch install live environment, after a few sanity checks.
</figcaption></figure>
<h3 id="15-set-the-console-keyboard">1.5. Set the console keyboard</h3>
<p>Nothing to do here, since I use a US keyboard layout.</p>
<h3 id="16-verify-the-boot-mode">1.6. Verify the boot mode</h3>
<p><code class="language-plaintext highlighter-rouge">cat /sys/firmware/efi/fw_platform_size</code> should read <code class="language-plaintext highlighter-rouge">64</code>.</p>
<h3 id="17-connect-to-the-internet">1.7. Connect to the internet</h3>
<p>Just use ethernet.
The live system connects automatically using DHCP.
<br />
Make sure your connection is actually working by <code class="language-plaintext highlighter-rouge">ping</code>ing an external server.</p>
<h3 id="18-update-the-system-clock">1.8. Update the system clock</h3>
<p>Check if the output of <code class="language-plaintext highlighter-rouge">timedatectl</code> looks sane (in UTC+0).</p>
<h3 id="19-partition-the-disks">1.9. Partition the disks</h3>
<p>This is where it gets interesting.
I already know how I want to partition my disks, but here are a few highlights copied straight from the Arch wiki:</p>
<blockquote>
<ul>
<li>Take time to plan a long-term partitioning scheme to avoid risky and complicated conversion or re-partitioning procedures in the future.</li>
</ul>
</blockquote>
<p><a href="../dual-boot-linux-encrypted-hybrid-storage">Done</a>.</p>
<blockquote>
<ul>
<li>The following partitions are required for a chosen device: one partition for the root directory <code class="language-plaintext highlighter-rouge">/</code>; for booting in UEFI mode: an EFI system partition.</li>
<li>If the disk from which you want to boot already has an EFI system partition, do not create another one, but use the existing partition instead.</li>
<li>Swap space can be set on a swap file for file systems supporting it.</li>
</ul>
</blockquote>
<p>We already have an EFI partition created by the Ubuntu installer, so we’ll keep using that.
Then, instead of a single root partition mounted at <code class="language-plaintext highlighter-rouge">/</code>, we’ll create separate root (<code class="language-plaintext highlighter-rouge">/</code>) and boot (<code class="language-plaintext highlighter-rouge">/boot/</code>) partitions, since we want the former to be encrypted (and the latter can’t be, depending on the <a href="https://en.wikipedia.org/wiki/Bootloader#Second-stage_boot_loader">second-stage boot loader</a> we end up using).
Finally, if swap is needed at all I’ll just use a swap file, since that’s supported on our filesystem of choice, Btrfs.</p>
<blockquote>
<p>Aligning partitions correctly avoids excessive read-modify-write cycles.
A typical practice for personal computers is to have each partition’s start and size aligned to 1 MiB (1 048 576 bytes) marks.
This covers all common page and block size scenarios, as it is divisible by all commonly used sizes - 1 MiB, 512 KiB, 128 KiB, 4 KiB, and 512 B.
Warning: Misaligned partitions will prevent being able to use 4096 B sectors with LUKS.</p>
</blockquote>
<p>This important disk performance tip was hidden away in the <a href="https://wiki.archlinux.org/title/Advanced_Format#Partition_alignment">Advanced Format page</a>.
Even though most disk partitioning tools default to MiB alignment, I think this should be highlighted in the partitioning step of the installation guide.</p>
<blockquote>
<p>If you want to create any stacked block devices for LVM, encryption or RAID, do it now.</p>
</blockquote>
<h4 id="191-securely-erasing-a-drive">1.9.1. Securely erasing a drive</h4>
<p>I’m going to err on the side of caution and <a href="https://wiki.archlinux.org/title/Dm-crypt/Drive_preparation#dm-crypt_wipe_on_an_empty_device_or_partition">securely erase my entire HDD</a>:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wipefs <span class="nt">-a</span> /dev/sdb
cryptsetup open <span class="nt">--type</span> plain <span class="nt">-d</span> /dev/urandom <span class="nt">--sector-size</span> 4096 <span class="nt">--cipher</span> aes-xts-plain64:sha256 <span class="nt">--key-size</span> 256 /dev/sdb to_be_wiped
<span class="nb">dd </span><span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span>/dev/mapper/to_be_wiped <span class="nv">status</span><span class="o">=</span>progress <span class="nv">bs</span><span class="o">=</span>1M
cryptsetup close to_be_wiped
</code></pre></div></div>
<p>Here I’ve manually specified the fastest (according to a <code class="language-plaintext highlighter-rouge">cryptsetup benchmark</code>) combination of cipher and key size, as well as the physical sector size of my HDD (obtained with <code class="language-plaintext highlighter-rouge">lsblk -t</code>).</p>
<h4 id="192-physical-partitioning">1.9.2. Physical partitioning</h4>
<p>This is what our disks looked like after our encrypted Ubuntu 24.04 installation:</p>
<figure class=""><a href="/assets/images/dual-boot/ubuntu-partition-layout.png" class="image-popup" title="Disk layout after the Ubuntu install. sda is an SSD and sdb a bigger HDD.
"><img src="/assets/images/dual-boot/ubuntu-partition-layout.png" alt="ubuntu-partition-layout" /></a><figcaption>
Disk layout after the Ubuntu install. sda is an SSD and sdb a bigger HDD.
</figcaption></figure>
<p>Everything on the SSD is already MiB aligned.
You can check that manually by running <code class="language-plaintext highlighter-rouge">fdisk -l</code> and making sure the start sector and total sectors assigned to each partition are divisible by 8.
Then, I’ll just wipe the placeholder ext2 file systems which I used to “hide” available disk space from the Ubuntu installer:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wipefs <span class="nt">-a</span> /dev/sda2
wipefs <span class="nt">-a</span> /dev/sda3
</code></pre></div></div>
<p>As for the just-erased HDD, I’ll use <code class="language-plaintext highlighter-rouge">fdisk</code>’s interactive shell to:</p>
<ul>
<li>Set up a fresh GPT partition table (<code class="language-plaintext highlighter-rouge">g</code>)</li>
<li>Create a new partition the exact same size of <code class="language-plaintext highlighter-rouge">/dev/sda3</code> (<code class="language-plaintext highlighter-rouge">n</code>)</li>
<li>Commit my changes (<code class="language-plaintext highlighter-rouge">w</code>)</li>
</ul>
<h4 id="193-raid-on-hybrid-storage">1.9.3. RAID on hybrid storage</h4>
<p>We’ll now set up software RAID1 using mdadm.
In my particular case, I’ll have a <a href="https://www.tansi.org/hybrid/">hybrid RAID1 setup</a>: one of the mirrors is in an SSD, while the other is in an HDD.
Thankfully, mdadm has a <a href="https://raid.wiki.kernel.org/index.php/Write-mostly">“write-mostly” flag</a> which can mark expected-to-be-slower devices (<code class="language-plaintext highlighter-rouge">/dev/sdb</code>) in the array in order to make most reads come from the faster device (<code class="language-plaintext highlighter-rouge">/dev/sda</code>).
Setting it up is as simple as:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mdadm <span class="nt">--verbose</span> <span class="nt">--create</span> <span class="nt">--metadata</span><span class="o">=</span>0.90 /dev/md0 <span class="nt">--level</span><span class="o">=</span>1 <span class="nt">--raid-devices</span><span class="o">=</span>2 /dev/sda3 <span class="nt">--write-mostly</span> /dev/sdb1
</code></pre></div></div>
<p>Before continuing, <code class="language-plaintext highlighter-rouge">watch /proc/mdstat</code> to make sure the array had enough time to resync.</p>
<figure class=""><a href="/assets/images/dual-boot/arch-mdadm.png" class="image-popup" title="Setting up software RAID on Linux is easier than I imagined.
"><img src="/assets/images/dual-boot/arch-mdadm.png" alt="arch-mdadm" /></a><figcaption>
Setting up software RAID on Linux is easier than I imagined.
</figcaption></figure>
<h4 id="194-luks-encryption">1.9.4. LUKS encryption</h4>
<p>Setting up dm-crypt / LUKS encryption on top of a RAID1 array is also quite simple:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cryptsetup <span class="nt">-v</span> luksFormat /dev/md0
cryptsetup open <span class="nt">--allow-discards</span> /dev/md0 arch-root
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/arch-cryptsetup.png" class="image-popup" title="Save for discards, the default LUKS settings in this version of cryptsetup are exactly what I want for this particular system.
"><img src="/assets/images/dual-boot/arch-cryptsetup.png" alt="arch-cryptsetup" /></a><figcaption>
Save for discards, the default LUKS settings in this version of cryptsetup are exactly what I want for this particular system.
</figcaption></figure>
<h3 id="110-format-the-partitions">1.10. Format the partitions</h3>
<p>As planned, I’ll use ext4 for my boot partition and Btrfs (on LUKS, on RAID) for the rest:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkfs.ext4 /dev/sda2
mkfs.btrfs /dev/mapper/arch-root
</code></pre></div></div>
<h3 id="111-mount-the-file-systems">1.11. Mount the file systems</h3>
<p>I’ll start by temporarily mounting my Btrfs root at <code class="language-plaintext highlighter-rouge">/mnt</code>.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount <span class="nt">-o</span> defaults,compress<span class="o">=</span>zstd:1,ssd,discard<span class="o">=</span>async,noatime /dev/mapper/arch-root /mnt
</code></pre></div></div>
<ul>
<li>Compression is one of the reasons I chose Btrfs, and after looking at <a href="https://www.phoronix.com/review/btrfs-zstd-compress/2">a few</a> <a href="https://www.reddit.com/r/btrfs/comments/bpphbz/my_benchmarks_of_the_new_zstd_levels_in_51/">benchmarks</a>, it seems that <code class="language-plaintext highlighter-rouge">zstd:1</code> is the best compromise on compression ratio and CPU usage.</li>
<li>Apparently, Btrfs does not add <code class="language-plaintext highlighter-rouge">ssd</code> or <code class="language-plaintext highlighter-rouge">discard</code> options by default when it is mounted on top of LUKS/RAID, so I’ll add those manually.</li>
<li>Finally, I use <code class="language-plaintext highlighter-rouge">noatime</code> in order to avoid unnecessary writes on the hybrid RAID1 setup, since they’ll have HDD speeds and I want to preserve SSD read performance.</li>
</ul>
<p>Now, since the filesystem is empty, this is probably the most convenient moment to set up other Btrfs subvolumes.
I’ll follow the <a href="https://wiki.archlinux.org/title/snapper#Suggested_filesystem_layout">suggested filesystem layout for Snapper</a>, with separate subvolumes <code class="language-plaintext highlighter-rouge">@</code> and <code class="language-plaintext highlighter-rouge">@home</code> for <code class="language-plaintext highlighter-rouge">/</code> and <code class="language-plaintext highlighter-rouge">/home</code> respectively, then <code class="language-plaintext highlighter-rouge">@var_log</code> to exclude <code class="language-plaintext highlighter-rouge">/var/log</code> from root snapshots (note: I may have to create more subvolumes in the future in order to have separately-snapshottable containers, databases, and the like).</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@var_log
</code></pre></div></div>
<p>Now, in order to actually use the <code class="language-plaintext highlighter-rouge">@</code> subvolume as our <code class="language-plaintext highlighter-rouge">/</code> mountpoint (as opposed to mounting <code class="language-plaintext highlighter-rouge">/</code> directly on the root subvolume a.k.a. <code class="language-plaintext highlighter-rouge">subvolid=5</code>), we’ll unmount the current root:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount /mnt
</code></pre></div></div>
<p>And then set up mountpoints (subvolumes and normal partitions alike) in the way they’re actually going to be used in the installed system, in hierarchical order:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount <span class="nt">-o</span> <span class="nv">subvol</span><span class="o">=</span>@,defaults,compress<span class="o">=</span>zstd:1,ssd,discard<span class="o">=</span>async,noatime /dev/mapper/arch-root /mnt/
<span class="nb">mkdir</span> <span class="nt">-p</span> /mnt/home
mount <span class="nt">-o</span> <span class="nv">subvol</span><span class="o">=</span>@home,defaults,compress-force<span class="o">=</span>zstd:1,ssd,discard<span class="o">=</span>async,noatime /dev/mapper/arch-root /mnt/home
<span class="nb">mkdir</span> <span class="nt">-p</span> /mnt/var/log
mount <span class="nt">-o</span> <span class="nv">subvol</span><span class="o">=</span>@var_log,defaults,compress<span class="o">=</span>zstd:1,ssd,discard<span class="o">=</span>async /dev/mapper/arch-root /mnt/var/log
<span class="nb">mkdir</span> <span class="nt">-p</span> /mnt/boot
mount /dev/sda2 /mnt/boot
<span class="nb">mkdir</span> <span class="nt">-p</span> /mnt/boot/efi
mount /dev/sda1 /mnt/boot/efi
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/arch-btrfs.png" class="image-popup" title="Setting up mount points for subvolumes and partitions alike.
"><img src="/assets/images/dual-boot/arch-btrfs.png" alt="arch-btrfs" /></a><figcaption>
Setting up mount points for subvolumes and partitions alike.
</figcaption></figure>
<h2 id="2-installation">2. Installation</h2>
<h3 id="21-select-the-mirrors">2.1. Select the mirrors</h3>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>reflector <span class="nt">-p</span> https <span class="nt">-l</span> 100 <span class="nt">--sort</span> rate <span class="nt">-n</span> 20 <span class="nt">--save</span> /etc/pacman.d/mirrorlist
</code></pre></div></div>
<h3 id="22-install-essential-packages">2.2. Install essential packages</h3>
<p>This is where we decide what packages we want in our initial install:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pacstrap <span class="nt">-K</span> /mnt <span class="se">\</span>
base <span class="nb">sudo </span>systemd less which lsof <span class="se">\</span>
linux-zen linux linux-firmware <span class="se">\</span>
intel-ucode <span class="se">\</span>
e2fsprogs dosfstools cryptsetup lvm2 mdadm btrfs-progs <span class="se">\</span>
networkmanager <span class="nb">bind </span>whois wget curl <span class="se">\</span>
nano vim <span class="se">\</span>
man-db man-pages <span class="se">\</span>
refind efibootmgr mkinitcpio <span class="se">\</span>
base-devel cmake git python gnupg openssh diffutils <span class="se">\</span>
bash-completion htop tree xxd dmidecode usbutils perl-image-exiftool sysstat bat inxi
</code></pre></div></div>
<h2 id="3-configure-the-system">3. Configure the system</h2>
<h3 id="30-update-raid-config-file">3.0. Update RAID config file</h3>
<p>Since we’re using RAID, we need to update the default mdadm configuration file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mdadm <span class="nt">--detail</span> <span class="nt">--scan</span> <span class="o">>></span> /mnt/etc/mdadm.conf
</code></pre></div></div>
<p>Then open it on a text editor to make sure it looks OK.</p>
<h3 id="31-fstab">3.1. Fstab</h3>
<p>Similarly, for the fstab file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>genfstab <span class="nt">-U</span> /mnt <span class="o">>></span> /mnt/etc/fstab
</code></pre></div></div>
<h3 id="32-chroot">3.2. Chroot</h3>
<p>Now, we’ll be chrooting into the new system:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>arch-chroot /mnt
</code></pre></div></div>
<h3 id="33-time">3.3. Time</h3>
<p>If you want the system’s local time to be in your own timezone instead of UTC:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ln</span> <span class="nt">-sf</span> /usr/share/zoneinfo/<span class="nv">$REGION</span>/<span class="nv">$CITY</span> /etc/localtime
hwclock <span class="nt">--systohc</span>
</code></pre></div></div>
<h3 id="34-localization">3.4. Localization</h3>
<p>Edit <code class="language-plaintext highlighter-rouge">/etc/locale.gen</code> and uncomment <code class="language-plaintext highlighter-rouge">en_US.UTF-8 UTF-8</code>, as well as any other needed UTF-8 locales.
Then, generate the locales and set the system locale with:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>locale-gen
<span class="nb">echo</span> <span class="s1">'LANG=en_US.UTF-8'</span> <span class="o">></span> /etc/locale.conf
</code></pre></div></div>
<h3 id="35-network-configuration">3.5. Network configuration</h3>
<p>Create a hostname file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">'my-cool-hostname'</span> <span class="o">></span> /etc/hostname
</code></pre></div></div>
<p>And, in my case, I’ll manually enable the NetworkManager systemd unit:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ln</span> <span class="nt">-s</span> /usr/lib/systemd/system/NetworkManager.service /etc/systemd/system/multi-user.target.wants/
</code></pre></div></div>
<h3 id="36-initramfs">3.6. Initramfs</h3>
<p>In this setup, where I’m using LUKS encryption and software RAID, I needed to add <code class="language-plaintext highlighter-rouge">mdadm_udev</code> and <code class="language-plaintext highlighter-rouge">encrypt</code> to my initramfs hooks in <code class="language-plaintext highlighter-rouge">/etc/mkinitcpio.conf</code>:</p>
<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">HOOKS</span>=(<span class="n">base</span> <span class="n">udev</span> <span class="n">autodetect</span> <span class="n">microcode</span> <span class="n">modconf</span> <span class="n">kms</span> <span class="n">keyboard</span> <span class="n">keymap</span> <span class="n">consolefont</span> <span class="n">block</span> <span class="n">mdadm_udev</span> <span class="n">encrypt</span> <span class="n">filesystems</span> <span class="n">fsck</span>)
</code></pre></div></div>
<p>Then, in order to actually apply these changes and recreate the initramfs image:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkinitcpio <span class="nt">-P</span>
</code></pre></div></div>
<figure class=""><a href="/assets/images/dual-boot/arch-chroot.png" class="image-popup" title="Note: the mkinitcpio command may issue some warnings while generating the initramfs; I just ignored the ones I got.
"><img src="/assets/images/dual-boot/arch-chroot.png" alt="arch-chroot" /></a><figcaption>
Note: the mkinitcpio command may issue some warnings while generating the initramfs; I just ignored the ones I got.
</figcaption></figure>
<h3 id="37-root-password">3.7. Root password</h3>
<p>We can then set the root password with <code class="language-plaintext highlighter-rouge">passwd</code>.</p>
<h3 id="38-boot-loader">3.8. Boot loader</h3>
<p>In my case, I’ll use <a href="https://www.rodsbooks.com/refind/configfile.html">rEFInd</a> (which I already installed in the <code class="language-plaintext highlighter-rouge">pacstrap</code> command):</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>refind-install
<span class="nb">rm</span> /boot/refind_linux.conf
<span class="nb">cp</span> /boot/efi/EFI/refind/refind.conf /boot/efi/EFI/refind/refind.conf.bak
</code></pre></div></div>
<p>After creating a backup of the original config, I edited <code class="language-plaintext highlighter-rouge">/boot/efi/EFI/refind/refind.conf</code> to reduce the boot timeout, to <a href="https://wiki.archlinux.org/title/REFInd#For_kernels_automatically_detected_by_rEFInd">add support for the naming scheme of Arch Linux kernels</a> and to enable the inclusion of a separate <code class="language-plaintext highlighter-rouge">manual.conf</code> config file.</p>
<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># refind.conf
</span>...
<span class="n">timeout</span> <span class="m">5</span>
...
<span class="n">extra_kernel_version_strings</span> <span class="s2">"linux-hardened,linux-rt-lts,linux-zen,linux-lts,linux-rt,linux"</span>
...
<span class="n">include</span> <span class="n">manual</span>.<span class="n">conf</span>
</code></pre></div></div>
<p>Then, I like to set up a manual boot stanza in <code class="language-plaintext highlighter-rouge">/boot/efi/EFI/refind/manual.conf</code>, which reads:</p>
<div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># manual.conf
</span><span class="n">menuentry</span> <span class="s2">"Arch Linux"</span> {
<span class="n">icon</span> /<span class="n">EFI</span>/<span class="n">refind</span>/<span class="n">icons</span>/<span class="n">os_arch</span>.<span class="n">png</span>
<span class="n">volume</span> <span class="s2">"8B2310D6-C36B-4FB9-929B-F2FF5D5B120D"</span>
<span class="n">loader</span> /<span class="n">vmlinuz</span>-<span class="n">linux</span>-<span class="n">zen</span>
<span class="n">initrd</span> /<span class="n">initramfs</span>-<span class="n">linux</span>-<span class="n">zen</span>.<span class="n">img</span>
<span class="n">options</span> <span class="s2">"cryptdevice=UUID=6fd4672b-5745-404d-a4f2-5cf3984c0ae5:arch-root:allow-discards root=UUID=07a47b01-b163-4e7f-99ab-4c6310c4e4a1 rootflags=subvol=@ rw"</span>
<span class="n">submenuentry</span> <span class="s2">"Boot using fallback initramfs"</span> {
<span class="n">initrd</span> /<span class="n">initramfs</span>-<span class="n">linux</span>-<span class="n">zen</span>-<span class="n">fallback</span>.<span class="n">img</span>
}
}
</code></pre></div></div>
<ul>
<li>We need to specify the <code class="language-plaintext highlighter-rouge">icon</code> token before choosing a boot <code class="language-plaintext highlighter-rouge">volume</code>.</li>
<li>The <code class="language-plaintext highlighter-rouge">volume</code> token is set to the PARTUUID of my <code class="language-plaintext highlighter-rouge">/boot</code> partition (<code class="language-plaintext highlighter-rouge">/dev/sda2</code>).</li>
<li><code class="language-plaintext highlighter-rouge">loader</code> and <code class="language-plaintext highlighter-rouge">initrd</code> paths are set using the specified <code class="language-plaintext highlighter-rouge">volume</code> as a root, so we don’t need to prefix those with <code class="language-plaintext highlighter-rouge">/boot</code>.</li>
<li>The <code class="language-plaintext highlighter-rouge">cryptdevice</code> kernel option must be set with the UUID of a block device of <code class="language-plaintext highlighter-rouge">TYPE="crypto_LUKS"</code>, which corresponds to my software RAID block device.</li>
<li>The UUID in the <code class="language-plaintext highlighter-rouge">root</code> kernel option should match the <code class="language-plaintext highlighter-rouge">/</code> entry in my <code class="language-plaintext highlighter-rouge">fstab</code>.</li>
<li>Since my root filesystem is mounted in a non-default Btrfs subvolume, I need to specify <code class="language-plaintext highlighter-rouge">rootflags=subvol=@</code> as well.</li>
</ul>
<figure class=""><a href="/assets/images/dual-boot/arch-bootloader.png" class="image-popup" title="Configuring the second-stage bootloader has always been the hardest part of installing Linux for me.
"><img src="/assets/images/dual-boot/arch-bootloader.png" alt="arch-bootloader" /></a><figcaption>
Configuring the second-stage bootloader has always been the hardest part of installing Linux for me.
</figcaption></figure>
<h2 id="4-reboot">4. Reboot</h2>
<p>If everything was set up correctly, we should be able to reboot into our freshly-installed system:</p>
<ul>
<li>Leave the chroot environment by exiting the current shell</li>
<li>(Optionally) unmount partitions with <code class="language-plaintext highlighter-rouge">umount -R /mnt</code></li>
<li><code class="language-plaintext highlighter-rouge">reboot</code></li>
<li>Choose the correct option in our boot loader of choice</li>
</ul>
<figure class=""><a href="/assets/images/dual-boot/refind.png" class="image-popup" title="rEFInd has already detected my existing Ubuntu install and has correctly set up a corresponding chain-load entry.
"><img src="/assets/images/dual-boot/refind.png" alt="refind" /></a><figcaption>
rEFInd has already detected my existing Ubuntu install and has correctly set up a corresponding chain-load entry.
</figcaption></figure>
<p>You’ll then be prompted for your disk encryption password before fully booting:</p>
<figure class=""><a href="/assets/images/dual-boot/arch-boot-encrypted.png" class="image-popup"><img src="/assets/images/dual-boot/arch-boot-encrypted.png" alt="arch-boot-encrypted" /></a></figure>
<h2 id="5-post-installation">5. Post-installation</h2>
<p>All done!
I’ll leave any further post-installation steps to <a href="../arch-awesomewm">another post</a>.</p>]]></content><author><name>Gabriel B. Sant'Anna</name></author><category term="tutorial" /><category term="linux" /><summary type="html"><![CDATA[Advanced dual-boot setup - Part 2: I use Arch, btw]]></summary></entry><entry><title type="html">How to install Ubuntu 24.04 LTS with Full Disk Encryption</title><link href="https://www.baioc.dev/tutorial/ubuntu-24.04-encrypted/" rel="alternate" type="text/html" title="How to install Ubuntu 24.04 LTS with Full Disk Encryption" /><published>2024-05-16T00:00:00+00:00</published><updated>2024-05-17T00:00:00+00:00</updated><id>https://www.baioc.dev/tutorial/ubuntu-24.04-encrypted</id><content type="html" xml:base="https://www.baioc.dev/tutorial/ubuntu-24.04-encrypted/"><![CDATA[<p>Ubuntu 24.04 LTS, code name “Noble Numbat”, was <a href="https://wiki.ubuntu.com/Releases">released just 3 weeks ago</a>.
The new installer doesn’t make it obvious, but you can have an encrypted install without erasing / using the entire disk.
Here’s how to do it.</p>
<h2 id="1-acquire-installation-media">1. Acquire installation media</h2>
<ul>
<li>Download the <a href="https://ubuntu.com/download/desktop">official ISO image</a>;</li>
<li>Make sure its <code class="language-plaintext highlighter-rouge">sha256sum</code> matches <a href="https://releases.ubuntu.com/24.04/SHA256SUMS">the expected hash</a> (<code class="language-plaintext highlighter-rouge">81fae9cc21e2b1e3a9a4526c7dad3131b668e346c580702235ad4d02645d9455</code> for 24.04);</li>
<li>Flash the image on a USB stick;</li>
</ul>
<h2 id="2-prepare-the-target-system">2. Prepare the target system</h2>
<ul>
<li>Back up your data;</li>
<li>Boot your computer from the live USB;</li>
<li>Close the installer in order to see the system’s desktop;</li>
<li>Delete or shrink existing partitions in order to make space for Ubuntu:
<ul>
<li>In simple setups, this can be done using GParted or <code class="language-plaintext highlighter-rouge">fdisk</code></li>
<li>More advanced setups require extra steps (e.g; <a href="https://help.ubuntu.com/community/ResizeEncryptedPartitions">resizing encrypted partitions is tricky</a>)</li>
</ul>
</li>
<li>Consider using a <a href="https://wiki.archlinux.org/title/Dm-crypt/Drive_preparation#Secure_erasure_of_the_drive">secure erasing process</a> in case your drive wasn’t encrypted before;</li>
<li>If there’s any disk space you DON’T WANT Ubuntu to occupy, just make sure the installer doesn’t see it as free space by creating dummy partitions there;</li>
</ul>
<h3 id="partition-layout">Partition layout</h3>
<p>Based on my VM tests, here’s how the automated installer lays out partitions:</p>
<ul>
<li>If an ESP partition already exists, it will be used by Ubuntu as well;</li>
<li>Otherwise, a new one is created in the first sector range of the disk with enough free space for it (default size appears to be 1075 MiB);</li>
<li>Then, it chooses another disk chunk to set up a boot partition and a root partition:
<ul>
<li>I’m not sure whether it uses the first free range which can fit the OS, or the biggest such range that it can find;</li>
<li>Either way, the two partitions are laid out one after the other; where the first 1792 MiB are used by the boot partition and everything else is given to the root partition.</li>
</ul>
</li>
</ul>
<p>In my case, I’ve carved out the first 4 GiB and the last 10 GiB as free space.
The remaining disk space between those was reserved by two partitions which I’ll use to <a href="../arch-btrfs-luks-raid">install Arch afterwards</a>.</p>
<h2 id="3-guided-encrypted-install">3. Guided encrypted install</h2>
<ul>
<li>Re-open the installer and follow the wizard until you get to the disk setup page:</li>
</ul>
<figure class=""><a href="/assets/images/dual-boot/ubuntu-install-simple.png" class="image-popup" title="The new installer doesn’t make it obvious, but you can have an encrypted install without erasing the entire disk.
"><img src="/assets/images/dual-boot/ubuntu-install-simple.png" alt="ubuntu-install-simple" /></a><figcaption>
The new installer doesn’t make it obvious, but you can have an encrypted install without erasing the entire disk.
</figcaption></figure>
<ul>
<li>Toggle the “Erase disk” option, just for now;</li>
<li>Go to the “Advanced features” menu and select “Use LVM and encryption”;</li>
</ul>
<figure class=""><a href="/assets/images/dual-boot/ubuntu-advanced-options.png" class="image-popup" title="This tells the installer to encrypt the root partition using LVM on top of LUKS.
"><img src="/assets/images/dual-boot/ubuntu-advanced-options.png" alt="ubuntu-advanced-options" /></a><figcaption>
This tells the installer to encrypt the root partition using LVM on top of LUKS.
</figcaption></figure>
<ul>
<li>If you don’t want to erase the entire disk, make sure to toggle the “Install Ubuntu alongside other partitions” option before continuing;</li>
</ul>
<figure class=""><a href="/assets/images/dual-boot/ubuntu-install-encrypted.png" class="image-popup" title="Can you see the difference between this screenshot and the first one?
"><img src="/assets/images/dual-boot/ubuntu-install-encrypted.png" alt="ubuntu-install-encrypted" /></a><figcaption>
Can you see the difference between this screenshot and the first one?