471 lines
14 KiB
Markdown
471 lines
14 KiB
Markdown
---
|
|
layout: post
|
|
author: Sam Hadow
|
|
tags: archlinux selinux sysadmin
|
|
---
|
|
|
|
This post is a guide to install archlinux in UEFI with full disk encryption (LVM on LUKS), SELinux enabled and optionally secure boot.
|
|
**Warning:** apparmor is much easier to use on archlinux, SELinux on archlinux **will** require you to write some policies manually. Fedora is a better solution if you want SELinux working out of the box and don't want to fight SELinux writing policies. This guide is mostly for advanced users.
|
|
|
|
## preparing installation media
|
|
|
|
Follow the initial steps from archlinux [wiki](https://wiki.archlinux.org/title/Installation_guide) to prepare your installation media, the most convenient solution is to copy the ISO to a [ventoy](https://www.ventoy.net/en/index.html) USB key.
|
|
Then boot your archlinux ISO and first check you have internet access on your computer:
|
|
|
|
```bash
|
|
ping archlinux.org
|
|
```
|
|
|
|
If using WiFi, you'll need to use [iwctl](https://wiki.archlinux.org/title/Iwd#iwctl)
|
|
|
|
# installation steps
|
|
|
|
## 1) setting up LVM and preparing volumes
|
|
|
|
### 1.1) loading the required kernel modules
|
|
|
|
```bash
|
|
modprobe efivarfs
|
|
modprobe dm-crypt
|
|
modprobe dm-mod
|
|
```
|
|
|
|
### 1.2) partition table
|
|
|
|
Find the disk you want to use to install your system with `lsblk`. For me it's `vda` as I'm using a virtual machine to write this guide.
|
|
**important:** Select a GPT parition table type and not MBR.
|
|
Create a partition table with `cfdisk /dev/vda` (or your prefered tool) and create 2 partitions:
|
|
+ `/dev/vda1` as ef EFI (FAT-12/16/32) type, a size of 512MB is fine
|
|
+ `/dev/vda2` as 83 Linux filesystem type for the rest of the disk
|
|
|
|
Write the partition table to the disk.
|
|
|
|
### 1.3) setting up the encrypted volume
|
|
|
|
Create the encrypted volume, it will ask you for a confirmation and let you choose a passphrase. (Note that PBKDF2 key derivation algorithm is weaker than Argon2 but is required when using the default grub bootloader, the installation using systemd-boot will not be covered in this guide.)
|
|
|
|
```bash
|
|
cryptsetup luksFormat --type luks2 --pbkdf pbkdf2 /dev/vda2
|
|
```
|
|
|
|
Then open it with the passphrase chosen.
|
|
|
|
```bash
|
|
cryptsetup luksOpen /dev/vda2 luks
|
|
```
|
|
|
|
### 1.4) setting up LVM
|
|
|
|
We will create 3 volumes, one for the SWAP, one for the ROOT filesystem and one for the HOME filesystem. Adapt the sizes to what is appropriate for you, in my case I'm using a virtual machine with a 25GB disk so I won't create a huge root volume.
|
|
|
|
```bash
|
|
pvcreate /dev/mapper/luks
|
|
vgcreate system /dev/mapper/luks
|
|
lvcreate -L 1G -n swap system
|
|
lvcreate -L 10G -n root system
|
|
lvcreate -l 100%FREE -n home system
|
|
```
|
|
|
|
### 1.5) formating and mounting the volumes
|
|
|
|
I'll use a BTRFS filesystem but use the filesystem you prefer.
|
|
|
|
```bash
|
|
#formatting
|
|
mkfs.fat -F32 /dev/vda1
|
|
fatlabel /dev/vda1 BOOT
|
|
mkswap -L SWAP /dev/mapper/system-swap
|
|
mkfs.btrfs -L ROOT /dev/mapper/system-root
|
|
mkfs.btrfs -L HOME /dev/mapper/system-home
|
|
|
|
#mounting
|
|
swapon /dev/mapper/system-swap
|
|
mount -o compress=zstd /dev/mapper/system-root /mnt
|
|
mkdir -p /mnt/{home,boot,boot/efi,etc}
|
|
mount -o compress=zstd /dev/mapper/system-home /mnt/home
|
|
mount /dev/vda1 /mnt/boot/efi
|
|
```
|
|
|
|
Then create the fstab.
|
|
|
|
```bash
|
|
genfstab -pU /mnt >> /mnt/etc/fstab
|
|
```
|
|
|
|
## 2) base installation
|
|
|
|
### 2.1) installing required packages
|
|
|
|
We'll use reflector to generate the mirrorlist. Adapt the country code to pick the closest mirrors.
|
|
|
|
```bash
|
|
reflector -c FR -p https -a 12 --sort rate --save /etc/pacman.d/mirrorlist
|
|
```
|
|
|
|
Then install the required packages and some useful packages.
|
|
|
|
```bash
|
|
pacstrap -i /mnt base base-devel linux linux-firmware linux-headers pacman-contrib man-pages btrfs-progs vim git bash-completion
|
|
```
|
|
|
|
### 2.2) chroot
|
|
|
|
Chroot into the system to continue the installation.
|
|
|
|
```bash
|
|
arch-chroot /mnt /bin/bash
|
|
```
|
|
|
|
#### 2.2.1) locales, hostname, clock and timezone
|
|
|
|
In the file `/etc/locale.gen`, uncomment your locales (for example `en_US.UTF-8 UTF-8`)
|
|
You can also set your preferences for the virtual console in `/etc/vconsole.conf`, for example for a QWERTY layout:
|
|
|
|
```ini
|
|
KEYMAP=us
|
|
FONT=lat9w-16
|
|
```
|
|
|
|
And in `/etc/locale.conf` (LC_COLLATE=C for case sensitive sorting):
|
|
|
|
```ini
|
|
LANG=en_US.UTF-8
|
|
LC_COLLATE=C
|
|
```
|
|
|
|
And finally generate the locales:
|
|
|
|
```bash
|
|
locale-gen
|
|
```
|
|
|
|
You can set your hostname in `/etc/hostname`.
|
|
|
|
For your clock and timezone: (adapt to your timezone)
|
|
|
|
```bash
|
|
ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime
|
|
hwclock --systohc --utc
|
|
```
|
|
|
|
#### 2.2.2) root password and user creation
|
|
|
|
Set your root password with `passwd`
|
|
Then create a user (named sam here) in the wheel group (to use sudo) and set its password with:
|
|
|
|
```bash
|
|
useradd -m -G wheel sam
|
|
passwd sam
|
|
```
|
|
|
|
and uncomment the line containing `%wheel ALL=(ALL:ALL) ALL` in `/etc/sudoers`
|
|
|
|
#### 2.2.3) SELinux installation (from AUR)
|
|
|
|
Log in as your created user and install an AUR helper to make things easier:
|
|
|
|
```bash
|
|
su sam
|
|
cd
|
|
git clone https://aur.archlinux.org/yay.git
|
|
cd yay
|
|
makepkg -si
|
|
cd
|
|
```
|
|
|
|
Then install the required packages for SELinux to work. It will ask you for replacements with conflicting packages, answer yes every time.
|
|
|
|
```bash
|
|
yay -S libsepol libselinux checkpolicy secilc setools libsemanage semodule-utils policycoreutils selinux-python python-ipy mcstrans restorecond
|
|
yay -S pam-selinux pambase-selinux coreutils-selinux findutils-selinux iproute2-selinux logrotate-selinux openssh-selinux psmisc-selinux shadow-selinux cronie-selinux
|
|
yay -S sudo-selinux
|
|
```
|
|
|
|
Note: If `sudo-selinux` fails to build, build it with `--nocheck` option:
|
|
|
|
```bash
|
|
cd ~/.cache/yay/sudo-selinux
|
|
makepkg -si --nocheck
|
|
```
|
|
|
|
Then exit your user, remodify `/etc/sudoers` to uncomment the line containing `%wheel ALL=(ALL:ALL) ALL` and relog as your user. After that:
|
|
|
|
```bash
|
|
sudo pacman -S less
|
|
yay -S systemd-selinux systemd-libs-selinux util-linux-selinux util-linux-libs-selinux
|
|
cd ~/.cache/yay/systemd-selinux
|
|
makepkg -si --nocheck
|
|
```
|
|
|
|
Due to a [cyclic dependency which won't be fixed](https://bugs.archlinux.org/task/39767) the complete build will fail at first, that's why you need to manually build systemd-selinux again after. For some reason less is also required for the build but not a build dependency.
|
|
Then more SELinux packages and a policy:
|
|
|
|
```bash
|
|
yay -S selinux-alpm-hook dbus-selinux selinux-refpolicy-arch
|
|
```
|
|
|
|
If the check fails for `dbus-selinux` build it with `--nocheck` option:
|
|
|
|
```bash
|
|
cd ~/.cache/yay/dbus-selinux
|
|
makepkg -si --nocheck
|
|
```
|
|
|
|
If you want to apply a fedora-style user context (as root):
|
|
|
|
```bash
|
|
semanage login -m -s unconfined_u __default__
|
|
```
|
|
|
|
#### 2.2.4) necessary packages
|
|
|
|
Network for next boot:
|
|
|
|
```bash
|
|
pacman -S networkmanager
|
|
systemctl enable NetworkManager
|
|
```
|
|
|
|
grub and lvm2:
|
|
|
|
```bash
|
|
pacman -S grub efibootmgr lvm2
|
|
```
|
|
|
|
Secure boot:
|
|
*Note: If you don't want to bother with secure boot, do not run sbctl related command, and later when generating the boot image with grub, remove* `--modules="tpm" --disable-shim-lock` *from the command*
|
|
|
|
```bash
|
|
pacman -S sbctl
|
|
sbctl create-keys
|
|
sbctl enroll-keys -m
|
|
```
|
|
|
|
##### linking TPM and LUKS key
|
|
|
|
Without this step, the computer is still vulnerable to evild maid attacks and a software keylogger could be installed by disabling the secure boot (clear CMOS for example). To make sure the encrypted device is linked to the TPM, we need to run the following command:
|
|
|
|
```bash
|
|
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 /dev/vda2
|
|
```
|
|
|
|
[systemd-cryptenroll](https://wiki.archlinux.org/title/Systemd-cryptenroll) also support hardware security keys like FIDO2 tokens, in this case you can refer to the archwiki for the command syntax.
|
|
systemd-boot is also the recommended option instead of using grub when linking the TPM and LUKS key, you can then only have a PIN and also be protected in more scenarios.
|
|
|
|
#### 2.2.5) opional packages
|
|
|
|
If you have an intel CPU:
|
|
|
|
```bash
|
|
pacman -S intel-ucode
|
|
```
|
|
|
|
If you have a laptop and want battery optimization:
|
|
|
|
```bash
|
|
pacman -S tlp
|
|
systemctl enable tlp
|
|
```
|
|
|
|
If you need bluetooth:
|
|
|
|
```bash
|
|
pacman -S bluez
|
|
systemctl enable bluetooth
|
|
```
|
|
|
|
If you want 32bits apps (necessary for some packages), in `/etc/pacman.conf` uncomment these lines:
|
|
|
|
```ini
|
|
#[multilib]
|
|
#include = /etc/pacman.d/mirrorlist
|
|
```
|
|
|
|
#### 2.2.5) generating boot images
|
|
|
|
in `/etc/mkinitcpio.conf` on the `MODULES=()` line, add `dm-mod` and in the `HOOKS=()` line you should have:
|
|
|
|
```ini
|
|
HOOKS=(base udev autodetect modconf block keyboard encrypt lvm2 filesystems fsck)
|
|
```
|
|
|
|
Then:
|
|
|
|
```bash
|
|
mkinitcpio -p linux
|
|
```
|
|
|
|
sbctl post-hook should automatically sign `/boot/vmlinuz-linux`. Otherwise run:
|
|
|
|
```bash
|
|
sbctl sign -s /boot/vmlinuz-linux
|
|
```
|
|
|
|
Then in `/etc/default/grub`
|
|
+ uncomment the line `GRUB_UNABLE_CRYPTODISK=y`
|
|
+ in `GRUB_CMDLINE_LINUX=""` add `cryptdevice=/dev/vda2:system root=/dev/mapper/system-root`
|
|
+ in `GRUB_CMDLINE_LINUX_DEFAULT=""` add `lsm=selinux,landlock,lockdown,yama,integrity,bpf`
|
|
|
|
Then:
|
|
|
|
```bash
|
|
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=arch_grub --modules="tpm" --disable-shim-lock --recheck
|
|
grub-mkconfig -o /boot/grub/grub.cfg
|
|
sbctl sign -s /boot/efi/EFI/arch_grub/grubx64.efi
|
|
```
|
|
|
|
*Please note that in a virtual machine you'll need an emulated TPM for the virtual machine to boot if you want secure boot enabled.*
|
|
|
|
### 3) exit and reboot
|
|
|
|
```bash
|
|
exit # until you exit the chroot
|
|
umount -R /mnt
|
|
swapoff -a
|
|
reboot
|
|
```
|
|
|
|
### 4) post reboot steps
|
|
|
|
#### 4.1) relabel files
|
|
|
|
check SELinux status with `sestatus`, it should be in permissive with refpolicy-arch as the loaded policy.
|
|
Relabel all the files correctly with the following command:
|
|
|
|
```bash
|
|
restorecon -RFv /
|
|
```
|
|
|
|
you might want to clean yay cache before doing that to have less files to relabel:
|
|
|
|
```bash
|
|
rm -rf ~/.cache/yay/*
|
|
```
|
|
|
|
#### 4.2) enable auditd
|
|
|
|
enable auditd service to read AVC denials from SELinux later.
|
|
|
|
```bash
|
|
systemctl enable --now auditd
|
|
```
|
|
|
|
#### 4.3) create and load necessary policy
|
|
|
|
Create a file `requiredmod.te` with the following content:
|
|
|
|
```text
|
|
module requiredmod 1.0;
|
|
|
|
require {
|
|
type auditd_etc_t;
|
|
type getty_t;
|
|
type var_run_t;
|
|
type tmpfs_t;
|
|
type local_login_t;
|
|
type systemd_tmpfiles_t;
|
|
type init_runtime_t;
|
|
type devpts_t;
|
|
type kernel_t;
|
|
type device_t;
|
|
type udev_t;
|
|
type hugetlbfs_t;
|
|
type udev_tbl_t;
|
|
type policy_config_t;
|
|
type tmp_t;
|
|
type unconfined_t;
|
|
type var_lib_t;
|
|
type systemd_userdbd_runtime_t;
|
|
type systemd_user_runtime_dir_t;
|
|
type systemd_sessions_t;
|
|
type systemd_userdbd_t;
|
|
type etc_runtime_t;
|
|
type systemd_logind_t;
|
|
type file_context_t;
|
|
type semanage_t;
|
|
type selinux_config_t;
|
|
type initrc_runtime_t;
|
|
type sshd_t;
|
|
class dir { write add_name remove_name getattr open read search };
|
|
class file { getattr open read write create getattr ioctl lock relabelfrom relabelto setattr unlink };
|
|
class sock_file write;
|
|
class unix_stream_socket { read write ioctl connectto};
|
|
class capability2 block_suspend;
|
|
class filesystem { associate quotaget quotamod };
|
|
class key { link search };
|
|
class process { noatsecure rlimitinh siginh transition };
|
|
|
|
}
|
|
|
|
#============= getty_t ==============
|
|
allow getty_t tmpfs_t:dir { getattr open read };
|
|
allow getty_t var_run_t:file { getattr open read };
|
|
allow getty_t initrc_runtime_t:dir { getattr open read };
|
|
|
|
#============= local_login_t ==============
|
|
allow local_login_t init_runtime_t:sock_file write;
|
|
allow local_login_t systemd_logind_t:unix_stream_socket connectto;
|
|
allow local_login_t var_lib_t:dir { add_name remove_name };
|
|
allow local_login_t var_lib_t:file { create getattr lock open read setattr unlink write };
|
|
|
|
#============= sshd_t ==============
|
|
allow sshd_t local_login_t:key { link search };
|
|
allow sshd_t systemd_logind_t:unix_stream_socket connectto;
|
|
allow sshd_t unconfined_t:process { noatsecure rlimitinh siginh };
|
|
|
|
#============= systemd_tmpfiles_t ==============
|
|
allow systemd_tmpfiles_t auditd_etc_t:dir search;
|
|
allow systemd_tmpfiles_t auditd_etc_t:file getattr;
|
|
|
|
#============= systemd_sessions_t ==============
|
|
allow systemd_sessions_t kernel_t:dir search;
|
|
allow systemd_sessions_t kernel_t:file { getattr ioctl open read };
|
|
|
|
#============= systemd_user_runtime_dir_t ==============
|
|
allow systemd_user_runtime_dir_t etc_runtime_t:file { open read };
|
|
allow systemd_user_runtime_dir_t kernel_t:dir search;
|
|
allow systemd_user_runtime_dir_t kernel_t:file { getattr ioctl open read };
|
|
allow systemd_user_runtime_dir_t systemd_userdbd_runtime_t:sock_file write;
|
|
allow systemd_user_runtime_dir_t systemd_userdbd_t:unix_stream_socket connectto;
|
|
allow systemd_user_runtime_dir_t tmp_t:dir read;
|
|
allow systemd_user_runtime_dir_t tmpfs_t:filesystem { quotaget quotamod };
|
|
|
|
#============= systemd_userdbd_t ==============
|
|
allow systemd_userdbd_t initrc_runtime_t:dir { getattr open read search };
|
|
|
|
#============= devpts_t ==============
|
|
allow devpts_t device_t:filesystem associate;
|
|
|
|
#============= hugetlbfs_t ==============
|
|
allow hugetlbfs_t device_t:filesystem associate;
|
|
|
|
#============= kernel_t ==============
|
|
allow kernel_t self:capability2 block_suspend;
|
|
|
|
#============= tmpfs_t ==============
|
|
allow tmpfs_t device_t:filesystem associate;
|
|
|
|
#============= udev_t ==============
|
|
allow udev_t kernel_t:unix_stream_socket { read write ioctl };
|
|
allow udev_t udev_tbl_t:dir { write add_name };
|
|
allow udev_t var_run_t:sock_file write;
|
|
```
|
|
|
|
Run the following command to compile and load the module:
|
|
```bash
|
|
checkmodule -m -o requiredmod.mod requiredmod.te
|
|
semodule_package -o requiredmod.pp -m requiredmod.mod
|
|
semodule -i requiredmod.pp
|
|
```
|
|
|
|
And set a few booleans:
|
|
|
|
```bash
|
|
setsebool -P allow_polyinstantiation on
|
|
setsebool -P systemd_tmpfiles_manage_all on
|
|
setsebool -P ssh_sysadm_login on
|
|
```
|
|
|
|
Then in `/etc/selinux/config`, set SELinux mode to enforcing instead of permissive and reboot.
|
|
And that's it, you now have a minimal archlinux installation in UEFI with full disk encryption, secure boot, and SELinux in enforcing mode.
|