📜 ⬆️ ⬇️

Installing Archlinux with full system and LVM encryption on LUKS

In this post you will read a little about my strange research during forced sick leave. We will talk about several things at once that are not “best practice”, but also possible! So, there will be a tutorial on how to install Archlinux (my favorite distr) so that:


It is noteworthy that everything will be encrypted except for the EFI system partition with a single grubx64.efi file - an EFI application for running grub.

If you are interested, welcome under the cat!

At first, I configured this all on my Lenovo X240 laptop, then I already used a virtual machine with OVMF in Proxmox to write the article.
')

Test bench setup:


Everything is created fairly standard. The image uses my favorite arch, which can always be downloaded from Yandex .

Then a few moments on virtualke in Proxmox regarding UEFI. To test the booth with UEFI (otherwise it will not be so interesting), you need to set OVMF instead of SeaBIOS in the properties of the virtual machine:



Further, respectively, add a UEFI-disk to get something like this:



Now we can start the virtual machine and start the installation process. In the console of the virtual machine, we immediately start the sshd service, set the root password and find out the dhcp-address of the virtual machine:



Further we can continue work on ssh that was more convenient.

Disk layout


So, having already connected via ssh, we first set the time so that later it would not turn out that file systems were created in the future:

timedatectl set-ntp true && timedatectl set-timezone Europe/Moscow 

We check that everything is correct:

 root@archiso ~ # timedatectl Local time: Tue 2018-08-14 13:42:03 MSK Universal time: Tue 2018-08-14 10:42:03 UTC RTC time: Tue 2018-08-14 10:42:04 Time zone: Europe/Moscow (MSK, +0300) System clock synchronized: yes NTP service: active RTC in local TZ: no 

Now we can proceed to the layout of the disk. At this stage, I have a disk / dev / vda, because Virtio controller and it's just an empty disk without a partition table:

 root@archiso ~ # fdisk -l /dev/vda Disk /dev/vda: 15 GiB, 16106127360 bytes, 31457280 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes 

We will break it into 2 partitions:


Use gdisk to create a gpt:

 root@archiso ~ # gdisk /dev/vda GPT fdisk (gdisk) version 1.0.4 Command (? for help): o This option deletes all partitions and creates a new protective MBR. Proceed? (Y/N): y 

Next, create the first partition for EFI with type EF00 (EFI System Partition):

 Command (? for help): n Partition number (1-128, default 1): First sector (34-31457246, default = 2048) or {+-}size{KMGTP}: Last sector (2048-31457246, default = 31457246) or {+-}size{KMGTP}: +512M Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): <b>EF00</b> Changed type of partition to 'EFI System' 

Now we create a partition for LUKS, where we will not even bother with the type and leave it as it is:

 Command (? for help): n Partition number (2-128, default 2): First sector (34-31457246, default = 1050624) or {+-}size{KMGTP}: Last sector (1050624-31457246, default = 31457246) or {+-}size{KMGTP}: <b>Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to 'Linux filesystem'</b> 

Let's write the changes and finish with partitioning:

 Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to /dev/vda. The operation has completed successfully. 

Creating a LUKS container and file systems


With the first section (vda1) everything is quite simple. We just need to format it and for now it's all:

 root@archiso ~ # mkfs.vfat /dev/vda1 mkfs.fat 4.1 (2017-01-24) 

The second partition is the container that you first need to prepare. Format the partition using cryptsetup and set the passphrase:

 root@archiso ~ # cryptsetup -v luksFormat /dev/vda2 WARNING! ======== This will overwrite data on /dev/vda2 irrevocably. Are you sure? (Type uppercase yes): YES Enter passphrase for /dev/vda2: Verify passphrase: Command successful. 

*** I did not bother with the choice of ciphers, with a random mashing with uranium and other things, but simply created a default container.

Next, open the container by pointing to the same passphrase:

 root@archiso ~ # cryptsetup luksOpen /dev/vda2 container Enter passphrase for /dev/vda2: 

Now we have an open container accessible through device mapper:

 root@archiso ~ # ls -l /dev/mapper | grep container lrwxrwxrwx 1 root root 7 Aug 14 14:01 container -> ../dm-0 

