If you are looking to install Arch Linux the secure way, you have come to the right place. This step-by-step tutorial walks you through a robust, hardened setup featuring UEFI, LUKS full-disk encryption, LVM, Btrfs, GRUB, and Secure Boot.
Why this combination? LUKS ensures your data remains completely inaccessible to thieves, LVM gives you flexible partition management, Btrfs allows for easy system snapshots, and Secure Boot ensures only trusted code runs during startup.
Step 1: Connect to a Wi-Fi Network #
Arch Linux requires an active internet connection to download base packages. We will use iwctl to connect.
# iwctl
[iwd]# device list
[iwd]# device deviceName set-property Powered on
[iwd]# station deviceName scan
[iwd]# station deviceName get-networks
[iwd]# station deviceName connect SSID
[iwd]# exit
Ensure you are successfully connected by pinging the Arch Linux servers:
$ ping archlinux.org
Step 2: Check System Time #
Ensure your system clock is accurate to prevent cryptographic and network errors during package installation.
$ timedatectl
Step 3: Partition Disks #
Create Partitions using fdisk
- Check available disks:
# fdisk -l
- Enter fdisk:
# fdisk /dev/sdX
- Create a new GPT disk label:
Command (m for help): g
Created a new GPT disklabel (GUID: ...).
- Create the EFI boot partition (512M):
Command (m for help): n
Partition number:
First sector:
Last sector, +/-sectors or +/-size{K,M,G,T,P}: +512M
Command (m for help): t
Partition type or alias (type L to list all): uefi
- Make the remaining space a partition for LUKS:
Command (m for help): n
Partition number:
First sector:
Last sector, +/-sectors or +/-size{K,M,G,T,P}:
- Print partition info to verify
Command (m for help): p
- Write changes to the disk and quit:
Command (m for help): w
(Tip: Type q to quit without writing changes in case of mistakes).
Step 4: Format Boot disk #
# mkfs.fat -F 32 -n EFI /dev/sdXY
Step 5: Setup LUKS Disk Encryption #
We will use LUKS1 to encrypt the root partition, securing your data at rest.
Create LUKS partition #
# cryptsetup --use-random --type luks1 luksFormat /dev/sdXZ
Are you sure? YES
Enter passphrase:
Verify passphrase:
Open LUKS partition #
You can use any name instead of cryptroot, but be sure to replace it everywhere in the following commands.
# cryptsetup open /dev/sdXZ cryptroot
Note #
Once you create LVM, you only need to open the disk with cryptsetup. No additional command is needed to access the volume group (vg)—all existing LVM partitions are accessible right after unlocking the LUKS partition. This is handy if you have to reboot after the LVM setup
Step 6: Setup LVM (Logical Volume Manager) #
LVM allows for flexible resizing of partitions. This step assumes you don’t need a separate home partition on LVM.
Create LVM group #
# pvcreate /dev/mapper/cryptroot
# vgcreate vgroot /dev/mapper/cryptroot
Create LVM Partitions #
Create an 8GB swap partition:
# lvcreate --size 8G vgroot --name swap
Allocate the rest of the space to the root partition:
# lvcreate -l +100%FREE vgroot --name root
Format LVM partitions #
Format the swap volume:
# mkswap /dev/vgroot/swap -L swap
Format the root volume as Btrfs:
# mkfs.btrfs /dev/vgroot/root -L root
Step 7: Create Btrfs Subvolumes #
Btrfs subvolumes allow you to isolate system data from user data and create easy system snapshots.
Mount the Btrfs partition to /mnt (the install target root):
# mount -t btrfs LABEL=root /mnt
Create the required subvolumes one by one:
# btrfs subvolume create /mnt/@
# btrfs subvolume create /mnt/@home
# btrfs subvolume create /mnt/@tmp
# btrfs subvolume create /mnt/@varlog
# btrfs subvolume create /mnt/@snapshots
Disable Copy-on-Write for tmp and varlog to improve performance for highly volatile files:
# chattr +C /mnt/@tmp
# chattr +C /mnt/@varlog
Unmount /mnt:
# umount -R /mnt
Step 8: Mount Partitions #
Mount Btrfs Subvolumes #
We will mount the volumes with specific optimizations. Here is what the options mean:
commit= time interval between data-writes in secondsx-mount.mkdir= make directory if not existing when mountingssd= ssd based btrfs optimisationsnoatime&nodiratime= do not store access time for files/directories (makes btrfs faster)discard= asynchronous queued TRIM to discard freed file blocks
First, check if discard is supported by checking if the output is greater than 0:
# cat /sys/block/sdX/queue/discard_max_bytes
Mount btrfs subvolumes one by one:
# mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,nodiratime,discard=async,space_cache=v2,commit=120,subvol=@ LABEL=root /mnt
# mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,nodiratime,discard=async,space_cache=v2,commit=120,subvol=@home LABEL=root /mnt/home
# mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,nodiratime,discard=async,space_cache=v2,commit=120,subvol=@tmp LABEL=root /mnt/tmp
# mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,nodiratime,discard=async,space_cache=v2,commit=120,subvol=@varlog LABEL=root /mnt/var/log
# mount -t btrfs -o defaults,x-mount.mkdir,compress=zstd,ssd,noatime,nodiratime,discard=async,space_cache=v2,commit=120,subvol=@snapshots LABEL=root /mnt/.snapshots
Mount the EFI Directory #
# mkdir -p /mnt/boot/efi
# mount LABEL=EFI /mnt/boot/efi
Step 9: Setup Mirrorlist Using Reflector #
To ensure maximum download speeds, configure your mirrorlist. Install reflector:
# pacman -Syy reflector
Configure the mirrorlist using reflector:
# reflector --verbose --sort rate --save /etc/pacman.d/mirrorlist
Step 10: Install Base Packages (Pacstrap) #
Install the foundational Linux packages into the mounted root directory.
# pacstrap -K /mnt base linux linux-firmware vim nano
Step 11: Generate Mount Info Fstab #
Generate the fstab file so the system knows how to mount your partitions on boot.
# genfstab -L -p /mnt >> /mnt/etc/fstab
Step 12: Chroot into Installed Environment #
Shift into your newly installed system to configure it.
# arch-chroot /mnt
Step 13: Set Timezone #
Link your local time zone and sync the hardware clock.
# ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
hwclock --systohc
Step 14: Set Locale #
Edit /etc/locale.gen and uncomment your required locales, then generate them:
# locale-gen
Create /etc/locale.conf with content:
LANG=en_US.UTF-8
Step 15: Configure Hostname #
Set the name of your computer.
# echo yourhostname >> /etc/hostname
Step 16: Install Additional Packages #
Install required programs like the shell, development packages, sudo, Btrfs tools, Secure Boot manager, microcode, Bluetooth, Wi-Fi, and your desktop environment (GNOME).
# pacman -Syu base-devel btrfs-progs gptfdisk zsh sudo ttf-dejavu noto-fonts noto-fonts-cjk intel-ucode polkit wpa_supplicant mesa lvm2 efibootmgr bash-completion git man pipewire wireplumber pipewire-alsa pipewire-pulse terminus-font gnome
(If installing GNOME, select pipewire-jack, wireplumber, and noto-fonts-emoji in the proceeding interactive questions).
Step 17: Enable Services #
Enable essential background services to start automatically on boot.
Enable Gnome Display Manager:
# systemctl enable gdm
Enable Network Manager:
# systemctl enable NetworkManager
Enable Bluetooth:
# systemctl enable bluetooth
Step 18: User Management #
Running as the root user is dangerous. Set a root password and create a standard user with sudo privileges.
Create the root password:
# passwd
Create your standard user (USERNAME):
# useradd -m -G wheel,storage,power -g users -s /bin/bash USERNAME
Create a password for your new user:
# passwd USERNAME
Allow the wheel group to execute sudo commands by editing the visudo file:
# visudo
Search for the following line and remove the # in front of it:
%wheel ALL=(ALL:ALL) ALL
Switch to your newly created user:
$ sudo -u USERNAME -i
Step 19: Install an AUR Helper (Yay) #
Install yay to easily download user-created packages from the Arch User Repository. First, install Go:
$ sudo pacman -Syy go
Build and install yay:
$ git clone https://aur.archlinux.org/yay.git
$ cd yay
$ makepkg -is
$ cd ..
$ rm -rf yayStep 20: Configure mkinitcpio Hooks #
You must configure mkinitcpio so the kernel knows how to handle encryption and LVM during boot. Edit /etc/mkinitcpio.conf:
HOOKS=(base udev plymouth modconf kms keyboard keymap block encrypt lvm2 btrfs filesystems fsck)
Step 18: Install Missing Firmware #
Install mkinitcpio-firmware using yay:
$ yay -Syy mkinitcpio-firmware
Step 19: GRUB Bootloader Setup #
Install GRUB #
$ sudo pacman -Syy grub efibootmgr
Setup Disk Encryption for GRUB #
Append/uncomment the following line in /etc/default/grub:
GRUB_ENABLE_CRYPTODISK=y
Add Command Line Parameters #
In /etc/default/grub, edit the default arguments:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash sysrq_always_enabled=1 fbcon=nodefer cryptdevice=UUID=disk-UUID:cryptroot root=LABEL=root rootflags=subvol=@ rw loglevel=3"
Create a List of Modules for GRUB #
Create a list of modules for GRUB. (Note: Apple filesystem and RAID are excluded here. Check the Ubuntu GRUB Secure Boot script in the references for more details).
GRUB_MODULES="
all_video
boot
btrfs
cat
chain
configfile
echo
efifwsetup
efinet
ext2
fat
font
gettext
gfxmenu
gfxterm
gfxterm_background
gzio
halt
help
iso9660
jpeg
keystatus
loadenv
loopback
linux
ls
lsefi
lsefimmap
lsefisystab
lssal
memdisk
minicmd
normal
ntfs
part_msdos
part_gpt
password_pbkdf2
png
probe
reboot
regexp
search
search_fs_uuid
search_fs_file
search_label
sleep
smbios
squash4
test
true
video
cpuid
play
tpm
cryptodisk
gcry_rsa
gcry_seed
gcry_sha256
luks
lvm
"
Install GRUB on ESP (EFI System Partition) #
$ sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --modules=${GRUB_MODULES} --disable-shim-lock
Generate GRUB Config #
$ sudo grub-mkconfig -o /boot/grub/grub.cfg
Step 20: Avoiding Double Passphrase Entry #
Since GRUB prompts for your LUKS password to load the kernel, you can configure a keyfile to prevent having to type it a second time as the system boots.
Create the keyfile and add it to LUKS:
$ sudo dd bs=512 count=4 if=/dev/random of=/root/cryptlvm.keyfile iflag=fullblock
$ sudo chmod 000 /root/cryptlvm.keyfile
$ sudo cryptsetup -v luksAddKey /dev/sda3 /root/cryptlvm.keyfile
Edit /etc/mkinitcpio.conf to include the keyfile:
FILES=(/root/cryptlvm.keyfile)
Generate initramfs and secure the embedded keyfile:
$ sudo mkinitcpio -P
$ sudo chmod 600 /boot/initramfs-linux*
Edit /etc/default/grub and add the cryptkey parameter:
GRUB_CMDLINE_LINUX_DEFAULT="...cryptkey=rootfs:/root/cryptlvm.keyfile..."
Regenerate the GRUB config:
$ sudo grub-mkconfig -o /boot/grub/grub.cfg
Step 21: Secure boot setup #
Install Secure Boot Manager (sbctl) #
$ sudo pacman -Syyu sbctl
Create and Enroll Secure Boot Keys #
Create the keys:
$ sudo sbctl create-keys
Change attributes of keys in Btrfs:
$ sudo chattr -i /sys/firmware/efi/efivars/{PK,KEK,db}*
(If either PK, KEK, or db causes the command to fail, remove that specific one from the list and run with the rest).
Enroll the keys alongside Microsoft’s keys:
$ sudo sbctl enroll-keys -m
Sign the Bootloader #
Sign GRUB and the Linux kernel to satisfy Secure Boot:
$ sudo sbctl sign -s -o /boot/efi/EFI/arch/grubx64.efi /boot/efi/EFI/arch/grubx64.efi
$ sudo sbctl sign -s -o /boot/vmlinuz-linux /boot/vmlinuz-linux
Step 22: Plymouth Setup #
Plymouth provides an elegant, flicker-free graphical boot splash screen.
Install Plymouth:
$ sudo pacman -Syy plymouth
Install the theme via Yay:
$ yay -Syy plymouth-theme-bgrt-better-luks
View and set the Plymouth theme:
$ sudo plymouth-set-default-theme -l
$ sudo plymouth-set-default-theme -R bgrt-better-luks
Re-run mkinitcpio to apply changes:
$ sudo mkinitcpio -P
Step 23: Finish Install #
Log out of your user account, exit the chroot environment, unmount your drives, and reboot into your new, highly secure system!
$ exit
# exit
# umount -a
# reboot
Final Step: Don’t forget to physically turn on Secure Boot in your motherboard’s BIOS after rebooting. Nothing else is needed.
Frequently Asked Questions (FAQ) #
1. Why use GRUB instead of systemd-boot for Arch Linux? #
While systemd-boot is simpler, GRUB provides more advanced features for complex partition layouts. In this tutorial, GRUB handles the decryption of the LUKS partition before passing control to the OS, which is highly preferred by some security advocates. If you prefer systemd-boot, check out my alternative guide!
2. Why should I use Btrfs with LUKS? #
LUKS provides the heavy-duty security (encryption at rest), while Btrfs provides modern file system features. Btrfs allows you to take instant snapshots of your system. If an update breaks your Arch Linux install, you can simply roll back to a snapshot from the previous day without losing your encrypted setup.
3. Is an 8GB swap partition enough? #
Yes, 8GB is generally sufficient for modern systems with 16GB of RAM or more. However, if you plan to use hibernation on a system with 32GB of RAM, you will need a swap partition at least as large as your total RAM.
24. Reference #
-
https://wiki.archlinux.org/title/User:ZachHilman/Installation_-_Btrfs_%2B_LUKS2_%2B_Secure_Boot
-
https://gist.github.com/mjnaderi/28264ce68f87f52f2cabb823a503e673
-
https://gist.github.com/martijnvermaat/76f2e24d0239470dd71050358b4d5134
-
https://nerdstuff.org/posts/2020/2020-004_arch_linux_luks_btrfs_systemd-boot/
-
https://github.com/AravindIM/nixos-dotfiles/blob/main/hosts/thinkpad/hardware-configuration.nix
-
https://github.com/AravindIM/arch-install/blob/main/install-gnome.sh
-
https://github.com/0xadeeb/NixOs-config/blob/master/hosts/hp-pavilion/hardware-configuration.nix
-
https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate
-
https://askubuntu.com/questions/1304519/fstab-automatically-creates-mount-points
-
https://wiki.archlinux.org/title/User:Bai-Chiang/Installation_notes
-
https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot
-
https://linuxconfig.org/how-to-manage-efi-boot-manager-entries-on-linux
-
https://binary-manu.github.io/binary-is-better/linux/archlinux-secure-boot