Extended Brain Storage

Artix Linux: Full Disk Encryption with UEFI

Posted on September 20, 2017

Not everyone fells happy and confident about systemd. In order to keep peace within a linux-based operating system, administrators may study, serve and use the art of mystical energy of the Force...

Introduction

Artix Linux is a systemd-free linux-based distribution, which is derived from Arch Linux. Therefore, it is somewhat "backward-compatible", as it uses its repositories including the AUR. However, it uses OpenRC instead of the intrusive systemd.

The installation process (without encryption) is "somewhat" described on the project Wiki. The installation ISO can be downloaded from several mirrors and as yet, comes in three flavours: lxqt, i3 and base.

Within the respective (lxqt/i3) graphical user interface (GUI), the first two options provide an installation wizard that can be triggered by the calamares command, which is a distribution-independent installer framework. The base-flavoured option lacks these features, due to which it is very light-weighted and preferred.

The downloaded ISO image can be transferred to a USB flash medium using the dd command as follows:

$ dd if=/source/image of=/dev/target bs=4M status=progress && sync

The From CD/DVD/ISO option has to be selected in the GRUB boot menu (and NOT the From Stick/HDD). Those who dared to use the forbidden (second) option, experienced problems with polkit and other issues, examples of which can be found: here, here, here etc.

Artix GRUB Menu Selection

Artix GRUB Menu Selection


The Goal

This is a brief tutorial to install Artix linux on a notebook, which is:

The aforementioned requirements will provide a full disk encryption (FDE) installation, i.e. the root and swap partitions (the lvm-volRoot and lvm-volSwap volumes, to be more precise) will be encrypted using the LVM on LUKS method. The only unencrypted partition will be the first partition, i.e. the ESP; and thus, the kernels and initramfs files in the /boot/ directory will be encrypted as well.

UEFI GRUB Disk Partitioning Scheme

UEFI GRUB Disk Partitioning Scheme


Other Disk Format and Firmware Options

Other ideas of disk formatting and firmware options are discussed in: Linux: Full Disk Encryption with BIOS, UEFI using MBR, GPT, LUKS, LVM and GRUB


The Installation Process

Administrators can log into the machine using a terminal session and credentials artix/artix and change to the privileged account by running:

$ sudo su

The developers changed the project mirrors several months ago. Yet, they haven't been able to update the installation media accordingly (April 2018). Luckily, it can be repaired as follows:

$ echo "Server = https://mirrors.dotsrc.org/artix-linux/repos/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist

In order to have software tools up-to-date, the pacman's database needs to be updated as follows:

$ pacman -Sy

Optionally, it may be handy to perform the installation remotely, i.e. over a (local) network via SSH. For that purpose, openssh needs to be installed and activated as follows:

$ pacman -S --noconfirm glibc openssh openssh-openrc
$ rc-service sshd start

In order to log into the machine running SSH, the notoriously know command can be used as follows:

$ ssh artix@IP_ADDRESS

In order to manipulate disk partitions, the ISO image (live CD) comes with cfdisk. However, it does not align partitions to block device I/O limits. It may seem useful to work with tools that do support such elementary features, such as parted (fdisk, gdisk, etc.), which can be installed from the repository by running:

$ pacman -S parted

Disks Availability

Since the syntax of parted is obvious for example purposes, it will be used in the following command examples. The available disk(s) can be checked as follows:

$ parted -s /dev/sdX print

The comparison of their syntax can be found, for example, in Troy's Wiki.

Disk Format and Partitioning

The following commands WILL DELETE DATA. As discussed earlier, the SATA disk (/dev/sdX) will be partitioned using the GPT, since the target machine (notebook) comes with a UEFI firmware (instead of BIOS).

$ parted -s /dev/sdX mklabel gpt

Due to the UEFI firmware, an EFI System Partition of 512MiB should be created in Linux environment (550 MiB is recommended). Additionally, all parted commands can be run with -a optimal parameter in order to align partitions accordingly as follows:

$ parted -s -a optimal /dev/sdX mkpart "primary" "fat16" "0%" "512MiB"
$ parted -s /dev/sdX set 1 esp on