Now we can continue with lvm (I will write in a quick way, since this is not a subject):

 root@archiso ~ # pvcreate /dev/mapper/container Physical volume "/dev/mapper/container" successfully created. root@archiso ~ # vgcreate rootvg /dev/mapper/container Volume group "rootvg" successfully created root@archiso ~ # lvcreate -L1G -n swap rootvg Logical volume "swap" created. root@archiso ~ # lvcreate -L5G -n root rootvg Logical volume "root" created. root@archiso ~ # lvcreate -L2G -n home rootvg Logical volume "home" created. root@archiso ~ # lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert home rootvg -wi-a----- 2.00g root rootvg -wi-a----- 5.00g swap rootvg -wi-a----- 1.00g 

Next, create file systems on our lv:

 root@archiso ~ # mkfs.ext4 -L root /dev/mapper/rootvg-root mke2fs 1.44.3 (10-July-2018) ... Writing superblocks and filesystem accounting information: done [root@archiso ~]# mkfs.ext4 -L home /dev/mapper/rootvg-home mke2fs 1.44.3 (10-July-2018) Creating filesystem with 524288 4k blocks and 131072 inodes ... Writing superblocks and filesystem accounting information: done [root@archiso ~]# mkswap -L swap /dev/mapper/rootvg-swap ... LABEL=swap, UUID=98b0bc31-1c62-4fec-bb97-e1913d1e8cb4 

Now all this can be mounted to install the base system. The installation point will be / mnt, where the root of our future system will begin:

 [root@archiso ~]# mount /dev/mapper/rootvg-root /mnt/ [root@archiso ~]# mkdir -p /mnt/{home,boot/efi} 

*** I create / boot / efi so that / boot itself remains on / dev / mapper / rootvg-root, and the efi folder is already to mount / dev / vda1 (fat32 efi partition) into it:

 [root@archiso ~]# mount /dev/vda1 /mnt/boot/efi/ [root@archiso ~]# mount /dev/mapper/rootvg-home /mnt/home/ [root@archiso ~]# swapon /dev/mapper/rootvg-swap 

Check current mount points (always useful):

 [root@archiso ~]# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT loop0 7:0 0 462.5M 1 loop /run/archiso/sfs/airootfs sr0 11:0 1 573M 0 rom /run/archiso/bootmnt vda 254:0 0 15G 0 disk ├─vda1 254:1 0 512M 0 part /mnt/boot/efi └─vda2 254:2 0 14.5G 0 part └─container 253:0 0 14.5G 0 crypt ├─rootvg-swap 253:1 0 1G 0 lvm [SWAP] ├─rootvg-root 253:2 0 5G 0 lvm /mnt └─rootvg-home 253:3 0 2G 0 lvm /mnt/home 

As we see, everything is fair and now is the time to put the arch itself.

Base system installation


Install the base packages from the base and base-devel sets using the pacstrap package (they can put everything you want and besides this):

 pacstrap /mnt base base-devel 

Everything is perfectly loaded, the basic system is ready. I, naturally, removed a conclusion. Now we can configure this very system to load and work.

From the basic things we will immediately generate fstab:

 genfstab -pU /mnt >> /mnt/etc/fstab 

Next, we will make the arch-chroot in this new system:

 [root@archiso ~]# arch-chroot /mnt 

*** The arch-chroot is a very useful utility, because it does everything by itself. Although you can always use the standard chroot, before doing this, follow the instructions for the gentoo-handbook wiki.gentoo.org/wiki/Handbook : AMD64 / Installation / Base section "Mounting the necessary files files "

Let's set the system time and hostname right away:

 ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime && \ hwclock --systohc && \ echo luks-test > /etc/hostname 

Set the root password:

 [root@archiso /]# passwd root New password: Retype new password: passwd: password updated successfully 

Uncomment the necessary locales in /etc/locale.gen:

 [root@archiso /]# vi /etc/locale.gen [root@archiso /]# grep -v '^#' /etc/locale.gen en_US ISO-8859-1 en_US.UTF-8 UTF-8 ru_RU.UTF-8 UTF-8 ru_RU ISO-8859-5 

Generate them:

 [root@archiso /]# locale-gen Generating locales... en_US.ISO-8859-1... done en_US.UTF-8... done ru_RU.UTF-8... done ru_RU.ISO-8859-5... done Generation complete 

Immediately configure them for the system and the console:

 [root@archiso /]# echo LANG=en_US.UTF-8 > /etc/locale.conf [root@archiso /]# echo KEYMAP=ru > /etc/vconsole.conf [root@archiso /]# echo FOND=cyr-sun16 >> /etc/vconsole.conf 

