Install Arch Linux on UEFI/GPT computer with BTRFS support

Introduction

The goal of this article is to explain the installation of Linux distribution with some specificities:

  • The Linux distribution is an Arch Linux

  • The computer is UEFI compatible

  • The disk is a SSD

  • BTRFS will be the file system used

  • Use the BTRFS capabilities to split the /, /opt, /home and /var

  • The network is a wireless connection, configured with netctl

Run the Arch Linux installer

First of all, you need to download the ISO (around 550Mb) from the Arch Linux site (magnet or torrent) and copy it on a USB key or burn it on a CD. To make a copy on a USB key, you can use the dd tool.

$ dd if=archlinux-2013.10.01-dual.iso of=/dev/sdb

considering /dev/sdb is the device’s file for the USB key.

On Mac OS X, you will not have /dev/sdb but something like /dev/rdisk2.

You can now run your Arch Linux on the computer you want to install.

Initializations

First of all, you may want to change the keyboard layouts and the locales. For the keyboard layout, use the loadkeys tool.

$ loadkeys fr-pc

For the locales, edit the /etc/locale.gen file and uncomment the locale your want (you can uncomment more than one). Then generate the new locales and export your new default locale.

$ locale-gen
$ echo LANG=fr_FR.UTF-8 > /etc/locale.conf
$ export LANG=fr_FR.UTF-8

You may change the terminal’s font with the following.

$ setfont Lat2-Terminus16

Partitionning

Our installation will consider that the computer is UEFI compatible. UEFI is compatible with both MBR and GPT partitionning. However, GPT is the standard way to do it. In order to partition the disk, we will use the GPT version of fdisk, which is gdisk, on the main disk /dev/sda.

$ gdisk /dev/sda

gdisk brings you to a new shell. We will create 2 partitions:

  • The first partition will be the EFI partition

  • The second partition will be the partition for the Linux system

These are the operations you should do:

  1. type o and validate to create the GPT partitionning

  2. type n and validate to create a new partition

  3. enter the partition number or just validate for the default (the default should be good)

  4. enter the first sector or just validate for the default (the default should be good)

  5. enter the last sector or the size of your volume; for EFI, enter +512M and validate

  6. enter the type of the partition; for EFI, enter EF00 and validate

  7. type n and validate to create a new partition

  8. enter the partition number or just validate for the default (the default should be good)

  9. enter the first sector or just validate for the default (the default should be good)

  10. enter the last sector or the size of your volume; for Linux system, validate the default which is the last sector of the disk

  11. enter the type of the partition; for Linux system, enter 8300 and validate

  12. type w and validate to write all the modifications on the disk.

Formatting

The formatting is pretty easy. The EFI partition should be format in a FAT filesystem (16 or 32). The second partition will be format in BTRFS since it one of the purpose of this article.

$ mkfs.vfat -F32 -n "EFI" /dev/sda1
$ mkfs.btrfs -L "Arch Linux" /dev/sda2

Managing the BTRFS subvolumes

Mounting the main BTRFS volume

First of all, we will mount the BTRFS partition.

$ mkdir -p /mnt/btrfs-root
$ mount -o defaults,relatime,ssd,discard,space_cache /dev/sda2 /mnt/btrfs-root

discard and ssd mount options are optimizations for SSD drives. discard is to activate `Discard/TRIM'' optimizations and `ssd is for specific BTRFS optimization on SSD drives.

Creating and mounting the BTRFS subvolumes

Then we can create the subvolumes in the BTRFS partition.

$ mkdir -p /mnt/btrfs-root/__snapshot
$ mkdir -p /mnt/btrfs-root/__active
$ btrfs subvolume create /mnt/btrfs-root/__active/ROOT
$ btrfs subvolume create /mnt/btrfs-root/__active/home
$ btrfs subvolume create /mnt/btrfs-root/__active/opt
$ btrfs subvolume create /mnt/btrfs-root/__active/var

We can now mount the subvolumes in the right order.

$ mkdir -p /mnt/btrfs-active
$ mount -o \
	defaults,nodev,relatime,ssd,discard,space_cache,subvol=__active/ROOT \
	/dev/sda2 /mnt/btrfs-active

We create the directories in this new-mounted subvolume and mount the other subvolumes.

$ mkdir -p /mnt/btrfs-active/home
$ mkdir -p /mnt/btrfs-active/opt
$ mkdir -p /mnt/btrfs-active/var/lib
$ mount -o \
	defaults,nosuid,nodev,relatime,ssd,discard,subvol=__active/home \
	/dev/sda2 /mnt/btrfs-active/home
$ mount -o \
	defaults,nosuid,nodev,relatime,ssd,discard,subvol=__active/opt \
	/dev/sda2 /mnt/btrfs-active/opt
$ mount -o \
	defaults,nosuid,nodev,noexec,relatime,ssd,discard,subvol=__active/var \
	/dev/sda2 /mnt/btrfs-active/var

Tricky part for the /var/lib directory

However, the /var/lib is the directory in which some interesting files are installed and we want to keep them in the __active/ROOT subvolume to make easier the snapshot procedure. Remember, we create a directory in this subvolume. So we will bind it.