Optionally, parted can align partitions at any time by running:

$ parted -s /dev/sdX print
$ parted -s /dev/sdX align-check optimal <PARTITION_NUMBER>

Furthermore, an empty disk partition needs to be created in the rest of the space:

$ parted -s -a optimal /dev/sdX mkpart "primary" "ext4" "512MiB" "100%"
$ parted -s /dev/sdX set 2 lvm on

Disk Encryption and Logical Volumes

The disk encryption will utilise the Linux Unified Key Setup (LUKS), which is now part of an enhanced version of cryptsetup, using dm-crypt (device-mapper crypt) as the disk encryption backend.

LUKS physical partition can be created and formatted as follows:

$ cryptsetup luksFormat -v /dev/sdX2

Alternatively, including more details (the following is the default):

$ cryptsetup -v --cipher aes-xts-plain64 --key-size 256 --hash sha256 --iter-time 2000 --use-urandom --verify-passphrase luksFormat /dev/sdX2

The LUKS-encrypted partition (/dev/sdX2) needs to be opened and mounted using the device mapper (into e.g. lvm-system):

$ cryptsetup luksOpen /dev/sdX2 lvm-system

Note: If any of the commands produces the following warning, it can be ignored, as: "This is because /run is not available inside the chroot."

WARNING: Failed to connect to lvmetad. Falling back to device scanning.

or

/run/lvm/lvmetad.socket: connect failed: No such file or directory

or

WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.

Now it is possible to create a physical volume using the Logical Volume Manager (LVM) and the previously used id (lvm-system) as follows:

$ pvcreate /dev/mapper/lvm-system

Having the physical volume, it is possible to create a logical volume group named lvmSystem as follows:

$ vgcreate lvmSystem /dev/mapper/lvm-system

And having the logical volume group, the logical volumes can be created as follows. As an example, a 16GB for swap (volSwap) and the rest for the root partition (volRoot):

$ lvcreate -L 16G lvmSystem -n volSwap
$ lvcreate -l +100%FREE lvmSystem -n volRoot

Note: The size of a swap partition has always been part of many discussions. Basically, in order to have suspend-to-disk (hibernation) mechanism working, it is not necessary to have the swap of the same size as RAM. Reader discretion advised.

Having all physical and virtual disk partitions ready, it is possible to format them as follows (swap, fat for ESP and ext4 for /):

$ mkswap /dev/lvmSystem/volSwap
$ mkfs.fat -n ESP /dev/sdX1
$ mkfs.ext4 -L volRoot /dev/lvmSystem/volRoot

Having each partition formatted, they can be mounted as follows:

$ swapon /dev/lvmSystem/volSwap
$ mount /dev/lvmSystem/volRoot /mnt
$ mkdir -p /mnt/boot/EFI
$ mount /dev/sdX1 /mnt/boot/EFI

Packages Installation, Kernel Compilation

Finally, the operating system parts can be downloaded and installed as follows:

$ basestrap /mnt base base-devel

The /etc/fstab file can be created using various system identifiers, the following step uses UUIDs:

$ fstabgen -U /mnt >> /mnt/etc/fstab

Optionally, all solid-state disk (SSD) mountpoints can be updated with the discard option to enable TRIM:

$ sed -i "s/ordered/ordered,discard/g" /mnt/etc/fstab

However, there are opinions that recommend against that. If in doubt about the hardware, the Periodic TRIM can be applied instead.

Optionally, size of the TMPFS partition (e.g. of size 8GB, i.e. half RAM size) can be changed as follows:

$ echo "tmpfs	/tmp	tmpfs	nodev,nosuid,size=8G	0 0" >> /mnt/etc/fstab

Now, it is time to change root (chroot) to the newly installed environment:

$ artools-chroot /mnt /bin/bash

System-wide locale (e.g. en_AU.UTF-8) can be set up as follows:

$ echo -e "en_AU.UTF-8 UTF-8" >> /etc/locale.gen
$ locale-gen
$ echo LANG=en_AU.UTF-8 > /etc/locale.conf
$ export LANG=en_AU.UTF-8

