Edit: Modified for optimizations after creating the automated installations.
When I first started playing with Arch, I installed it as a virtual machine on Proxmox. I found I used snapshots a lot when I was trying out new packages – I was never sure I could get my machine back to a working state if I messed things up.
Moving from the VM to bare metal, I wanted to retain this ability to snapshot, so after a discussion with a colleague I decided to use btrfs as the filesystem.
Note: btrfs is a little unstable, so you probably should not use it for a production environment.
This walkthrough is largely based on Staf Wagemakers excellent article Install Arch on an encrypted btrfs partition with some changes for my environment, like using EFI.
This installation was actually performed on the Proxmox VM so that I could easily create screenshots.
Note: A prompt is implied for each of the code blocks but has been omitted to allow you to copy and paste directly from this page to your ssh window.
Download Arch
Download the ISO for Arch and copy it to a USB key, CD or whatever you need. As I am installing it on to a VM, it was easy, I just needed to mount it. This ISO is the latest version at the time of writing, no doubt it will be updated by the time you read this, but it really doesn’t matter because Arch is designed to be easily updateable.
wget ca.us.mirror.archlinux-br.org/iso/2020.07.01/archlinux-2020.07.01-x86_64.iso
The full list of mirrors is available at https://www.archlinux.org/download/
Booting Arch
Boot the ISO and select the highlighted option.