$ mkdir -p /mnt/btrfs-active/var/lib
$ mount --bind /mnt/btrfs-root/__active/ROOT/var/lib \
	/mnt/btrfs-active/var/lib

Mount the EFI partition into the main directory layout

At this point, we should mount the EFI partition as the /boot directory.

$ mkdir -p /mnt/btrfs-active/boot
$ mount -o \
	defaults,nosuid,nodev,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro,discard \
	/dev/sda1 /mnt/btrfs-active/boot

Install the base system

Before being able to install the base system, you need to configure a network connection. If you want a wireless connection, you can simply use wifi-menu. It will display you a menu where you can choose a wireless network and enter your password (in clear).

You may update the list of mirrors /etc/pacman.d/mirrorlist before running the following command.

The base package will install a base system for your Arch Linux. Because we use a BTRFS system, we also install btrfs-progs package (we could install it later too).

$ pacstrap /mnt/btrfs-active base btrfs-progs

We must now generate and configure the fstab file with the help of genfstab.

$ genfstab -U -p /mnt/btrfs-active >> /mnt/btrfs-active/etc/fstab

You should modify the /etc/fstab file and make it looks like something like the following.

tmpfs					/tmp		tmpfs	rw,nodev,nosuid 0 0
tmpfs					/dev/shm	tmpfs	rw,nodev,nosuid,noexec 0 0

# /dev/sda1 LABEL=Arch\x20Linux
UUID=...				/		btrfs	rw,nodev,relatime,ssd,discard,space_cache,subvol=__active/ROOT 0 0
UUID=...				/home		btrfs	rw,nodev,nosuid,relatime,ssd,discard,space_cache,subvol=__active/home 0 0
UUID=...				/opt		btrfs	rw,nodev,nosuid,relatime,ssd,discard,space_cache,subvol=__active/opt 0 0
UUID=...				/var		btrfs	rw,nodev,nosuid,noexec,relatime,ssd,discard,space_cache,subvol=__active/var 0 0
UUID=...				/run/btrfs-root	btrfs	rw,nodev,nosuid,noexec,relatime,ssd,discard,space_cache 0 0
/run/btrfs-root/__active/ROOT/var/lib	/var/lib	none	bind 0 0

# /dev/sdb1 LABEL=EFI
UUID=...	/boot	vfat rw,nosuid,nodev,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro,discard 0 2

Be careful about the configuration of /var/lib. In fact, we need to mount the main BTRFS partition in order to access the directory that should be binded. Moreover, do not forget to check the line about the /boot partition.

We also need to create the directory where the root BTRFS partition will mount (see in the fstab).

$ mkdir -p /mnt/btrfs-active/run/btrfs-root

Configure the base system

You will now root from the newly installed base system with a arch-chroot. The configuration begins with mainly the same operations that we have done before.

$ echo "KEYMAP=fr-pc" > /etc/vconsole.conf
$ echo "FONT=Lat2-Terminus16" >> /etc/vconsole.conf
$ echo "fr_FR.UTF-8 UTF-8" > /etc/locale.gen
$ locale-gen
$ echo "LANG=fr_FR.UTF-8" > /etc/locale.conf
$ export LANG=fr_FR.UTF-8
$ ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime
$ hwclock --systohc --utc
$ echo "mypc" > /etc/hostname
$ passwd

Configure a wireless network connection

We will configure a default profile for a wireless connection with SSID mySSID and a WPA security. Then we will make this connection automatic with wpa_actiond. Begin to install wpa_actiond with the base package netctl. The dialog package allow us the use of wifi-menu to generate netctl profiles.

$ pacman -S netctl iw dialog wpa_actiond

Then create a netctl profile from an example file. You can either automatically generate a profile file with wifi-menu or use the manual configuration below.

$ cp /etc/netctl/examples/wireless-wpa-config /etc/netctl/profile

You should modify /etc/netctl/profile to make it look like the following.

Description='A wpa_supplicant configuration file based wireless connection'
Interface=wlp3s0
Connection=wireless
Security=wpa-config
WPAConfigFile='/etc/wpa_supplicant/wpa_supplicant.conf'
IP=dhcp

Do not forget to change the path to the wpa_supplicant.conf file which should be /etc/wpa_supplicant/wpa_supplicant.conf.

Now, we can configure the WPA configuration of our mySSID wifi network. To configure this network, we use wpa_passphrase. We first backup the default configuration file.

$ cp /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf.example
$ wpa_passphrase "mySSID" "mypassword" > /etc/wpa_supplicant/wpa_supplicant.conf

Do not forget the double quotes, especially if the SSID contains spaces. You may edit the file and remove the password which appear in clear.

You can now enable this service.

$ systemctl enable netctl-auto@wlp3s0.service

Configure the initial ramdisk environment

To generate the initial ramdisk, because you run with BTRFS partitions, you should modify some hooks in the /etc/mkinitcpio.conf. We will add a hook for btrfs. For this new hook, we must install the package btrfs-progs.

