new post, install guide, archlinux with SELinux, full disk encryption and secure boot
This commit is contained in:
@@ -0,0 +1,461 @@
|
||||
---
|
||||
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
|
||||
```
|
||||
|
||||
If you also want to enroll hardware security keys, use [systemd-cryptenroll](https://wiki.archlinux.org/title/Systemd-cryptenroll)
|
||||
|
||||
#### 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.
|
||||
Reference in New Issue
Block a user