Time zone and hostname (e.g. 4rt1x) can be configured as follows:

$ ln -s /usr/share/zoneinfo/Continent/City /etc/localtime
$ echo "hostname=4rt1x" > /etc/conf.d/hostname

The /etc/mkinitcpio.conf file enables to set up various kernel parameters. Within the HOOKS part, the encrypt lvm2 need to be put between block and filesystems keywords in order to enable the FDE. It may also be useful to include the resume keyword to enable suspend to disk options. However, this may not work at all times, such as with hardened kernels. Finally, the GRUB's /crypto_keyfile.bin file can be specified to automatically unlock disk X after system boot:

$ sed -i "s/FILES=(/FILES=(\/crypto_keyfile.bin/g" /etc/mkinitcpio.conf
$ sed -i "s/modconf block/modconf block encrypt lvm2 resume/g" /etc/mkinitcpio.conf

For more details regarding usage of /dev/random and /dev/urandom for keys generation, this ArchWiki page can be visited. A random-byte file can be generated in order to serve as key to automatically decrypt the system partition during boot by GRUB as follows:

$ dd if=/dev/random of=/crypto_keyfile.bin bs=512 count=8 iflag=fullblock
$ cryptsetup luksAddKey /dev/sdX2 /crypto_keyfile.bin
$ chmod 000 /crypto_keyfile.bin

Now, the kernel can be compiled and a new initramdisk created (the default kernel is now linux):

$ mkinitcpio -p linux

Consequently, the root password needs to be set up:

$ passwd

Boot Loader Installation

There are various bootloaders. However, the following commands use the GRUB (and its optional dependencies):

$ pacman -S grub efibootmgr
$ pacman -S dosfstools freetype2 fuse2 gptfdisk libisoburn mtools os-prober
$ pacman -S iw memtest86+ wpa_supplicant

Optionally when required and after considering that hibernation/resume will not work with hardened kernels, the resume partition needs to be configured in the /etc/default/grub file as follows:

$ sed -i "s/quiet/quiet resume=UUID=`blkid -s UUID -o value /dev/lvmSystem/volSwap`/g" /etc/default/grub

As discussed earlier, in order to prevent the password to open the LUKS volume to be asked the second time (the first time it is asked by GRUB), the /etc/mkinitcpio.conf file (the FILES variable) needs to be updated with the key file path reference as follows:

$ sed -i "s/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"cryptdevice=UUID=`blkid -s UUID -o value /dev/sdX2`:lvm-system\"/g" /etc/default/grub

Grub needs to be configured in /etc/default/grub in order to find the LUKS-encrypted partition as follows:

$ sed -i "s/#GRUB_ENABLE_CRYPTODISK/GRUB_ENABLE_CRYPTODISK/g" /etc/default/grub

Optionally, GRUB colours can be modified as follows:

$ sed -i "s/#GRUB_COLOR_NORMAL/GRUB_COLOR_NORMAL/g" /etc/default/grub
$ sed -i "s/#GRUB_COLOR_HIGHLIGHT/GRUB_COLOR_HIGHLIGHT/g" /etc/default/grub

Finally, GRUB can be installed at the beginning of the first disk (/dev/sdX) that contains the ESP mounted in the /boot/EFI directory as follows:

$ grub-install --target=x86_64-efi --efi-directory=/boot/EFI --bootloader-id=artix --recheck /dev/sdX
$ grub-mkconfig -o /boot/grub/grub.cfg

Note: Every change in the configuration of GRUB needs to be followed by the following command in order to be applied:

$ grub-mkconfig -o /boot/grub/grub.cfg

Note: When reinstalling GRUB, the following warnings may be observed and ignored:

/run/lvm/lvmetad.socket: connect failed: No such file or directory

or

WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.

This is because /run is not available inside the chroot. These warnings will not prevent the system from booting, provided that everything has been done correctly, so you may continue with the installation.

Optionally, the GRUB setup needs to be changed in order to prevent the (e)udev from renaming the kernel eth0, wlan0 interfaces to enp0s25, wlp4s0 etc. using the optional net.ifnames=0 parameter as follows:

