Installing Arch Linux on a Thinkpad T420 with system encryption July 22, 2012
Posted by Rich in laptop, linux.Tags: arch, encryption, linux, lvm, T420
trackback
I completed a basic install of Arch Linux over the weekend on my new Thinkpad T420. As mentioned in my previous post, I converted to UEFI mode and partitioned the hard drive in GPT format. I wanted to install Arch Linux for UEFI/GPT while using full system encryption using LUKS. Since it took a few tries to get all of the steps right, I’m posting what I did here in tutorial form.
Note: be wary of copying-and-pasting my commands for your configuration, since my drive letters and such won’t necessarily be typical.
The 2011-08-19 Arch installation media is rather out-of-date, so I elected to choose a more recent testing ISO. Word on the mailing lists indicates that they’ll release an updated official installation ISO soonish, but I don’t have the patience to wait for that. So, I used the one here and downloaded this iso. For BIOS systems, it’s easy to copy the ISO to a USB flash drive for installation purposes by doing something like dd if=archlinux.iso of=/dev/sdb bs=4M. A UEFI system requires a bit more than this. So, as per this README, I performed the following steps to get my USB media bootable for UEFI:
- Install gptfdisk on my desktop to get access to GPT partitioning utilities
- Create a GPT setup on the USB drive: sudo gdisk /dev/sdc, then o to create a blank GPT, n to create a new partition. I used the default size (whole disk) and set the type to ef00, an EFI system partition. I checked that it looks right with p to print the partition table, then w to write and quit.
- Create a FAT32 filesystem: sudo mkfs.vfat -F 32 -n ARCH_201207 /dev/sdc1 Note: It’s important that the EFI FAT32 partition is named ARCH_201207 otherwise the installer fails to boot.
- Mount the new filesystem: sudo mount /dev/sdc1 /media/sdc1 or pmount /dev/sdc1 if you use pmount
- Extract the ISO to the filesystem: bsdtar -x --exclude=isolinux/ --exclude=arch/boot/syslinux/ -f ~/Downloads/archlinux-2012.07.21_04-00-02-netinstall-dual.iso -C /media/sdc1
- Extract the contents of the EFI boot image: mcopy -s -i /media/sdc1/EFI/archiso/efiboot.img ::/EFI /media/sdc1/
- Remove the unneeded boot image: rm /media/sdc1/EFI/archiso/efiboot.img
- Unmount the USB: umount /media/sdc1 or pumount /dev/sdc1
And now the USB installation media is ready and we’re ready to boot.
Once booted into the Arch installation environment, the first thing to do is set up dm-crypt with LUKS. I’m using this page as my reference for this step. This is what I did:
-
Create the boot partition: I used cgdisk /dev/sda to create a new partition. The boot partition doesn’t have to be big, so I opted for a 128 MiB partition with GPT partition type 8300, a Linux filesystem partition. GPT lets you use fancy partition names, so I opted for Arch boot partition. With the three previous partitions for Windows 7, this means that /dev/sda4 is my boot partition.
-
Create the LUKS partition in the remaining free space of the disk: Still in cgdisk /dev/sda, I created a partition to fill the rest of the disk. I couldn’t find anything online to indicate what partition type/GUID to set, so I used 8e00, Linux LVM. I named the partition Arch Linux LUKS partition. This partition is now /dev/sda5.
-
Securely erase the LUKS partition by filling it with random data: badblocks -c 10240 -wvst random /dev/sda5. This took a couple hours, but is much faster than using /dev/random or /dev/urandom as an input to dd.
-
Setup dm-crypt/LUKS: It’s possible to use a keyfile and/or a passphrase. I opted for the passphrase only and the cipher suggested by the wiki page I’m following. The command is cryptsetup -c aes-xts-plain -y -s 512 luksFormat /dev/sda5
-
Unlock the LUKS partition so we can install Arch on it: cryptsetup luksOpen /dev/sda5 arch-luks. Now the unlocked LUKS partition is accessed using device-mapper, /dev/mapper/arch-luks
-
Now to create the LVM partitions. With a 238 GiB volume group, I opted for the following:
- 15 GiB for the root partition
- 8 GiB for the var partition
- 4 GiB for the swap partition (I have 8 GiB RAM, so will probably never need swap, but I want hibernation support. Apparently the RAM is compressed before saving in the swap partition upon hibernation, so 40% of RAM should be sufficient). If I need to adjust, I can do so later.)
- 200 GiB for the home partition
- This leaves 11 GiB un-allocated. If/when I need it in the future to extend any of the three above partitions, then I can do so with some LVM and ext4 resizing magic.
Here are the steps to create the LVM partitions:
- Initialize the LUKS partition to be an LVM physical volume: pvcreate /dev/mapper/arch-luks, check with pvdisplay
- Add this LVM physical volume to a volume group: vgcreate amonkira_lvm /dev/mapper/arch-luks, check with vgdisplay. I named the volume group amonkira_lvm, which is used later on.
- Create the logical volumes from the volume group: lvcreate -L 15G amonkira_lvm -n root, lvcreate -L 8G amonkira_lvm -n var, lvcreate -C y -L 4G amonkira_lvm -n swap, lvcreate -L 200G amonkira_lvm -n home. The LVM physical extents making up the swap partition are forced to be contiguous with -C y, whereas we aren’t so picky about the other volumes. We can check the logical volumes with lvdisplay. The logical volumes are accessed in /dev/mapper/<volume_group_name>-<volume_name> or /dev/<volume_group_name>/<volume_name>.
-
Now we’re ready to format the partitions. I used ext4 for the non-boot partitions and added optional filesystem labels. I now have GPT partition names, LVM logical volume names, and filesystem labels.
- Boot partition: This is not on LVM, so it’s mkfs.ext2 -L arch-boot /dev/sda4
- / partition: mkfs.ext4 -L arch-root /dev/amonkira_lvm/root
- /home partition: mkfs.ext4 -L arch-home /dev/amonkira_lvm/home
- /var partition: mkfs.ext4 -L arch-var /dev/amonkira_lvm/var
- Swap partition: mkswap -L arch-swap /dev/amonkira_lvm/swap
I reduce or eliminate the number of reserved blocks for the filesystems (it’s 5% by default):
- tune2fs -m 1.0 /dev/amonkira_lvm/root
- tune2fs -m 1.0 /dev/amonkira_lvm/var
- tune2fs -m 0.0 /dev/amonkira_lvm/home
-
Now we have all of our partitions ready and can continue with the installation. Mount the partitions under /mnt for arch-install-scripts (these aren’t all strictly needed for installation, but it will make generating /etc/fstab easier later on):
- mount /dev/amonkira_lvm/root /mnt
- mkdir /mnt/var && mount /dev/amonkira_lvm/var /mnt/var
- mkdir /mnt/home && mount /dev/amonkira_lvm/home /mnt/home
- mkdir /mnt/boot && mount /dev/sda4 /mnt/boot
- swapon /dev/amonkira_lvm/swap
-
Since this is a netinstall, I need to be connected to the Internet. I’ll bring up the wireless interface and connect to a WPA2 network using wpa_supplicant:
- My wireless drivers were working out-of-the-box, as confirmed with iwconfig
- Bring up the interface with ip link set wlan0 up
- Save old wpa_supplicant config: mv /etc/wpa_supplicant.conf /etc/wpa_supplicant.conf.original
- Add network name/password to new config: wpa_passphrase linksys "my_secret_passkey" > /etc/wpa_supplicant.conf
- Load wpa_supplicant to associate with the network: wpa_supplicant -B -Dwext -i wlan0 -c /etc/wpa_supplicant.conf
- Request an IP address: dhcpcd wlan0
- Test connection: ping -c 3 http://www.google.com
-
Install the base system: pacstrap /mnt base base-devel
-
Install the boot loader: I’m going to install GRUB2, even though I could use the EFISTUB method to bypass GRUB entirely. Maybe I’ll switch to EFISTUB booting another day.
- Mount the UEFI system partition: mkdir /mnt/boot/efi && mount -t vfat /dev/sda1 /mnt/boot/efi
- Install GRUB: pacstrap /mnt grub-efi-x86_64
-
Configure the system
- Generate the /etc/fstab: genfstab -p /mnt >> /mnt/etc/fstab. I found I had to edit it since /dev/mapper/amonkira_lvm-swap didn’t show up.
- Secure /etc/fstab: I changed the following mount options to my devices for /mnt/etc/fstab:
- <device> /boot ext2 defaults,nodev,nosuid,noexec,noatime 0 2
- <device> / ext4 defaults,noatime 0 1
- <device> /var ext4 defaults,nodev,nosuid,relatime 0 2
- <device> /home ext4 defaults,nodev,nosuid,relatime 0 2
- chroot into the new system: arch-chroot /mnt
- Set up /etc/rc.conf and set USELVM to YES
- Set up /etc/locale.gen, then run locale-gen to generate locales
- Configure /etc/mkinitcpio.conf, add “encrypt” and “lvm2” to hooks (in that order) before “filesystem” entry, add “ext4” to MODULES; run mkinitcpio -p linux
- Configure GRUB
- Install GRUB UEFI application to the UEFI system partition and the GRUB modules to the boot partition:
- Outside the chroot (in another TTY, for example), run modprobe efivars
- grub-install --directory=/usr/lib/grub/x86_64-efi --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=arch_grub --boot-directory=/boot --recheck --debug
- mkdir -p /boot/grub/locale
- cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale/en.mo
- Add some command-line kernel arguments in /etc/default/grub: for GRUB_CMDLINE_LINUX, add root=/dev/mapper/amonkira_lvm-root for LVM and cryptdevice=/dev/sda5:arch-luks for LUKS and resume=/dev/mapper/amonkira_lvm-swap for hibernation
- I decided to add Windows 7 to the Grub menu. I followed this and added it to /etc/grub.d/40_custom.
- Create the GRUB config file: grub-mkconfig -o /boot/grub/grub.cfg
- Install GRUB UEFI application to the UEFI system partition and the GRUB modules to the boot partition:
- Set root password: passwd
-
Clean up
- exit out of the chrooted filesystem
- umount /mnt/{boot/efi,boot,var,home} && umount /mnt
-
Reboot and hopefully everything works! It did for me. 🙂
Now a basic and minimal Arch installation is done. Next post will be the post-installation configuration steps.
Thank you very much. This has saved me a lot of reading, after they changed the installer script.
You’re welcome. It’s funny, like the day after I made this post, they released a new official ISO, so the stuff about using a testing release could be replaced with using the official release.
Thanks for the write up! Just wondering where sda1 came from in this line: “Mount the UEFI system partition: mkdir /mnt/boot/efi && mount -t vfat /dev/sda1 /mnt/boot/efi”?
This was previously created when I installed Windows 7 (see my previous post). For UEFI/GPT on a blank disk, Windows 7 creates three partitions:
* /dev/sda1 is the EFI boot partition. It’s FAT32 and 100 MiB big
* /dev/sda2 is some Microsoft system parition. 128 MiB big
* /dev/sda3 is the main Windows 7 parititon. NTFS and 60 GiB large in my case.
We need this partition mounted because grub installs some stuff there. Hope that helps!
Thanks! About 5 minutes after I posted that I realized you had mentioned you had Windows installed first. So, I ended up creating the boot partition (since I don’t have Windows installed). Odd thing is everything seems to work, however now I I end up hanging at “Loading initial ramdisk” as someone else has blogged about. I have a T430 and am wondering if maybe I should try installing Windows on part of the disk first… Going to see if there’s EFI updates as well, but it *almost* works for me.
I’m not sure what the problem is, but I kinda doubt installing Windows would help. Have you asked on the forums or on the archlinux subreddit?
[…] is a follow-on post to last time where I did a basic install of Arch linux on my Thinkpad […]