Once Booted, you will be presented with a command prompt. No installer, text or graphical. Welcome to the wonders of Arch!
Network Access
We need the DHCP assigned IP address and we need to verify everything is working correctly.
# Display the IP address
ip a
# Verify internet access
ping -c 3 8.8.8.8
ping www.google.com
Start SSH
If you want to install via SSH (way easier because you can copy and paste from the walkthrough), we need to start it.
# set a root password
passwd root
# start ssh
systemctl list-unit-files -t service | grep ssh
systemctl start sshd
ssh root@ip
Partition the hard disk
First find out the device name
cat /proc/partitions
Overwrite with random data. If you are impatient you can exit out of this after the first few bytes are completed and the partition table has been destroyed.
badblocks -c 10240 -s -w -t random -v /dev/sda
Use parted to partition the disk because we want EFI. We are creating the following partitions –
- 200mb partition, formatted as FAT32 for the EFI
- 600mb partition for the GRUB bootloader
- 32gb (ish) partition for swap
- A partition for btrfs that consumes the rest of the disk
parted /dev/sda
mklabel gpt
mkpart ESP fat32 1MiB 200MiB
set 1 boot on
name 1 efi
mkpart primary 200MiB 800MiB
name 2 boot
mkpart primary 800MiB 32Gib
(parted) name 3 swap
mkpart primary 32GiB 100%
name 4 btrfs
# print the partitions to make sure they are correct
print
# exit & write to disk
quit
Create a LUKS volume & Open it
cryptsetup luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha256 --use-random /dev/sda4
cryptsetup luksOpen /dev/sda4 cryptroot
Format all the Partitions
mkfs.fat -F32 /dev/sda1
mkfs.ext4 /dev/sda2
mkswap /dev/sda3
mkfs.btrfs /dev/mapper/cryptroot
Mount the root file system
mount -o noatime,compress=lzo,discard,ssd,defaults /dev/mapper/cryptroot /mnt
Create the subvolumes
cd /mnt
btrfs subvolume create __active
btrfs subvolume create __active/rootvol
btrfs subvolume create __active/home
btrfs subvolume create __active/var
btrfs subvolume create __snapshots
btrfs subvolume create __snapshots/root
btrfs subvolume create __snapshots/home
btrfs subvolume create __snapshots/var
cd
umount /mnt
Mount the subvolumes
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__active/rootvol /dev/mapper/cryptroot /mnt
mkdir /mnt/.snapshots
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__snapshots/root /dev/mapper/cryptroot /mnt/.snapshots
mkdir /mnt/{home,var,boot}
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__active/home /dev/mapper/cryptroot /mnt/home
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__active/var /dev/mapper/cryptroot /mnt/var
mkdir /mnt/home/.snapshots
mkdir /mnt/var/.snapshots
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__snapshots/home /dev/mapper/cryptroot /mnt/home/.snapshots
mount -o noatime,compress=lzo,discard,ssd,defaults,subvol=__snapshots/var /dev/mapper/cryptroot /mnt/var/.snapshots
sync
Mount the non-btrfs partitions
mount /dev/sda2 /mnt/boot
mkdir /mnt/boot/efi
mount /dev/sda1 /mnt/boot/efi
swapon /dev/sda3
swapon -a ; swapon -s
Install Arch Linux
Use the pacstrap script to install the base packages, obviously we are including the btrfs package and EFI support.
pacstrap /mnt base base-devel linux linux-firmware nano btrfs-progs efibootmgr grub networkmanager openssh git --noconfirm
Generate an fstab file.
genfstab -p -U /mnt >> /mnt/etc/fstab
Change root into the newly installed system
arch-chroot /mnt
Time zone
Set the timezone & hardware clock.
Link for timezone to /etc/localtime
ln -s /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
hwclock --systohc --utc
Localization.
Edit /etc/locale.gen
and uncomment en_US.UTF-8 UTF-8
and other needed locales.
nano /etc/locale.gen
Generate the locales by running:
locale-gen
Network Configuration
Replace ‘myhostname’ with your desired name.
echo myhostname > /etc/hostname
Create a hosts file.
nano /etc/hosts
127.0.0.1 localhost
::1 localhost
127.0.1.1 myhostname.localdomain myhostname
Create a new initramfs
Add encrypt to HOOKS before filesystems in /etc/mkinitcpio.conf and create the initial ramdisk environment for booting the linux kernel.
sed -i 's/HOOKS=(base\ udev\ autodetect\ modconf\ block\ filesystems\ keyboard\ fsck)/HOOKS="base\ udev\ autodetect\ modconf\ block\ encrypt\ filesystems\ keyboard\ fsck"/' /etc/mkinitcpio.conf
mkinitcpio -p linux
Set the root password
passwd root
Autostart network manager & sshd services
systemctl enable NetworkManager.service
systemctl enable sshd.service
Install grub
grub-install --target=x86_64-efi --efi-directory=/boot/efi --recheck
Configure LUKS kernel parameters
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/GRUB_CMDLINE_LINUX_DEFAULT="cryptdevice=\/dev\/sda4:cryptroot\ root=\/dev\/mapper\/cryptroot\ rootflags=subvol=__active\/rootvol\ quiet"/' /etc/default/grub
Regenerate grub.cfg file:
grub-mkconfig -o /boot/grub/grub.cfg
grub-mkconfig -o /boot/efi/EFI/arch/grub.cfg
*** BECAUSE EFI IS SHIT
mkdir /boot/efi/EFI/BOOT
cp /boot/efi/EFI/arch/grubx64.efi /boot/efi/EFI/BOOT/BOOTX64.EFI
Allow users to run SUDO
echo "%wheel ALL=(ALL) ALL" | (EDITOR="tee -a" visudo)
Create a user account
useradd -m -G wheel [username]
passwd [username]
Reboot!
sync
exit
reboot
First Boot
Login using your new user account
ssh [username]@[ip address]
Install YAY
You will probably want to install packages from the Arch User Repository (AUR). My favorite package manager for this is YAY (Yet another yogurt) – lets install it.
Warning: AUR packages are user produced content. Any use of the provided files is at your own risk.
git clone https://aur.archlinux.org/yay.git
cd yay/
makepkg -si --noconfirm
cd ..
sudo rm -dR yay/
Job done.
References:
1. Install Arch on an encrypted btrfs partition – http://stafwag.github.io/blog/blog/2016/08/30/arch-on-an-encrypted-btrfs-partition/#download-the-arch-linux-iso-and-boot-it
6 Comments
🔥 💯
I wouldn’t create an unencrypted swap. Those can contain lots of goodies even after system poweroff.
Interesting. Never thought about that!
Works like a charm. Thank you!
Hey thanks for this guide I was able to successfully setup my system with it. A few considerations:
1. small typo when creating partition 4 it says to name it partition 3
2. For the intramfs config, that didnt work for me as the bootloader? could not find /dev/mapper/cryptroot, I ended up mapping it via UUID
3. steps to add a keyfile so the drive auto-decrypts at boot would be nice, I used another guide and got this working
4. after rebooting and entering the OS I had no wifi again so some quick steps to reconnect would be good, i had to use ip link commands? as iwctl and wifi-util were not installed
5. listing your preferred DE etc is always welcome 🙂
Thanks for the comments – I updated the quick and easy ones. I will try to incorporate the others when I get a chance to rebuild 🙂