$ vi /etc/default/grub
GRUB_CMDLINE_LINUX="... net.ifnames=0"
$ grub-mkconfig -o /boot/grub/grub.cfg

Necessary Services Setup

In order to decrypt and use the LUKS/LVM volumes, the following services need to be installed and activated:

$ pacman -S device-mapper-openrc lvm2-openrc cryptsetup-openrc
$ rc-update add device-mapper boot
$ rc-update add lvm boot
$ rc-update add dmcrypt boot

The udev service (eudev/eudev-openrc) should be started by default in the sysinit runlevel. Its activation can be confirmed as follows:

$ rc-status sysinit | grep udev
Service `netmount' needs non existent service `net'
 udev                                                              [  stopped  ]
 udev-trigger                                                      [  stopped  ]

The dbus service should be installed and activated. Should it not, it can be done as follows:

$ rc-update add dbus default

The systemd project's logind should be installed as part of the base meta package. Should it not be activated, it can be done as follows:

$ rc-update add elogind boot

The haveged service is a simple entropy daemon useful for unpredictable random number generation, which can be installed and activated as follows:

$ pacman -S haveged haveged-openrc
$ rc-update add haveged default

Cron job daemons (cronie, fcron etc.) can be installed and activated as follows (e.g. cronie):

$ pacman -S cronie cronie-openrc
$ rc-update add cronie default

Adding Unprivileged User Accounts

As an example, the following list of commands adds a non-privileged user (USERNAME) into the system as part of the wheel and users groups and including a prompt for password:

$ useradd -m -G wheel -s /bin/bash USERNAME
$ passwd USERNAME

Sudoers setup for the wheel group can be simply changed as follows:

$ sed -i "s/# %wheel ALL=(ALL) ALL/%wheel ALL=(ALL) ALL/g" /etc/sudoers

Network Setup using Network Manager

If Network Manager GUI is the desired choice to manage network interfaces, the following needs to be run in order to install and activate the service:

$ pacman -S networkmanager networkmanager-openrc networkmanager-openvpn network-manager-applet
$ rc-update add NetworkManager default

Optionally, more plugin options for NetworkManager can be looked up as follows:

$ pacman -Ss networkmanager

Since the unprivileged user should be in either wheel or network group in order to manage network interfaces, it may be necessary to run, e.g.:

$ usermod -a -G wheel USERNAME

One of the downsides is that the passwords are stored in clear text in:

