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. ### The Goal This is a brief tutorial to install Artix linux on a notebook, which is: • equipped with Unified Extensible Firmware Interface (UEFI), • equipped with a hard-drive (e.g. SSD), which will: • be formatted using GUID Partition Table (GPT) disk scheme, • contain two partitions: 1. of type EF00 (EFI System Partition (ESP)) to be mounted as /boot/EFI with a min. size of 200 MiB, • denoted as EFI System by fdisk, • denoted as boot, esp by parted, 2. of type 8E00 (Linux LVM) to contain the encrypted container that will be: 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. ### 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.