Now we will configure the /etc/mkinitcpio.conf file, which is responsible for options, hooks, etc., when generating the initramfs:

 vi /etc/mkinitcpio.conf 

The most important thing here is the hooks and their order:

 HOOKS=(base udev autodetect modconf block keymap encrypt lvm2 resume filesystems keyboard fsck) 

*** resume hook for booting system after hibernation from swap. On virtualk it is not needed. I copied it from beech.

Now we can generate the initramfs:

 [root@archiso /]# mkinitcpio -p linux ==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'default' -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img ==> Starting build: 4.17.14-arch1-1-ARCH -> Running build hook: [base] -> Running build hook: [udev] -> Running build hook: [autodetect] -> Running build hook: [modconf] -> Running build hook: [block] -> Running build hook: [keymap] -> Running build hook: [encrypt] -> Running build hook: [lvm2] -> Running build hook: [resume] -> Running build hook: [filesystems] -> Running build hook: [keyboard] -> Running build hook: [fsck] ==> Generating module dependencies ==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img ==> Image generation successful 

Now that we have a system, we need to install the bootloader itself. I chose grub (2), because it is somehow more familiar and quite easy to load the kernel from an encrypted partition (well, or I didn’t particularly look for others).

Install the grub package:

 [root@archiso /]# pacman -S grub dosfstools efibootmgr mtools 

Before generating the config, edit the default grub options:

 vim /etc/default/grub 

here you need to uncomment one important line (without comment, of course):

 # Uncomment to enable booting from LUKS encrypted devices GRUB_ENABLE_CRYPTODISK=y 

and add (there is empty by default) in GRUB_CMDLINE_LINUX:

 GRUB_CMDLINE_LINUX="cryptdevice=UUID=5ad7c9ad-fb17-4839-925e-479432516c07:container" 

UUID I took from blkid:

 [root@archiso /]# blkid | grep vda2 /dev/vda2: UUID="5ad7c9ad-fb17-4839-925e-479432516c07" TYPE="crypto_LUKS" PARTLABEL="Linux filesystem" PARTUUID="667a1243-17ff-4f03-952c-5afd5e3415cc" 

We generate a config for grub:

 [root@archiso /]# grub-mkconfig -o /boot/grub/grub.cfg Generating grub configuration file ... WARNING: Failed to connect to lvmetad. Falling back to device scanning. Found linux image: /boot/vmlinuz-linux Found initrd image: /boot/initramfs-linux.img Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img WARNING: Failed to connect to lvmetad. Falling back to device scanning. done 

Next, install grub itself on the disk:

 [root@archiso /]# grub-install /dev/vda Installing for x86_64-efi platform. ... Installation finished. No error reported. 

*** you can add --recheck --debug, specify the architecture ... but ... because it works by itself)

Now edit / etc / crypttab so that the system itself knows that you need to decrypt the LUKS partition when booting. Add a line:

 echo "container /dev/vda2 none" >> /etc/crypttab 

Which means that you need to request a password (none) for the / dev / vda2 section and present it as container through device mapper.

Now we are ready to exit the chroot and reboot the system:

 [root@archiso /]# exit exit [root@archiso ~]# reboot Welcome back! 

Now let's turn to the virtual machine console to see the result:



At this stage, we run the EFI application /boot/efi/EFI/arch/grubx64.efi with / dev / vda1, which asks us for a password to decrypt our container.

Further, after entering the password:



Here is the usual grub window with our boot options from /boot/grub/grub.cfg.
At this stage, grub decrypted our container and accessed this file itself (/boot/grub/grub.cfg), the kernel, and initramfs. After selecting the default option, the kernel will boot, initramfs:



Actively, the kernel and business came to the encrypt hook, which again asks us the password for decrypting the container (generally entering the password 2 times, but it may be that you are going to make 2 containers for boot and root :)

And then after the system is fully booted:



PS: to increase the level of schizophrenia, the only thing missing is a secure boot to sign our grubx64.efi bootloader.

I just found the kernel and initramfs on / dev / vda1 to be uninteresting, since I did it 100 times. Other boot loaders such as SHIM, bootctl, etc. do not know how to do this (well, and I don’t know - tell in the comments)

Source: https://habr.com/ru/post/420081/


All Articles