$ grep -H '^psk=' /etc/NetworkManager/system-connections/*

Another issue is a bit privacy-concerned, since the NetworkManager service periodically connects to http://www.archlinux.org/check_network_status.txt (formerly apollo.archlinux.org) to check its online status.

$ curl http://www.archlinux.org/check_network_status.txt
NetworkManager is online

Luckily, the URL can be changed as follows:

$ vi /etc/NetworkManager/conf.d/11-connectivity-check.conf
[connectivity]
uri=http://server.domain.tld/nm-status/index.php
interval=120
response="You're up, buddy!"
#response="NetworkManager is online"

Obviously, a replacement URL needs to be accessible on another web server. Assuming that the web server runs HTTPD with PHP Support, the configuration can be updated as follows:

### server.domain.tld:80
server "server.domain.tld" {
...
  # NetworkManager
  location "/nm-status/index.php" {
    root "/htdocs/nm-status"
    root strip 1
    fastcgi socket "/run/php-fpm.sock"
  }
...
}

Naturally, the index.php script needs to be created. The example is as follows:

$ mkdir /var/www/htdocs/nm-status
$ vi /var/www/htdocs/nm-status/index.php
<?php
  header('X-NetworkManager-Status: online');
  header('Content-Type: text/plain');
  echo "You're up, buddy!";
  header("HTTP/1.1 200 OK");
?>

Testing and verification:

$ curl http://server.domain.tld/nm-status/index.php
You're up, buddy!

Network Setup using RC scripts

If Network Manager GUI is not the preferred solution, relevant RC services need to be started during system startup (in the default runlevel). In order to activate such option, the following commands need to be run to activate all interfaces (found in the /sys/class/net directory):

$ rc-update add net.lo default
$ for i in `ls /sys/class/net | grep -v lo`; do
  ln -s /etc/init.d/net.lo /etc/init.d/net.$i
  rc-update add net.$i default
done

Note: The previous will not work if the default interface names recognised by udev were changed to eth0 etc. It needs to be run manually and not as per the /sys/class/net directory in chroot enviroment, e.g. for eth0, it needs to be run as: ln -s /etc/init.d/net.lo /etc/init.d/net.eth0; rc-update add net.eth0 default.

A WiFi interface can be configured using the WPA supplicant as follows:

$ wpa_passphrase "SSID" "PASSWORD" > /etc/wpa_supplicant/wpa_supplicant.conf
$ echo "modules_INTERFACE_ID=\"wpa_supplicant dhcpcd\"" >> /etc/conf.d/net

Optionally, the configuration of WPA supplicant can be verified using:

$ wpa_supplicant -iINTERFACE_ID -c/etc/wpa_supplicant/wpa_supplicant.conf

Optionally, to fine-tune any interface, there are many options present in the /etc/conf.d/net file. The following may come handy to decrease the carrier timeout (in seconds), which is ten seconds by default (i.e. waiting until the physical interface is "brought up"):

$ echo "carrier_timeout_INTERFACE_ID=5" >> /etc/conf.d/net

Additional Services Setup

Optionally, numlock can be automatically enabled after system start (generally not desirable for laptops/notebooks):

$ pacman -S numlockx
$ rc-update add numlock default

Optionally, the bloody system beeper can be disabled as follows:

$ echo "blacklist pcspkr" > /etc/modprobe.d/nobeep.conf

SSH daemon can be installed as follows:

$ pacman -S openssh openssh-openrc
$ rc-update add sshd default

For some reason, the basestrap command does install only group nobody without the matching user nobody. A brief check, whether the user and the group are present in the system, can be run as follows:

$ grep nobody /etc/group
nobody:x:99:
$ grep nobody /etc/passwd
<EMPTY-RESULT>

Should the result of the previous command is empty, user nobody needs to be created manually in /etc/passwd as follows:

$ UGID=`grep nobody /etc/group | awk -F: '{print $3}'`
$ echo "nobody:x:$UGID:$UGID:nobody:/:/usr/bin/nologin" >> /etc/passwd

Note: The missing account of user nobody will prevent the SSH daemon from starting (after the installation is complete and system is restarted) such as the following:

$ rc-service sshd start
Privilege separation user nobody does not exist
ERROR: sshd failed to start

NTP, ACPI, Syslog-NG daemons can be installed and activated as follows:

$ pacman -S ntp ntp-openrc acpid acpid-openrc syslog-ng syslog-ng-openrc
$ rc-update add ntpd default
$ rc-update add acpid default
$ rc-update add syslog-ng default

Useful commands (will include samba, samba client):

$ pacman -S artools bash-completion lsof strace
$ pacman -S wget htop mc zip samba unrar p7zip unzip
$ pacman -S hdparm smartmontools hwinfo dmidecode
$ pacman -S whois rsync nmap tcpdump inetutils net-tools ndisc6

In order to access AUR, yaourt can be installed:

$ pacman -S yaourt

Congratulations

The chroot can be escaped as follows:

$ exit

Optionally, everything can be unmounted (should be done automatically, though):

$ umount -R /mnt
$ swapoff -a

The system now can be rebooted:

$ reboot

Post Installation Steps

The very first step after the system restart and successful login attempt is to BACKUP THE LVM METADATA. The process is as simple as follows:

$ cp /etc/lvm/backup/* /somewhere/safe

Furthermore, a brief tutorial of how to install XFCE4 desktop environment is described in Artix Linux: Installation of XFCE4.

Tags: #Artix Linux #security #encryption #FDE #systemd #OpenRC #UEFI #MBR #GPT #LUKS #LVM

⏴ Previous Post Next Post ⏵