Secondly, BTRFS does not have a robust check file system so if we have the fsck hook, it will display an error. We have 2 solutions:

  • We erase the fsck hook and there will not have file system check anymore, even if other partitions are not BTRFS

  • We can create a fake fsck.btrfs command

    $ ln -s /usr/bin/true /usr/bin/fsck.btrfs
    $ sed 's/^\(HOOKS=.*fsck\)\(.*$\)/\1 btrfs\2/g' -i mkinitcpio.conf
    $ mkinitcpio -p linux

Install and configure the bootloader

I choose gummiboot bootloader which is a simple bootloader for EFI systems. First of all, you install it. Before installing it, you may mount the efivarfs.

$ mount -t efivarfs efivarfs /sys/firmware/efi/efivarfs
$ pacman -S gummiboot
$ gummiboot install

Now, we can configure the bootloader following the specifications propose by http://www.freedesktop.org (see the references). Before configuring it, we will get the following variable:

$ export MACHINE_ID=`cat /etc/machine-id`
$ export KERNEL_VERSION=`uname -r`
$ export OS_IDENTIFIER=`cat /etc/os-release | grep ID | awk -F '=' '{print $2}'`
$ export MACHINE_HARDWARE=`uname -m`
$ export OS_VERSION=`echo $KERNEL_VERSION.$OS_IDENTIFIER.$MACHINE_HARDWARE`
$ export PARTUUID=`ls -l /dev/disk/by-partuuid/ | grep sda2 | awk '{print $9}'`

Create an entry in /boot/loader/entries.

$ vi /boot/loader/entries/$MACHINE_ID-$OS_VERSION.conf
title		Arch Linux
version		<value of $OS_VERSION>
machine-id	<value of $MACHINE_ID>
options		root=PARTUUID=<value of $PARTUUID> rootflags=subvol=__active/ROOT rw
linux		/<value of $MACHINE_ID>/<value of $OS_VERSION>/linux
initrd		/<value of $MACHINE_ID>/<value of $OS_VERSION>/initrd

We may also configure the main configuration file /boot/loader/loader.conf.

timeout		3
default		<name of the entries conf file, without the '.conf'>

The default should be fine since it use any entry file which begin with the machine ID.

You should now create the directories and copy the images into them.

$ mkdir -p /boot/$MACHINE_ID/$OS_VERSION
$ cp /boot/vmlinuz-linux /boot/$MACHINE_ID/$OS_VERSION/linux
$ cp /boot/initramfs-linux.img /boot/$MACHINE_ID/$OS_VERSION/initrd

Rebooting the system

Before rebooting, you should define a root password, unmount all the mounted filesystems and quit the chroot environment.

$ umount /sys/firmware/efi/efivarfs
$ exit
$ umount -R /mnt/btrfs-active
$ umount -R /mnt/btrfs-root
$ reboot

Possible errors

Make the ramdisk environment

You may have the following messages during the creation of the ramdisk.

==> WARNING: Possibly missing firmware for module: aic94xx
==> WARNING: Possibly missing firmware for module: bfa
==> WARNING: Possibly missing firmware for module: smsmdtv

It is probably some missing firmware you may install later.

Gummiboot installation

When installing gummiboot with pacman, you may have the following error message.

$ pacman -S gummiboot
...
Copied /usr/lib/gummiboot/gummibootx64.efi to /boot/EFI/gummiboot/gummibootx64.efi
Copied /usr/lib/gummiboot/gummibootx64.efi to /boot/EFI/Boot/BOOTX64.efi
Failed to create EFI Boot variable entry: No such file or directory

If this is the case, you may try the following before trying to reinstall gummiboot.

$ mount -t efivarfs efivarfs /sys/firmware/efi/efivarfs
$ pacman -S gummiboot

When rebooting, crash into ramfs

You may crash into the ramfs when rebooting. This is probably because you forget to indicate to the kernel which BTRFS subvolume is the default one. You may choose one of the two following solutions (both are explained in the above configuration):

  • Give the right option to the kernel with rootflags (see above for details)

  • Make one of the BTRFS subvolume the default. You can list the subvolume with the following command.

    $ btrfs subvolume list -atp /mnt/btrfs-root

You should have something like the following

ID	gen	parent	top level	path
--	---	------	---------	----
256	18	5	5		__active/ROOT
257	7	5	5		__active/home
258	8	5	5		__active/opt
259	18	5	5		__active/var

We will now set the default subvolume which will be used by the kernel to launch the system. Keep the ID of the __active/ROOT subvolume and use it in the following command.

$ btrfs subvolume set-default 256 /mnt/btrfs-root/__active/ROOT

Be aware that this solution will fail to mount the root BTRFS system since it will mount instead this default subvolume. You may avoid it in the previous configuration because the root BTRFS file system must be mount in order to bind /var/lib.

References

For this article, there is two main references. The first one is the Beginner’s guide for Arch Linux installation. There is a lot of information on how to install an Arch Linux distribution and a lot of links to explain the details.

The second reference is mainly about the BTRFS configuration suggest by Fabio Mancinelli in his article.

links

social