User:Bikepunk005
From: https://wiki.archlinux.org/title/User:Bai-Chiang/Installation_notes
The official installation guide only covers basics.
I want to have a installation that enables encrypted root partition, secure boot with my own key and unified kernel image.
It took me quite some time go through these seperated wiki pages to get every pieces working together.
Here I documented all of these steps in one place to save some efforts for my future installations, also provides a guidance for someone looking for a similar setup.
Reader should already familiar the official installation guide. Also I will not give detailed explanation for each step, instead I will provide a link to corresponding wiki page for those interested.
Feature list:
- Encrypted root and swap partition.
- Secure boot with your own keys.
- Unified kernel image boot directly from UEFI.
- Btrfs as root filesystem.
- Using snapper automatically create/cleanup snapshots based on timeline and pacman transactions.
- systemd-homed encrypts your home directory when system is suspended.
- SELinux for adventurous users (unofficial repository, see current status and issues)
sshd.service
by default. You only need to change root password to be able to login remotely.Pre-installation
Put the firmware in "Setup Mode"
This step depends on BIOS implementation. First you need to enable UEFI boot only (no legacy boot). Then change Secure Boot option to Setup Mode. Usually it is under Secure Boot section, the exact name may be different, sometimes called Custom Mode. To check the Secure Boot is set to the Setup Mode, boot into the live iso. Then run
# bootctl status | grep "Secure Boot"
... Secure Boot: disabled (setup) ...
It should have (setup)
.
UEFI Boot manager efibootmgr(8)
Display current boot settings
# efibootmgr
BootCurrent: 0004 BootNext: 0003 BootOrder: 0004,0000,0001,0002,0003 Timeout: 30 seconds Boot0000* Diskette Drive(device:0) Boot0001* CD-ROM Drive(device:FF) Boot0002* Hard Drive(Device:80)/HD(Part1,Sig00112233) Boot0003* PXE Boot: MAC(00D0B7C15D91) Boot0004* Linux
Delete unused boot options. For example
# efibootmgr -b 0004 -B
will delete boot entry 0004.
Set the console keyboard layout
# loadkeys us
Check UEFI mode
If booted as UFEI mode
# ls /sys/firmware/efi/efivars
should should print the directory without error.
Check internet connection
# ping archlinux.org
Recommend using wired connection during installation. Use a USB to Ethernet dongle if necessary.
Check system clock
# timedatectl
Partition the disks
Use fdisk create three partitions:
/dev/sdX1
512MiB EFI system partition. It will not be encrypted./dev/sdX2
root partition. Setup LUKS2 encryption later./dev/sdX3
swap partition. Setup swap encryption later.
Setup encrypted root partition
Encrypt the device with LUKS2 mode
# cryptsetup --type luks2 --verify-passphrase --sector-size 4096 --verbose luksFormat /dev/sdX2
SSD usually report their sector size as 512 bytes, even though they use larger sector size.
So add --sector-size 4096
force create a LUKS2 container with 4K sector size.
If the sector size is wrong cryptsetup
will abort with an error.
To re-encrypt with correct sector size see Advanced Format#dm-crypt.
Unlock the LUKS2 container
# cryptsetup open /dev/sdX2 cryptroot
It will map the encrypted container to new device /dev/mapper/cryptroot
.
Format the partitions
- EFI partition
# mkfs.fat -F 32 /dev/sdX1
- Root partition
# mkfs.btrfs /dev/mapper/cryptroot
- Swap partition
# mkswap /dev/sdX3
swap encryption will be configured afterarch-bootstrap
.
Create Btrfs subvolumes
# mount /dev/mapper/cryptroot /mnt # btrfs subvolume create /mnt/@ # btrfs subvolume create /mnt/@home # btrfs subvolume create /mnt/@snapshots # btrfs subvolume create /mnt/@var_log # btrfs subvolume create /mnt/@pacman_pkgs # mkdir /mnt/@/home # mkdir /mnt/@/.snapshots # mkdir /mnt/@/efi # mkdir -p /mnt/@/var/log # mkdir -p /mnt/@/var/cache/pacman/pkg # umount -R /mnt
Following Snapper#Suggested filesystem layout.
Mount all file systems
# mount -o ssd,noatime,compress=zstd:1,space_cache=v2,autodefrag,subvol=@ /dev/mapper/cryptroot /mnt # mount -o ssd,noatime,compress=zstd:1,space_cache=v2,autodefrag,subvol=@home,nodev,nosuid /dev/mapper/cryptroot /mnt/home # mount -o ssd,noatime,compress=zstd:1,space_cache=v2,autodefrag,subvol=@snapshots,nodev,nosuid,noexec /dev/mapper/cryptroot /mnt/.snapshots # mount -o ssd,noatime,compress=zstd:1,space_cache=v2,autodefrag,subvol=@var_log,nodev,nosuid,noexec /dev/mapper/cryptroot /mnt/var/log # mount -o ssd,noatime,compress=zstd:1,space_cache=v2,autodefrag,subvol=@pacman_pkgs,nodev,nosuid,noexec /dev/mapper/cryptroot /mnt/var/cache/pacman/pkg # mount /dev/sdX1 /mnt/efi # swapon /dev/sdX3
Check btrfs(5) § MOUNT OPTIONS and Security#Mount options for the explanations.
Here I assume the root partition is on a SSD.
If you are still using spinning rust for your boot drive, change mount option ssd
to nossd
.
Installation
Add SELinux repository (optional)
Enable Unofficial user repositories#selinux by adding these lines to the end of /etc/pacman.conf
[selinux] Server = https://github.com/archlinuxhardened/selinux/releases/download/ArchLinux-SELinux SigLevel = PackageOptional
Install essential packages
- Without SELinux:
# pacstrap -K /mnt base base-devel linux linux-firmware man-db vim dosfstools e2fsprogs btrfs-progs cpu_manufacturer-ucode
- With SELinux: replace
base
andbase-devel
withbase-selinux
andbase-devel-selinux
. Also add archlinux-keyring to the list:# pacstrap -K /mnt base-selinux base-devel-selinux linux linux-firmware man-db vim dosfstools e2fsprogs btrfs-progs archlinux-keyring cpu_manufacturer-ucode
- The base-selinuxAUR depends selinux-refpolicy-archAUR, no need to install extra policy.
Replace cpu_manufacturer-ucode
with amd-ucode
or intel-ucode
depends on the CPU manufacturer.
Configure the system
Fstab
Generate an fstab
# genfstab -U /mnt >> /mnt/etc/fstab
Remove all subvolid=
options in fstab
/mnt/etc/fstab
# <file system> <dir> <type> <options> <dump> <pass> # /dev/mapper/cryptroot UUID=xxxx / btrfs rw,noatime,compress=zstd:1,ssd,space_cache=v2,autodefrag,subvolid=256,subvol=/@ 0 0 # /dev/sdX1 UUID=xxxx /efi vfat ... # /dev/mapper/cryptroot UUID=xxxx /home btrfs rw,noatime,compress=zstd:1,ssd,space_cache=v2,autodefrag,subvolid=257,subvol=/@home 0 0 ... # /dev/sdX3 UUID=xxxx none swap defaults 0 0
You can run this command remove all subvolid
options
# sed -i 's/subvolid=[0-9]*,//g' /mnt/etc/fstab
This is helpful because you do not need to edit fstab file after restoring root partition to its previous snapshot.
Chroot
# arch-chroot /mnt # export PS1="(chroot) ${PS1}"
Time zone
(chroot) # ln -sf /usr/share/zoneinfo/Region/City /etc/localtime (chroot) # hwclock --systohc
Localization
Uncomment en_US.UTF-8 UTF-8
in /etc/locale.gen
, then
(chroot) # locale-gen
Create /etc/locale.conf
and /etc/vconsole.conf
(chroot) # echo "LANG=en_US.UTF-8" > /etc/locale.conf (chroot) # echo "KEYMAP=us" > /etc/vconsole.conf
Network configuration
Hostname
(chroot) # echo archlinux > /etc/hostname
Creating the /etc/resolv.conf
symlink need to be done outside of chroot environment.
(chroot) # exit # ln -sf /run/systemd/resolve/stub-resolv.conf /mnt/etc/resolv.conf # arch-chroot /mnt # export PS1="(chroot) ${PS1}"
Choose only one network manager.
- systemd-networkd is my preferred choice for devices that only need wired connection. iwd works well for WPA-Personal WiFi, but not easy to configure for the WPA-Enterprise WiFi.
- NetworkManager with wpa_supplicant for devices need wireless connection.
systemd-networkd
Create configuration file
/etc/systemd/network/20-ethernet.network
[Match] Name=en* Name=eth* [Network] DHCP=yes IPv6PrivacyExtensions=yes
Enable systemd-resolved.service
and systemd-networkd.service
.
NetworkManager
Install networkmanager and wpa_supplicant.
Then enable systemd-resolved.service
, NetworkManager.service
and wpa_supplicant.service
.
Disk encryption
Configure mkinitcpio
A configuration with systemd-based initramfs using sd-encrypt
would looks similar to
/etc/mkinitcpio.conf
... HOOKS=(base systemd keyboard autodetect modconf kms sd-vconsole block sd-encrypt filesystems fsck) ...
Create /etc/crypttab.initramfs
/etc/crypttab.initramfs
cryptroot UUID=ROOT_UUID - password-echo=no,x-systemd.device-timeout=0,timeout=0,no-read-workqueue,no-write-workqueue,discard
You can get ROOT_UUID
with command lsblk -dno UUID /dev/sdX2
. The no-read-workqueue,no-write-workqueue,discard
options at the end is for SSD, see dm-crypt/Specialties#Disable workqueue for increased solid state drive (SSD) performance and dm-crypt/Specialties#Discard/TRIM support for solid state drives (SSD).
Swap encryption
To use UUID instead of /dev/sdX3
in the /etc/crypttab
, we need to create a small 1MiB sized filesystem at /dev/sdX3
, see dm-crypt/Swap encryption#UUID and LABEL.
First deactivate swap partition
(chroot) # swapoff /dev/sdX3
Then create a 1MiB ext2 filesystem with label cryptswap
(chroot) # mkfs.ext2 -F -F -L cryptswap /dev/sdX3 1M
Add /etc/crypttab
entry
/etc/crypttab
# <name> <device> <password> <options> cryptswap UUID=SWAP_UUID /dev/urandom swap,offset=2048
Get SWAP_UUID with command lsblk -dno UUID /dev/sdX3
.
The option offset
is the start offset in 512-byte sectors. So 2048 of 512 bytes is 1MiB.
Edit the swap entry in /etc/fstab
, change UUID=xxxx
to /dev/mapper/cryptswap
/etc/fstab
# <filesystem> <dir> <type> <options> <dump> <pass> /dev/mapper/swap none swap defaults 0 0
Unified kernel image
Kernel command line
Create /etc/kernel/cmdline
and /etc/kernel/cmdline_fallback
file, which will contains kernel parameters for the unified kernel image. Fallback images would use cmdline_fallback
as kernel parameters. You could have different kernel parameters for fallback images.
/etc/kernel/cmdline
root=/dev/mapper/cryptroot rootfstype=btrfs rootflags=subvol=/@ rw modprobe.blacklist=pcspkr
/etc/kernel/cmdline_fallback
root=/dev/mapper/cryptroot rootfstype=btrfs rootflags=subvol=/@ rw modprobe.blacklist=pcspkr
modprobe.blacklist=pcspkr
disable the PC speaker (or beeper) globally, see PC speaker#Disabling the PC speaker.
If SELinux enabled also add lsm=landlock,lockdown,yama,integrity,selinux,bpf
to the end.
Modify .preset file
Edit all .preset
files for the kernels you installed, eg. linux.preset
, linux-zen.preset
, linux-lts.preset
etc.
- Add line
ALL_microcode=(/boot/*-ucode.img)
- Add
default_uki=
andfallback_uki=
- Optionally, comment out
default_image=
andfallback_imag=
- Optionally, add Arch splash screen by appending
--splash
todefault_options=
/etc/mkinitcpio.d/linux.preset
# mkinitcpio preset file for the 'linux' package ALL_config="/etc/mkinitcpio.conf" ALL_kver="/boot/vmlinuz-linux" ALL_microcode=(/boot/*-ucode.img) PRESETS=('default' 'fallback') #default_config="/etc/mkinitcpio.conf" #default_image="/boot/initramfs-linux.img" default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp" default_uki="/efi/EFI/Linux/Archlinux-linux.efi" #fallback_config="/etc/mkinitcpio.conf" #fallback_image="/boot/initramfs-linux-fallback.img" fallback_options="-S autodetect --cmdline /etc/kernel/cmdline_fallback" fallback_uki="/efi/EFI/Linux/Archlinux-linux-fallback.efi"
If installed linux-zen kernel then linux-zen.preset
would looks like
/etc/mkinitcpio.d/linux-zen.preset
# mkinitcpio preset file for the 'linux-zen' package ALL_config="/etc/mkinitcpio.conf" ALL_kver="/boot/vmlinuz-linux-zen" ALL_microcode=(/boot/*-ucode.img) PRESETS=('default' 'fallback') #default_config="/etc/mkinitcpio.conf" #default_image="/boot/initramfs-linux-zen.img" default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp" default_uki="/efi/EFI/Linux/Archlinux-linux-zen.efi" #fallback_config="/etc/mkinitcpio.conf" #fallback_image="/boot/initramfs-linux-zen-fallback.img" fallback_options="-S autodetect --cmdline /etc/kernel/cmdline_fallback" fallback_uki="/efi/EFI/Linux/Archlinux-linux-zen-fallback.efi"
This will generate unified kernel image Archlinux-linux.efi
.
Finally regenerate the initramfs
(chroot) # mkinitcpio -P
and remove any leftover initramfs-*.img
from /boot
or /efi
.
Secure boot
Create keys
(chroot) # sbctl create-keys
Enroll keys
If you don't want to enroll Microsoft key run
(chroot) # sbctl enroll-keys
If you want to enroll Microsoft key run
(chroot) # sbctl enroll-keys --microsoft
- If
sbctl
saysYou need to chattr -i files in efivarfs
, first run(chroot) # chattr -i /sys/firmware/efi/efivars/{PK,KEK,db}*
then enroll key again. - If running libvirt virtual machine, you may add
--yes-this-might-brick-my-machine
to force enroll keys.
Sign unified kernel image
Sign all unified kernel images
(chroot) # sbctl sign --save /efi/EFI/Linux/ArchLinux-linux.efi (chroot) # sbctl sign --save /efi/EFI/Linux/ArchLinux-linux-fallback.efi
If installed linux-zen, you also need to sign those images
(chroot) # sbctl sign --save /efi/EFI/Linux/ArchLinux-linux-zen.efi (chroot) # sbctl sign --save /efi/EFI/Linux/ArchLinux-linux-zen-fallback.efi
This will replace old unsigned images with new signed ones.
.preset
file regenerate the initramfs. Then sign the unified kernel images and add UEFI boot entries. Finally run sbctl sign-all
since you regenerated initramfs.UEFI boot entries
For linux kernel
(chroot) # efibootmgr --create --disk /dev/sdX --part 1 --label "ArchLinux-linux" --loader "EFI\\Linux\\ArchLinux-linux.efi" (chroot) # efibootmgr --create --disk /dev/sdX --part 1 --label "ArchLinux-linux-fallback" --loader "EFI\\Linux\\ArchLinux-linux-fallback.efi"
--disk
is the disk containing boot loader do not include part number, it is /dev/sdX
not /dev/sdX1
.
The --part
specify the partition number.
If the EFI partition is /dev/sdX2
then it is --disk /dev/sdX --part 2
.
If you install linux-zen kernel also need to add them to boot entry, for example
(chroot) # efibootmgr --create --disk /dev/sdX --part 1 --label "ArchLinux-linux-zen" --loader "EFI\\Linux\\ArchLinux-linux-zen.efi" (chroot) # efibootmgr --create --disk /dev/sdX --part 1 --label "ArchLinux-linux-zen-fallback" --loader "EFI\\Linux\\ArchLinux-linux-zen-fallback.efi"
Change the boot order, for example I want first boot entry 0003 then 0004, then 0005, run
(chroot) # efibootmgr --bootorder 0003,0004,0005
Set root password
(chroot) # passwd
Reboot into BIOS
(chroot) # exit # umount -R /mnt # systemctl reboot --firmware-setup
- Now you can enable Secure Boot (also called User Mode) in the BIOS. Some motherboard manufacture will automatically change to User Mode if you enrolled your own key.
- Then set a BIOS password.
- Now finger crossed and boot into your new system.
Post-installation
SELinux#Post-installation steps
Label your filesystem
# restorecon -r / # systemctl reboot
Check SELinux Status:
# sestatus
It should be permissive mode. To temporary switch to enforcing mode
# echo 1 > /sys/fs/selinux/enforce
Or edit /etc/selinux/config
to switch permanently.
Enable restorecond.service
to maintain correct context.
systemd-homed
From Lennart Poettering's blog:
- It (systemd-homed) also allows us to correct another major issue with traditional Linux systems: the way how data encryption works during system suspend. Traditionally on Linux the disk encryption credentials (e.g. LUKS passphrase) is kept in memory also when the system is suspended. This is a bad choice for security, since many (most?) of us probably never turn off their laptop but suspend it instead. But if the decryption key is always present in unencrypted form during the suspended time, then it could potentially be read from there by a sufficiently equipped attacker.
In other words, my data is still safe even if I leave my laptop suspended in a hotel. In my humble opinion, systemd-homed does not provide much benefits for server or single user desktop use cases. Also it needs extra configuration if running SSH server, see systemd-homed#SSH remote unlocking.
If you want to add a user using systemd-homed keep reading this section, otherwise follow Users and groups#User management.
Start and enable systemd-homed.service
.
# homectl create tux --uid=1000 --member-of=wheel --shell=/bin/bash --storage=luks --fs-type=btrfs
Will add user tux
with UID=1000
and a member of wheel
group.
Its home directory is a encrypted LUKS volume, and the filesystem is btrfs.
Disable root login
# passwd -d root # passwd -l root
Time servers
/etc/systemd/timesyncd.conf
[Time] NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org FallbackNTP=0.pool.ntp.org 1.pool.ntp.org 0.fr.pool.ntp.org
Then start and enable systemd-timesyncd.service
Pacman#Enabling parallel downloads
Uncomment ParallelDownloads
in /etc/pacman.conf
.
reflector
Install the reflector package.
/etc/xdg/reflector/reflector.conf
--save /etc/pacman.d/mirrorlist --protocol https --country us --latest 5 --sort age
Enable reflector.service
and reflector.timer
.
Pacman#Cleaning the package cache
Install the pacman-contrib package. Enable paccache.timer
.
Solid state drive#Periodic TRIM
Enable fstrim.timer
.
Optimize AUR building
Remove any -march
and -mtune
CFLAGS, then add -march=native
in /etc/makepkg.conf
.
/etc/makepkg.conf
CFLAGS="-march=native -O2 -pipe ..."
Add -C target-cpu=native
to RUSTFLAGS:
/etc/makepkg.conf
RUSTFLAGS="-C opt-level=2 -C target-cpu=native"
/etc/makepkg.conf
MAKEFLAGS="-j$(nproc)"
firewall
Install the firewalld package. Start and enable firewalld.service
.
Snapper
I want to use systemd manage snapshots instead of cron.
Uncomment NoExtract
in /etc/pacman.conf
/etc/pacman.conf
NoExtract = etc/cron.daily/snapper etc/cron.hourly/snapper
Follow Snapper#Configuration of snapper and mount point suggestion create configuration for /
.
Unmount and remove existing /.snapshots
# umount /.snapshots # rm -r /.snapshots
Create a new config for /
named root
.
# snapper -c root create-config /
Delete the subvolume created by snapper, and recreate the directory
# btrfs subvolume delete /.snapshots # mkdir /.snapshots
Remount @snapshots
to /.snapshots
and set right permission.
# mount -a # chmod -R 750 /.snapshots
Create new config for /home
# snapper -c home create-config /home
systemd-homed
create a config for /home/tux
instead. /home
only contains encrypted volumes.Edit /etc/snapper/configs/root
and /etc/snapper/configs/home
TIMELINE_CREATE="yes" TIMELINE_CLEANUP="yes" NUMBER_MIN_AGE="1800" NUMBER_LIMIT="10" NUMBER_LIMIT_IMPORTANT="10" TIMELINE_MIN_AGE="1800" TIMELINE_LIMIT_HOURLY="5" TIMELINE_LIMIT_DAILY="7" TIMELINE_LIMIT_WEEKLY="0" TIMELINE_LIMIT_MONTHLY="0" TIMELINE_LIMIT_YEARLY="0"
Enable snapper-timeline.timer
and snapper-cleanup.timer
.
Install the snap-pac and rsync packages to create snapshot on pacman transactions.
Create this pacman hook to backup /efi
directory.
/etc/pacman.d/hooks/zz-signed_uki_backup.hook
[Trigger] Operation = Upgrade Operation = Install Operation = Remove Type = Package Target = * [Action] Depends = rsync Description = Backing up /efi... When = PostTransaction Exec = /usr/bin/rsync --archive --delete /efi/ /.efibackup
Pacman post transaction backup:
- New unified kernel images are generated in
/efi/EFI/Linux/
. Thenzz-sbctl.hook
from the sbctl package will sign and replace these unsigned kernel images. Then thiszz-signed_uki_backup.hook
will copy/efi
directory to/.efibackup
. Finally,zz-snap-pac-post.hook
from the snap-pac package will snapshot/
.
Pacman pre transaction backup:
05-snap-pac-pre.hook
from snap-pac snapshot/
before pacman transaction./.efibackup
contains old signed kernel images.
snapper rollback
, but is intended to alleviate the inherent problems of #Restoring / to its previous snapshot. See this this forum thread. To rollback you need to temporary disable secure boot and boot into Arch ISO, then manually restore snapshot.To restore /
, see snapper#Restoring / to its previous snapshot.
Restore dotfiles from a Git bare repository
Clone your dotfiles repository
$ git clone --bare dotfiles-repo-url $HOME/.dotfiles $ alias dotfiles='/usr/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
Checkout the repository
$ dotfiles checkout
It may show an error of conflicting files that already exist in your home directory would be overwritten. Since this is fresh installed system, we simply delete them. Or run this command then checkout again
$ dotfiles checkout 2>&1 | egrep "\s+\." | awk {'print $1'} | xargs -I{} rm {} $ dotfiles checkout
If using GitHub change the remote url to use SSH key
~/.dotfiles/config
... [remote "origin"] url = git@github.com:username/dotfiles.git ...
Install the openssh package or openssh-selinuxAUR if using SELinux. Generate new SSH keys#Ed25519 pairs
$ ssh-keygen -t ed25519
After installed Graphical user interface upload your new SSH key to GitHub. Now you can push to your Git repository with
$ dotfiles push
Zsh
Install the zsh, zsh-completions, zsh-syntax-highlighting, zsh-autosuggestions and grml-zsh-config packages, which provides the same setup as the Arch ISO release.
To have Fish-like syntax highlighting and autosuggestions, add these lines to your .zshrc
:
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
To make Zsh your default shell
$ chsh -s /usr/bin/zsh
or if you are using systemd-homed
# homectl update --shell=/usr/bin/zsh tux