My notes with the steps to install Arch Linux with encrypted BTRFS (LUKS2) and GRUB.
If you stumbled upon this document looking for a guide to install Arch Linux, I recommend checking the official installation guide on the Arch Linux Wiki: https://wiki.archlinux.org/title/Installation_guide. This is not a guide, just some notes that I'm taking while trying this setup and getting fragments of information from the internet.
If you want to try this steps... Well, it worked for me, but I'm not responsible for any damage that you may cause to your system.
- Arch install with encrypted BTRFS (LUKS2), GRUB e AwesomeWM
- Table of contents
- Download and boot
- Adjusts during installation
- Preparing the disks
- Installing Arch Linux
- Installing GRUB
- Post-install Tweaks
- Installing AwesomeWM
- BTRFS snapshots
- Customizations
- References
Download and write the official Arch Linux ISO to a USB stick.
Usually I have a usb stick with ventoy and multiple ISOs, but if I want to write only the Arch Linux ISO to a USB stick, I use usbimager.
It may be necessary to disable secure boot in the BIOS.
- Official Arch Linux website download page:
- Ventoy:
- USBImager:
- Secure boot info on Arch Wiki:
I recommend using tmux
so you can see long outputs and split the terminal if
needed.
br-abnt2: Brazilian ABNT2 us: US us-acentos: US international
# PT BR ABNT2
loadkeys br-abnt2
br-abnt2: Brazilian ABNT2 us: US us-acentos: US international
# List available keymaps
localectl list-keymaps
# Set BR ABNT2
localectl set-keymap us-acentos
The font may be to small during the installation.
Changing installation font (reddit + arch wiki):
# List available fonts
ls /usr/share/kbd/consolefonts/
# Change to another font (my recomendation: ter-132n)
setfont ter-132n
If you are using UEFI, the directory /sys/firmware/efi/efivars
should exist.
# If the directory does not exist, the system is booted in BIOS mode
ls /sys/firmware/efi/efivars
If you are using Wi-Fi, execute iwctl
and the following commands:
device list # list the devices
station <wlan> scan # scan for networks
station <wlan> get-networks # list the networks
station <wlan> connect <SSID> # connect to the network
ps: you can test the connection with ping archlinux.org
.
I will delete all partitions on the disk and create new ones. If you have data on the disk, backup it before continuing or adjust the steps to keep the data.
Use fdisk
to partition the disk.
# Start the fdisk interactive mode (for the example, it will be "/dev/sda" disk)
fdisk /dev/sda
# List all partitions
p
# Create a new GPT partition layout (this will erase all data on the disk)
g
# Create a new partition (partition for EFI)
# 500M should be enough, however, I prefer to use 1G to be sure
n
> Partition number (1-128, default 1): # use default
> First sector (2048-1048575966, default 2048): # use default
> Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1048575966, default 1048575966): +1G
# Set the type EFI
t
> Partition type or alias (type L to list all): 1 # EFI
# Create a second partition (partition for /boot (grub))
# 500M should be enough here too
n
> Partition number (2-128, default 2): # use default
> First sector (1026048-1048575966, default 1026048): # use default
> Last sector, +/-sectors or +/-size{K,M,G,T,P} (1026048-1048575966, default 1048575966): +1G
# (Optional) Create a swap partition
# 8G should be fine for most cases
n
> Partition number (3-128, default 3): # use default
> First sector (2050048-1048575966, default 2050048): # use default
> Last sector, +/-sectors or +/-size{K,M,G,T,P} (2050048-1048575966, default 1048575966): +8G
# Set the type SWAP
t
> Partition type or alias (type L to list all): swap # Linux swap
# Change partition name to cryptoswap
# Enter extra functionality mode
x
# Change the partition name
n
Partition number (1-3, default 3): 3
New name: cryptswap
# Return to the main menu
r
# Create a fourth partition (partition for /)
n
> Partition number (4-128, default 4): # use default
> First sector (10242048-1048575966, default 10242048): # use default
> Last sector, +/-sectors or +/-size{K,M,G,T,P} (10242048-1048575966, default 1048575966): # use default
# Change the partition name
n
Partition number (1-4, default 4): 4
New name: cryptsystem
# Return to the main menu
r
# Check partitions, should have two 1G partitions, one 8G partition and one
# partition with the remaining space. The first partition should be EFI, the
# second and fourth should be Linux filesystem and the third should be SWAP
p
# Write the partition table and exit fdisk
w
# List disks (should be same output as we got before in the fdisk prompt (when
# used the command "p" before "w"))
fdisk -l
# Encrypt the root partition
cryptsetup luksFormat --type=luks2 /dev/sda4
# Open the encrypted partition
cryptsetup open --type=luks2 /dev/sda4 system
# Open swap as crypt device
cryptsetup open --type plain --key-file /dev/urandom /dev/sda3 swap
# Format the swap partition
mkswap -L swap /dev/mapper/swap
# Enable the swap partition
swapon -L swap
# Create the EFI filesystem
mkfs.fat -F32 /dev/sda1
# Create the /boot filesystem
mkfs.ext4 /dev/sda2
# Create the root filesystem
# mkfs.btrfs /dev/mapper/system
mkfs.btrfs -L system /dev/mapper/system
# Mount the root filesystem
mount -t btrfs LABEL=system /mnt
# Create the root subvolume
btrfs subvolume create /mnt/@root
# Create the home subvolume
btrfs subvolume create /mnt/@home
# Create the var subvolume
btrfs subvolume create /mnt/@var
# Create the tmp subvolume
btrfs subvolume create /mnt/@tmp
# Create the snapshots subvolume
btrfs subvolume create /mnt/@snapshots
# Unmount the root filesystem
umount -R /mnt
# Mount the root subvolume
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@root LABEL=system /mnt
# Mount the snapshots subvolume
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@snapshots LABEL=system /mnt/.snapshots
# Mount the var subvolume
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@var LABEL=system /mnt/var
# Mount the tmp subvolume
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@tmp LABEL=system /mnt/tmp
# Mount the home subvolume
mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,subvol=@home LABEL=system /mnt/home
# Mount the boot partition
mkdir /mnt/boot
mount /dev/sda2 /mnt/boot
Create the fstab with the current mount points:
# Creating etc directory
mkdir /mnt/etc
# Generating fstab file
genfstab -U -p /mnt >> /mnt/etc/fstab
Install base packages for Arch Linux:
# Install only the base packages
pacstrap /mnt base
Configure crypttab to encrypt the swap partition:
# Get PARTUUID of the swap partition (remember that /dev/sda3 is the swap partition)
blkid /dev/sda3
# Open the crypttab file
nvim /mnt/etc/crypttab
# Add the swap partition to the crypttab file
swap PARTUUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /dev/urandom swap,offset=2048,cipher=aes-xts-plain64,size=256
Verify if swap is correct in fstab:
# /dev/mapper/swap LABEL=swap
/dev/mapper/swap none swap defaults 0 0
Observation: although I'm using UUID for most things, the swap partition I was
only able to make it work with the /dev/mapper/swap
path.
Configure installation through chroot environment:
# Attach to work in progress installation in chroot environment
arch-chroot /mnt
# linux linux-headers: install kernel latest and lts
# linux-firmware: firmware for the kernel
# nvim: a text editor (nvim, vim, neovim...)
# base-devel is a group of development packages that is often needed
# openssh allows you to use ssh to manage the installation remotely
# networkmanager: network support and wifi support
# btrfs, lvm, ntfs-3g: support to filesystems
# zsh: my preferred shell
pacman -S linux linux-headers \
linux-lts linux-lts-headers \
mkinitcpio \
linux-firmware \
neovim \
base-devel openssh \
networkmanager \
btrfs-progs lvm2 ntfs-3g \
zsh zsh-completions
# Enabling ssh service (if you want to manage the installation remotely)
systemctl enable sshd
# Enabling network manager
systemctl enable NetworkManager
Edit the mkinitcpio configuration (/etc/mkinitcpio.conf
) file to add encrypt
and btrfs
to the HOOKS
array (before filesystems
):
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt btrfs filesystems fsck)
Generate the initramfs:
mkinitcpio -P
Edit the /etc/locale.gen and uncomment the desired locales.
...
#en_SG.UTF-8 UTF-8
#en_SG ISO-8859-1
en_US.UTF-8 UTF-8
#en_US ISO-8859-1
#en_ZA.UTF-8 UTF-8
...
#pl_PL ISO-8859-2
#ps_AF UTF-8
pt_BR.UTF-8 UTF-8
#pt_BR ISO-8859-1
#pt_PT.UTF-8 UTF-8
...
Generate the locales:
locale-gen
# execute as root user...
passwd
useradd -m -U -G wheel,users --shell /usr/bin/zsh <user_name>
passwd <user_name>
pacman -S sudo
Open the sudoers file using visudo, you can force nvim putting EDITOR=nvim in front of the visudo command:
# Open sudoers file in nvim
EDITOR=nvim visudo
Uncomment the line %wheel ALL=(ALL) ALL
and save the file:
## Uncomment to allow member of group wheel to execute any command
%wheel ALL=(ALL) ALL
Install GRUB, tools and UEFI support:
pacman -S grub grub-btrfs efibootmgr dosfstools os-prober mtools
Creating EFI directory for GRUB and mounting the EFI partition on the new directory:
# Creating EFI directory
mkdir /boot/EFI
# Mounting first partition on /boot/EFI (remember to check the partition, it
# should be the EFI partition, in this case, /dev/sda1)
mount /dev/sda1 /boot/EFI
Installing GRUB on the master boot record:
grub-install --target=x86_64-efi --bootloader-id=grub_uefi --recheck
Setting GRUB locale/language (1:24:02):
# Check if locale folder exists in /boot/grub
ls -l /boot/grub
# If it doesn't exist, create it
mkdir /boot/grub/locale
# Copy grub locale file from /usr/share/locale to /boot/grub/locale
cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale/en.mo
Edit the /etc/default/grub
file to add/set the encryption settings:
# Opening default grub config file with nvim
nvim /etc/default/grub
Uncomment the line GRUB_ENABLE_CRYPTODISK=y
:
# Uncomment to enable booting from LUKS encrypted disks
GRUB_ENABLE_CRYPTODISK=y
If you want that grub search for other operational systems, you can also
uncomment the line GRUB_DISABLE_OS_PROBER=false
:
GRUB_DISABLE_OS_PROBER=false
If you want that grub remember the last selected entry, you can also uncomment
the line GRUB_SAVEDEFAULT=true
and change the line GRUB_DEFAULT=0
to
GRUB_DEFAULT=saved
:
...
GRUB_DEFAULT=saved
...
GRUB_SAVEDEFAULT=true
...
Edit the line with GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"
adding the
parameters
cryptdevice=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX:system:allow-discards
before the "loglevel" (UUID is the one from the encrypted partition):
# get the UUID of the encrypted partition
blkid /dev/sda4
# Example:
GRUB_CMDLINE_LINUX_DEFAULT="cryptdevice=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX:system:allow-discards loglevel=3 quiet"
Generate the grub configuration file:
grub-mkconfig -o /boot/grub/grub.cfg
Exiting chroot and rebooting:
# Exiting chroot
exit
# Unmounting all partitions
umount -a
# Reboot the system
reboot
Boot the system and log as the user that was created.
Most commands require root privileges, so you can use sudo
before each command
or use su
to become root.
su
# Check for available timezones
timedatectl list-timezones
# Set timezone to your location (America/Sao_Paulo for me)
timedatectl set-timezone America/Sao_Paulo
Enabling systemd-timesyncd service so that the system syncs the time at start
# Sync time at start
systemctl enable systemd-timesyncd
# File /etc/hostname probably doesn't exists yet
cat /etc/hostname
# Set hostname as a name of your choice
hostnamectl set-hostname <hostname>
# Now the file /etc/hostname was generated
cat /etc/hostname
Open the file /etc/hosts
:
nvim /etc/hosts
Add the following lines to the file:
127.0.0.1 localhost
127.0.1.1 <hostname>
Observation: Use the name chosen as hostname instead of <hostname>
.
Install micro code for AMD or Intel CPU so that the system can take advantage of the latest CPU features and security updates.
For AMD CPU:
pacman -S amd-ucode
For Intel CPU:
pacman -S intel-ucode
Install xorg and gpu drivers (no wayland yet... I like awesome wm too much and I am too lazy to update my config and scripts to work with wayland):
# If you have an intel or amd GPU, install the mesa package
pacman -S mesa
# If you have a nvidia GPU, install the nvidia or nvidia-lts packages (or both)
pacman -S nvidia nvidia-lts
# Installing xorg
pacman -S xorg-server
Enabling multilib (required for some packages, like steam
for example)
(arch wiki reference):
Uncomment section [multilib]
in /etc/pacman.conf
:
[multilib]
Include = /etc/pacman.d/mirrolist
# Enable this option to enable parallel downloads
ParallelDownloads = 5
# Enable this option to enable color output
Color
# Add this secret option to make pacman output more visually appealing
ILoveCandy
Yay is a wrapper for pacman that allows you to install packages from the AUR. The syntax is similar to pacman, so it's easy to use.
Obs.: Use those commands as normal user, not as root.
# Essential dependencies
pacman -S base-devel git
# Clone yay repository
git clone https://aur.archlinux.org/yay.git
# Enter the directory
cd yay
# Build and install the package
# Observation: in the guide, he uses only `makepkg -s`, but for me it only works with `makepkg -si`
makepkg -si
Activating numlock at early boot (if the password has numbers, it can be useful) (arch wiki reference):
# Install AUR package mkinitcpio-numlock
yay -S mkinitcpio-numlock
# Edit the file `/etc/mkinitcpio.conf`
nvim /etc/mkinitcpio.conf
In the line HOOKS=(...
move keyboard
to before modconf
, and add keymap
,
consolefont
and numlock
after keyboard. Example:
HOOKS=(base udev autodetect keyboard keymap consolefont numlock modconf block encrypt btrfs filesystems fsck)
My locale.conf file with fallback (arch wiki reference):
LANG="en_US.UTF-8"
LANGUAGE="en_US:en:C:pt_BR"
LC_ADDRESS="pt_BR.UTF-8"
LC_COLLATE="pt_BR.UTF-8"
LC_CTYPE="pt_BR.UTF-8"
LC_IDENTIFICATION="pt_BR.UTF-8"
LC_MEASUREMENT="pt_BR.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="pt_BR.UTF-8"
LC_NAME="pt_BR.UTF-8"
LC_NUMERIC="pt_BR.UTF-8"
LC_PAPER="pt_BR.UTF-8"
LC_TELEPHONE="pt_BR.UTF-8"
LC_TIME="pt_BR.UTF-8"
Edit the /etc/security/pam_env.conf
to set the XDG directories:
Add the following lines to the file:
XDG_CONFIG_HOME DEFAULT=@{HOME}/.config
XDG_DATA_HOME DEFAULT=@{HOME}/.local/share
XDG_STATE_HOME DEFAULT=@{HOME}/.local/state
XDG_CACHE_HOME DEFAULT=@{HOME}/.cache
ps: Some directories may not exist yet, so use mkdir
just in case.
mkdir -p ~/.config
mkdir -p ~/.local/share
mkdir -p ~/.local/state
mkdir -p ~/.cache
Edit the /etc/zsh/zshenv
to set the ZDOTDIR:
Add the following lines to the file:
ZDOTDIR=$HOME/.config/zsh
Install awesome wm package
pacman -S awesome
Copy the default configuration to the user directory:
mkdir ~/.config/awesome
cp /etc/xdg/awesome/rc.lua ~/.config/awesome/rc.lua
Edit the rc.lua
file to set the default terminal emulator to alacritty:
nvim ~/.config/awesome/rc.lua
Find the line terminal = "xterm"
and change it to terminal = "alacritty"
.
Install a login manager (I use lightdm) and a terminal emulator (I use alacritty):
pacman -S lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings
Enable the lightdm service:
systemctl enable lightdm
Firefox: web browser PCManFM: file manager Alacritty: terminal emulator PipeWire: audio server
pacman -S firefox pcmanfm-gtk3 alacritty pipewire pipewire-pulse pipewire-jack
Enable user services for pipewire:
systemctl --user enable pipewire
systemctl --user enable pipewire-pulse
sudo setxkbmap -layout br -variant abnt2
pacman -S flatpak xdg-desktop-portal xdg-desktop-portal-gtk
btrfs subvolume snapshot / /.snapshots/@clean-install
Create a pacman hook to create a snapshot before and after a system upgrade (arch wiki reference):
# Create the directory for the pacman hooks
mkdir /etc/pacman.d/hooks
# Create the file for the pacman hook
nvim /etc/pacman.d/hooks/90-btrfs-snapshot.hook
Add the following lines to the file:
[Trigger]
Type = Package
Operation = Install
Operation = Upgrade
Operation = Remove
Target = linux
Target = linux-lts
Target = nvidia
Target = nvidia-lts
Target = intel-ucode
Target = grub
[Action]
Description = Creating BTRFS snapshot before system upgrade
When = PreTransaction
Exec = /usr/bin/bash -c '/usr/bin/btrfs subvolume snapshot / /.snapshots/@root-snapshot-$(date +%Y-%m-%d-%H-%M)'
AbortOnFail
Create another pacman hook to update the grub configuration file after a system upgrade:
# Create the file for the pacman hook
nvim /etc/pacman.d/hooks/91-grub-mkconfig.hook
Add the following lines to the file:
[Trigger]
Type = Package
Operation = Install
Operation = Upgrade
Operation = Remove
Target = linux
Target = linux-lts
Target = nvidia
Target = nvidia-lts
Target = intel-ucode
Target = grub
[Action]
Description = Update grub cfg so it can boot from new snapshots
When = PostTransaction
Exec = /usr/bin/bash -c '/usr/bin/grub-mkconfig -o /boot/grub/grub.cfg'
Very important! I never actually needed this, I just tested once to see if it worked, but I never had to use it in practice and I'm not sure if this is the correct way to do it...
-
Boot from a snapshot using grub-btrfs.
-
Do the following steps:
# list btrfs subvolumes
btrfs subvolume list /
# boot the desired snapshot to restore
mount -t btrfs -o subvolid=<subvol_id> /dev/mapper/system /mnt
# to check mounted btfrs subvolumes you can use findmnt
findmnt -t btrfs
# edit the fstab file to change the id of the root subvolume
nvim /mnt/etc/fstab
# UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / btrfs rs,noatime,compress=zstd,ssd,space_cache,subvolid=256,subvol=@root 0 0
# =>
# UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / btrfs rs,noatime,compress=zstd,ssd,space_cache,subvolid=<NEW_ID>,subvol=@root 0 0
# Unmount the root filesystem
umount -R /mnt
# mount subvolid 5 in some directory
mount -t btrfs -o subvolid=5 /dev/mapper/system /mnt
# go to the mounted directory
cd /mnt
# rename @root to @root.bak
mv @root @root.bak
# rename @snapshots/@root-snapshot-2021-09-01-00-00 to @root
mv @snapshots/@root-snapshot-2021-09-01-00-00 @root
# umount the filesystem
umount /mnt
reboot
This is a simple install, it is a good idea to give a look into archwiki "General recommendations" and archwiki "Improving performance".
Besides that, now it is just a matter of customizing the system to your needs. :)
- Most of what I know came from the "arch linux installation guides" from Learn Linux TV and the Arch Linux Wiki.
- While researching some steps that I didn't remember from the last time I installed arch like this, I found the following guide User:ZachHilman/Installation - Btrfs + LUKS2 + Secure Boot, which has some cool steps that I hadn't done before, like encrypting the swap partition, so I ended up using it as a reference for some steps.
- My old notes (it is kinda outdated, but I believe it still works): Arch install with UEFI and Encryption