6 minutes
Arch Linux With LVM on LUKS
I’ve been using Arch Linux for the past several years, but never quite got to documenting the exact steps I use for installation. Every time I do a reinstall, I have to spend some time re-learning what exactly I have to configure to have the system I want. This is my attempt to document the installation steps so that I can recall them whenever I need.
At the time of writing, there is the handy archinstall library, but I still prefer the old-school manual installation.
We’ll end up with a UEFI-booting system with LVM on LUKS. No GUI is installed in this guide, since I do that using one of my repos, depending on whether I run X or Wayland
First, download an image from https://archlinux.org/download/ and copy it to a USB drive, after having verified the file integrity.
$ cat archlinux-YYYY.MM.DD-x86_64.iso >/dev/sdX && sync
Network configuration
If you are connected over Ethernet using DHCP, the network connection should
get picked up automatically. For Wi-Fi, authenticate using iwctl
:
$ iwctl
[iwd]# device list
[iwd]# station <device-name> scan
[iwd]# station <device-name> get-networks
[iwd]# station <device-name> connect <ssid>
Disk partitioning
Check your drives with
$ fdisk -l
The rest of the guide assumes that Arch is installed to /dev/sda
. Run fdisk
on this device and start partitioning.
$ fdisk /dev/sda
First, create a 600M EFI partition:
n
(new partition)Enter
(accept the default partition type)Enter
(accept the default partition number)Enter
(accept the default first sector)+600M
(partition size)t
(partition type)Enter
(accept the default partition number)ef
(EFI)
Next, create a 1G boot partition:
n
Enter
Enter
Enter
+1G
t
Enter
83
(Linux)
Finally, create the LVM partition taking up the remaining space:
n
Enter
Enter
Enter
Enter
t
Enter
8e
(Linux LVM)
Check that everything is OK by typing p
. Write the changes by typing w
.
There are now three partitions:
/dev/sda1
for EFI. This will be formatted with FAT./dev/sda2
for/boot
. This will be formatted with EXT4./dev/sda3
for LVM on LUKS.
To create the file systems for the first two, enter
$ mkfs.fat -F32 /dev/sda1
$ mkfs.ext4 /dev/sda2
LVM on LUKS
Here we’ll setup disk encryption using LUKS followed by LVM with several partitions. By using LVM on LUKS, we can have multiple logical volumes all accessed using a single encryption key. The opposite would be LUKS on LVM, which would allow an encrypted volume to span more devices, with the volume group visible without decrypting the encrypted volumes.
Setup encryption on the third partition. This will prompt you for a passphrase.
$ cryptsetup luksFormat /dev/sda3
To be able to create the logical volumes and proceed with the installation, we need to open the encrypted partition. This will prompt you for the passphrase defined in the previous step.
$ cryptsetup open /dev/sda3 root
Here, root
is arbitrary and only describes where the unlocked partition
should be mapped. Once opened, it can be accessed in /dev/mapper/root
.
Initialize a physical volume for use by LVM:
$ pvcreate --dataalignment 1m /dev/mapper/root
Create a volume group in the physical volume we’ve just created:
$ vgcreate vg0 /dev/mapper/root
The name of the group (vg0
here) is arbitrary.
Finally, we can create the logical volumes.
- An 8G swap partition.
- A 50G file system root partition.
- A home partition taking up all the remaining space.
$ lvcreate -L 8G vg0 -n swap
$ lvcreate -L 50G vg0 -n root
$ lvcreate -l 100%FREE vg0 -n home
Each partition needs a file system; I use ext4
.
$ mkswap /dev/mapper/vg0-swap
$ mkfs.ext4 /dev/mapper/vg0-root
$ mkfs.ext4 /dev/mapper/vg0-home
The partitions now have to be mounted, along with the /boot
and EFI
partitions.
$ mount /dev/mapper/vg0-root /mnt
$ mkdir /mnt/boot
$ mount /dev/sda2 /mnt/boot
$ mkdir /mnt/boot/efi
$ mount /dev/sda1 /mnt/boot/efi
$ mkdir /mnt/home
$ mount /dev/mapper/vg0-home /mnt/home
$ swapon /dev/mapper/vg0-swap
$ mkdir /mnt/etc
Generate the fstab file.
$ genfstab -U /mnt >>/mnt/etc/fstab
Make /tmp
a RAM disk for increased speed and reduced SSD wear:
$ echo 'tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0' >>/mnt/etc/fstab
Arch installation
First, use pacstrap
to install the base
package, the Linux kernel and
firmware. When that’s done, chroot into the newly installed system.
$ pacstrap -i /mnt base base-devel linux linux-firmware
$ arch-chroot /mnt
At this point, we are working inside the newly installed system. Install some
additional packages. Based on your CPU manufacturer, select either amd-ucode
or intel-ucode
in place of <cpu-ucode>
.
$ pacman -S <cpu-ucode> sudo vim iwd lvm2 grub efibootmgr
Set a hostname of your choice:
$ echo '<hostname>' >/etc/hostname
Make sure the /etc/hosts
file contains the following lines:
127.0.0.1 localhost.localdomain localhost
::1 localhost.localdomain localhost
127.0.0.1 <hostname>.localdomain <hostname>
Define your locale by uncommenting it inside /etc/locale.gen
(in my case,
en_US.UTF-8 UTF-8
) and running
$ locale-gen
$ echo 'LANG=en_US.UTF-8' >/etc/locale.conf
The changes will take effect after the next login.
Setup system clock by running
$ ln -s /usr/share/zoneinfo/<timezone> /etc/localtime
$ hwclock --systohc --utc
Finally, we have to enable encryption in mkinitcpio
hooks. Make sure that the
line beginning with HOOKS=
inside /etc/mkinitcpio.conf
looks like this:
HOOKS=(base udev autodetect keyboard keymap consolefont modconf block lvm2 encrypt filesystems fsck)
and that the line beginning with MODULES=
contains ext4
in the parentheses.
After that, run
$ mkinitcpio -p linux
User management
Here we change the root password and create a user with superuser permissions.
$ passwd
$ useradd -m -G wheel <username>
$ passwd <username>
Next, make members of the wheel
group superusers.
$ EDITOR=vim visudo
and make sure that there is a line containing
%wheel ALL=(ALL:ALL) ALL
Bootloader configuration
We’ll refer to devices by UUIDs instead of bus names, because the device nodes may be added in arbitrary order if you have more disk controllers. Run
$ blkid
and look up the UUID corresponding to /dev/sda3
. Then, make sure that the
line starting with GRUB_CMDLINE_LINUX=
inside /etc/default/grub
looks like
this:
GRUB_CMDLINE_LINUX="cryptdevice=UUID=<uuid>:vg0:allow-discards root=/dev/mapper/vg0-root"
Install grub:
$ grub-install --target=x86_64-efi --bootloader-id=grub_uefi --recheck
Setup grub locale and generate the grub configuration file:
$ mkdir /boot/grub/locale
$ cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale/en.mo
$ grub-mkconfig -o /boot/grub/grub.cfg
Finishing up
Exit the system chroot, unmount all devices, reboot, and enjoy your new system.
$ exit
$ umount -R /mnt
$ swapoff -a
$ reboot
Network configuration
The full article comes from the amazing Insanity Industries, so I’ll just summarize to keep the configuration handy.
To configure wired networking, put the following inside
/etc/systemd/network/cable.network
:
[Match]
Name=<name of the wired network device> <second one if applicable> [<more ...>]
[Network]
DHCP=yes
IPv6PrivacyExtensions=true
[DHCP]
Anonymize=true
Afterwards, run
$ systemctl enable --now systemd-networkd.service
To configure wireless networking, put the following inside
/etc/iwd/main.conf
:
[General]
EnableNetworkConfiguration=true
AddressRandomization=once
[Network]
EnableIPv6=true
Next, configure iwd
to start only after udev
has finished renaming the
network interfaces. Run
$ systemctl edit iwd.service
and enter
[Unit]
Requires=sys-subsystem-net-devices-<wireless-device>.device
After=sys-subsystem-net-devices-<wireless-device>.device
Afterwards, run
$ systemctl enable --now iwd.service
To disable iwd
when WiFi is not present, put the following inside
/etc/udev/rules.d/wifi.rules`:
SUBSYSTEM=="rfkill", ENV{RFKILL_NAME}=="phy0", ENV{RFKILL_TYPE}=="wlan", ACTION=="change", ENV{RFKILL_STATE}=="1", RUN+="/usr/bin/systemctl --no-block start iwd.service"
SUBSYSTEM=="rfkill", ENV{RFKILL_NAME}=="phy0", ENV{RFKILL_TYPE}=="wlan", ACTION=="change", ENV{RFKILL_STATE}=="0", RUN+="/usr/bin/systemctl --no-block stop iwd.service"
Finally, to setup systemd-resolved
as the DNS client, run
$ systemctl enable --now systemd-resolved.service
$ ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
1172 Words
2023-02-27 20:02