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
|
---
extends: _layouts.post
section: content
title: Installing Arch Linux on a Thinkpad X220
date: 2020-05-25
description: This is a guide to how I installed Arch Linux onto my Thinkpad X220.
tags: [Arch]
---
## Introduction
So I purchased a used Thinkpad X220 for about £90 on eBay and decided to install Arch Linux onto it. This guide is the steps that I took to achieve this.
Now when it comes to Linux there is always more than one way of doing things and this guide is just my preferred way. Feel free to follow it for your own installation, just keep in mind that you may have to change some of the steps to suit your own circumstances. Also there is every chance that the information presented here will be out of date so I recommend that you at least read the through the [official installation guide](https://www.archlinux.org/Installation_guide/) for the most up-to-date information.
## Download the Arch Linux ISO Image
The Arch Linux [download](https://www.archlinux.org/download/) page provides direct download and torrent links. You should also download the PGP signature to the same location and use the *gpg* command to verify that the ISO has not been compromised.
```shell
$ gpg --keyserver-options auto-key-retrieve --verify archlinux-2020.05.01-x86_64.iso.sig
```
## Create a live USB of Arch Linux
Flash the image to a USB drive using [Etcher](https://www.balena.io/etcher/). Alternatively you can use the dd command. Just ensure that */path/to/archlinux.iso* is to where you have downloaded the image and that */dev/sdx* is your USB drive.
```shell
dd bs=4M if=/path/to/archlinux.iso of=/dev/sdx status=progress && sync
```
## Boot the live environment
I wanted to make sure that the Thinkpad was using UEFI as I would be using EFISTUB to load the Linux kernel as an EFI executable. This is done through the BIOS which can be gotten to by pressing the *ThinkVantage* button as the machine is booting before pressing *F1* to get to the BIOS settings. From there navigate to *Startup* and changed the *UEFI/Legacy Boot* option to be *UEFI Only*. Press *F10* to save and exit the BIOS and then power down the machine.
With the USB drive plugged in power the machine back on, all the while pressing *F12* until the boot menu appears and select *USB HDD: Mass Storage Device* and wait for the installation image to boot. When prompted select *Arch Linux archiso X86_64 UEFI CD* where you will be take to the live environment's terminal.
## Set the keyboard layout
The default console map is US which meant that for me pressing *Shift+3* was displaying the hash symbol (#) instead of the pound symbol (£). So the UK keyboard layout needed to be loaded.
```shell
$ loadkeys uk
```
You can get a list of supported keyboard layouts if you need to load a different one.
```shell
ls /usr/share/kbd/keymaps/**/*.map.gz
```
## Verify the boot mode
To verify that the Thinkpad has UEFI enabled check that the *efivars* directory exists.
```shell
$ ls /sys/firmware/efi/efivars
```
## Connect to the internet
Verify that the machine can connect to the internet with the *ping* command.
```shell
$ ping -c3 davidtsadler.com
```
Before booting the machine I plugged in an Ethernet cable that was connected directly to my home network's router. The installation environment detected the network connection and obtained an IP address via DHCP.
## Update the system clock
Ensure the system clock is correct.
```shell
$ timedatectl set-ntp true
```
## Partition the disks
Use the *lsblk* command to determine which disks and partitions exist on the system.
```shell
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 535M 1 loop /run/archiso/sfs/airootfs
sda 8:0 0 298.1G 0 disk
sdb 8:16 1 7.4G 0 disk
├─sdb1 8:17 1 652M 0 part /run/archiso/bootmnt
└─sdb2 8:18 1 64M 0 part
```
From the above output I could see that my hard drive was *sda* as *sdb* was the USB drive and *loop0* could just be ignored.
I knew that I wanted to have an encrypted partition and make use of LVM on it so my disk layout would be.
```
+-------------------+ +--------------------------------------------------------+
| Boot partition | | Logical volume 1 | Logical volume 2 | Logical volume 3 |
| | | | | |
| /boot | | / | [SWAP] | /home |
| | | | | |
| | | 50G | 16G | 200G |
| | | | | |
| | | /dev/vg0/root | /dev/vg0/swap | /dev/vg0/home |
| | |_ _ _ _ _ _ _ _ _ |_ _ _ _ _ _ _ _ _ |_ _ _ _ _ _ _ _ _ |
| | | |
| | | LUKS2 encrypted partition |
| /dev/sda1 (512MB) | | /dev/sda2 |
+-------------------+ +--------------------------------------------------------+
```
The hard drive would be split into two partitions. The first, *sdb1* would be 512MB in size and mounted in the file system at */boot*. This would be the EFI system partition. The reminder of the disk space would be given to the partition *sda2* and encrypted using LUKS2. LVM would then be used to create the volume group *vg0* that would be divided into three partitions as logical volumes.
- */dev/vg0/root* 50G root partition.
- */dev/vg0/swap* 16G swap partition.
- */dev/vg0/home* 200G home partition.
Use *fdisk* to create the partitions.
```shell
$ fdisk /dev/sda
```
Enter **g** to create a new empty GPT partition table
```shell
Command (m for help): g
Created a new GPT disklabel (GUID: 6987D065-936E-1547-9F02-F78145025A96).
```
Since this is a UEFI system there must be a EFI partition at the beginning of the disk. Enter **n** to add a new partition and enter **1** to assign it as the first partition. Use the default value for the first sector but enter **+512M** for the last sector.
```shell
Command (m for help): n
Partition number (1-128, default 1): 1
First sector (2048-625142414, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-625142414, default 625142414): +512M
Created a new partition 1 of type 'Linux filesystem' and of size 512 MiB.
```
Enter **t** to change the partition type and enter **1** to make it an EFI System. You can also get a list of partition types by pressing **L**.
```shell
Command (m for help): t
Selected partition 1
Partition type (type L to list all types): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.
```
To create the second partition enter **n** again to add another partition, and then enter **2** to assign it as the second partition. Use the default values for both first and last sectors to allocate the remainder of the drive.
```shell
Command (m for help): n
Partition number (2-128, default 2): 2
First sector (1050624-625142414, default 1050624):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1050624-625142414, default 625142414):
Created a new partition 2 of type 'Linux filesystem' and of size 297.6 GiB.
```
Enter **w** to write the changes and quit.
```shell
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
```
Use *lsblk* to confirm that two partitions have been created.
```shell
$ lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 298.1G 0 disk
├─sda1 8:1 0 512M 0 part
└─sda2 8:2 0 297.6G 0 part
```
## LUKS
Encrypt the second partition with the *cryptsetup* command.
```shell
$ cryptsetup luksFormat /dev/sda2
```
When prompted enter **YES** in capitals to overwrite any data that is currently on the partition.
```shell
WARNING!
========
This will overwrite data on /dev/sda2 irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
```
Enter and verify a passphrase. Whenever the machine is now booted you will be prompted to enter this passphrase in order for the partition to be decrypted.
```shell
Enter passphrase for /dev/sda2:
Verify passphrase:
cryptsetup luksFormat /dev/sda2 17.01s user 1.05s system 105% cpu 17.106 total
```
## LVM on LUKS
Before setting up LVM decrypt the partition.
```shell
$ cryptsetup open /dev/sda2 cryptlvm
```
You will be prompted to enter the passphrase that you set up earlier.
```shell
Enter passphrase for /dev/sda2:
cryptsetup open /dev/sda2 cryptlvm 6.48s user 0.36s system 92% cpu 7.436 total
```
Create a physical volume.
```shell
$ pvcreate /dev/mapper/cryptlvm
```
Create a volume group called *vg0*.
```shell
$ vgcreate vg0 /dev/mapper/cryptlvm
```
Create three logical volumes for the root, swap and home partitions.
```shell
$ lvcreate -L 50G vg0 -n root
$ lvcreate -L 16G vg0 -n swap
$ lvcreate -L 200G vg0 -n home
```
Make use of *lsblk* again to verify that LVM has been setup as expected.
```shell
$ lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 298.1G 0 disk
├─sda1 8:1 0 512M 0 part
└─sda2 8:2 0 297.6G 0 part
└─cryptlvm 254:0 0 297.6G 0 crypt
├─vg0-root 254:1 0 50G 0 lvm
├─vg0-swap 254:2 0 16G 0 lvm
└─vg0-home 254:3 0 200G 0 lvm
```
## Format the partitions
Format the boot partition at */dev/sda1* with a FAT32 file system as the UEFI specification requires the usage of it.
```shell
$ mkfs.fat -F32 /dev/sda1
```
The root and home partitions can be formatted with ext4.
```shell
$ mkfs.ext4 /dev/vg0/root
$ mkfs.ext4 /dev/vg0/home
```
Initialise the swap partition.
```shell
$ mkswap /dev/vg0/swap
$ swapon /dev/vg0/swap
```
## Mount the file systems
Mount the root partition into */mnt*.
```shell
$ mount /dev/vg0/root /mnt
```
Mount the boot partition into */mnt/boot*.
```shell
$ mkdir /mnt/boot
$ mount /dev/sda1 /mnt/boot
```
Finally mount the home partition into */mnt/home*.
```shell
$ mkdir /mnt/home
$ mount /dev/vg0/home /mnt/home
```
## Select the mirrors
All mirror servers defined in */etc/pacman.d/mirrorlist* where done at the time the installation image was built. Since it's ideal to try and use servers that are close to your location you can rebuild the list using the *rankmirrors* utility. This is not included by default on the live environment so you will need to download it.
First sync the pacman repository.
```shell
pacman -Syy
```
Then download the *pacmain-contrib* package which contains the *rankmirrors* utility.
```shell
$ pacman -S pacman-contrib
```
The official [Pacman Mirrorlist Generator](https://www.archlinux.org/mirrorlist/) can be used to get an up-to-date list of servers for your country. The below command obtains a list of UK servers that support https and pass it to *rankmirrors* to obtain the 5 fastest.
```shell
$ curl -s "https://www.archlinux.org/mirrorlist/?country=GB&protocol=https&use_mirror_status=on" | sed -e 's/^#Server/Server/' -e '/^#/d' | rankmirrors -n 5 - > /etc/pacman.d/mirrorlist
```
## Install essential packages
The *pacstrap* script is used to install the base package, Linux kernel and firmware.
```shell
$ pacstrap /mnt base linux linux-firmware vim wpa_supplicant dhcpcd cryptsetup lvm2 efibootmgr intel-ucode
```
I also installed a few other packages that I knew I was going to need.
- *vim*. Allows you to edit files instead of using *nano*.
- *wpa_supplicant*. Provides tools for connecting to a WPA2 protected wireless network.
- *dhcpcd*. Needed so that you machine can obtain an IP address from your home router via dhcp.
- *cryptsetup*. Since the partition is encrypted this package is required in order for it to be decrypted during booting.
- *lvm2*. Provides the LVM tools to manage the LVM partition.
- *efibootmgr*. Needed to configure the system to boot via UEFI.
- *intel-ucode*. Enables microcode updates during boot.
## Fstab
Create a *fstab* file on the new system.
```shell
$ genfstab -U /mnt >> /mnt/etc/fstab
```
## Chroot
Use *arch-chroot* to enter the new system as the root user. From now on you will be configuring the new system.
```shell
$ arch-chroot /mnt
```
## Time zone
Setup the timezone. Replace *Europe/London* with your timezone.
```shell
$ ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime
```
Update the hardware clock.
```shell
$ hwclock --systohc
```
## Localization
Use *vim* to edit */etc/locale.gen*.
```shell
$ vim /etc/locale.gen
```
Uncomment your preferred language. For me this meant *en_GB.UTF-8 UTF-8*. Save the file and exit before generating the locales.
```shell
$ locale-gen
```
Edit */etc/locale.conf*.
```shell
$ vim /etc/locale.conf
```
Add the below line. Replace *en_GB.UTF-8* with the language that you chose earlier.
```
LANG=en_GB.UTF-8
```
If you used *loadkeys* earlier you will need to edit */etc/vconsole.conf* and add your chosen keymap.
```shell
$ vim /etc/vconsole.conf
```
For me this meant adding the UK keymap.
```
KEYMAP=uk
```
## Network configuration
Create the file */etc/hostname* and add an entry to it. This hostname will be the name of the machine on your network. I tend to name by devices after characters from the book [Howl's Moving Castle](https://en.wikipedia.org/wiki/Howl%27s_Moving_Castle).
```shell
$ echo suliman > /etc/hostname
```
You then need to edit the */etc/hosts* file.
```shell
$ vim /etc/hosts
```
Add the following lines to this file. Replace *suliman* with the hostname you set up earlier.
```shell
127.0.0.1 localhost
::1 localhost
127.0.0.1 suliman.localdomain suliman
```
## Wireless
Use the`ip` command to determine the name of the wireless network interface.
```shell
$ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether f0:de:f1:86:e1:75 brd ff:ff:ff:ff:ff:ff
3: wwp0s29u1u4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 86:06:37:c4:9b:41 brd ff:ff:ff:ff:ff:ff
4: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 08:11:96:02:10:ac brd ff:ff:ff:ff:ff:ff
```
Looking at the output of the *ip* command this is *wlan0*. This name however will not be the name of the interface once the installation has been completed. You see the Arch installation environment does not use predictable names for interfaces. This is due to it using *iwd* which is unable to cope with interface renaming and so it is disabled for wireless interfaces. When the system boots into the installed system predictable names for interfaces will be enabled and *wlan0* will be assigned a different name.
In order to find out what name will be assigned use the *udevadm* command.
```shell
$ udevadm test-builtin net_id /sys/class/net/wlan0
Load module index
Parsed configuration file /usr/lib/systemd/network/99-default.link
Parsed configuration file /usr/lib/systemd/network/80-iwd.link
Created link configuration context.
Using default interface naming scheme 'v245'.
ID_NET_NAMING_SCHEME=v245
ID_NET_NAME_MAC=wlx0811960210ac
ID_OUI_FROM_DATABASE=Intel Corporate
ID_NET_NAME_PATH=wlp3s0
Unload module index
Unloaded link configuration context.
```
What we are interested in is the value of *ID_NET_NAME_PATH* which is *wlp3s0*.
My wireless network is a WPA2 protected network with a hidden SSID. Since *wpa_supplicant* has been installed when running *pacstrap* it is possible to use *wpa_passphrase* to generate the configuration file that *wpa_supplicant* will use to connect to the wireless network. Replace *<SSID>* and *<PASSWORD>* with your details. Note that the name of the configuration file contains the name of the network interface *wlp3s0*. Replace this with the name of your network interface.
```shell
$ wpa_passphrase <SSID> <PASSWORD> > /etc/wpa_supplicant/wpa_supplicant-wlp3s0.conf
```
If your wireless network uses a hidden SSID you will need to edit the configuration file.
```shell
$ vim /etc/wpa_supplicant/wpa_supplicant-wlp3s0.conf
```
And add the below line.
```shell
scan_ssid=1
```
Make sure that *wpa_supplicant* starts at boot.
```shell
$ systemctl enable wpa_supplicant@wlp3s0.service
```
Have an IP address assigned via DHCP during booting.
```shell
$ systemctl enable dhcpcd@wlp3s0.service
```
## Initramfs
You will need to rebuild the initial ramdisk and the current one is not aware that the filesystem will be encrypted. Before rebuilding it some configuration changes need to be made.
```shell
$ vim /etc/mkinitcpio.conf
```
Locate the section where the *HOOKS* are configured and replace it with the line below.
```
HOOKS=(base udev autodetect keyboard keymap modconf block encrypt lvm2 filesystems fsck)
```
This ensures that the keyboard is present before the filesystem is detected so that you are enter the passphrase to decrypt the partition. It also ensures that the decryption is done before the *LVM* is handled.
Save the changes and exist before rebuilding with the *mkinitcpio* command.
```shell
mkinitcpio -P
```
## EFISTUB Booting and Microcode
The Thinkpad X220 UEFI implementation allows an operating system to be booted without the need for an intermediate bootloader such as GRUB. It is possible to add a UEFI boot entry to the motherboard itself and have Arch booted directly.
Modifying the motherboard boot entries is done using *efibootmgr*. However usage of this command can be quite verbose so it is recommended to create a shell script instead.
```shell
vim /usr/local/sbin/mkefibootentry
```
The shell script will call *efibootmgr* with the required arguments.
```
#!/bin/sh
# Determine the UUID of the partition that is encrypted
PARTUUID=`blkid /dev/sda2 -s PARTUUID -o value`
efibootmgr \
--disk /dev/sda --part 1 \
--create --label "Arch Linux" \
--loader /vmlinuz-linux \
--unicode 'cryptdevice=PARTUUID='$PARTUUID':cryptlvm root=/dev/vg0/root rw initrd=\intel-ucode.img initrd=\initramfs-linux.img' \
--verbose
```
The *--unicode* argument is where the kernel parameters are specified. This tells the system that the partition identified by *PARTUUID* is encrypted and that the root filesystem to mount is the logical volume called *root* that is part of the volume group *vg0*. The microcode is also loaded with *initrd=\intel-ucode.img*.
Make this script executable.
```shell
chmod u+x /usr/local/sbin/mkefibootentry
```
Run the script to add to the motherboard boot entries.
```shell
$ mkefibootentry
```
## Root password
Create a secure password for the root user.
```shell
$ passwd
```
## Reboot
Return to the Arch live installation environment.
```shell
$ exit
```
Unmount the partitions.
```shell
$ umount -R /mnt
```
Restart the machine with *reboot*. Remember to remove any installation media such as a USB drive.
```shell
$ reboot
```
Provided nothing has gone wrong your machine will boot into a fresh installation of Arch Linux. Don't forget that during the boot you will be prompted to enter the passphrase to decrypt the system partition.
Following this guide will leave you with a very minimal system where you can login as the root user. From this point how you configure the system is up to you as it will be very different to how I configure my own. If you interested in seeing how I do it then see my other posts on the subject.
|