Hope this will stay relevant for longer than just 2021. This guide will focus mostly on things you shouldn't overlook and will harshly prioritise assuming that you're running on recent hardware. EFI and all that.
Always refer to the official guide in case of doubt.
One important thing first: the environment you will encounter on the live image is very different
from what you'll end up installing, some things are significantly easier there: e.g. wifi tools come
pre-installed, the default shell is a pimped zsh
with nice completions, and so on. We'll keep this
in mind where it's important.
I assume you haven't downloaded the setup image from a dodgy website so you don't really have to verify it (I wonder how many people do that).
The first thing you should do is set your preferred console keyboard layout with loadkeys
, unless
the default one, us
, is the one you want.
# ls /usr/share/kbd/keymaps/**/*.map.gz # look up the possible values
# loadkeys no # grab one of the file names, minus the extension
As above, we assume you're using EFI, to check this
# ls /sys/firmware/efi/efivars
If this throws any error you should stop here and stick to the official guide.
Connecting to the internet is not the same procedure during the installation phase as it will be later. The install iso has a bunch of closed source modules embedded so it should recognise your wifi card out of the box. If it doesn't, grab an ethernet cable and your favourite dongle in case you don't have an ethernet port.
- Ethernet should work once you plug the cable
- For Wifi you should use
iwctl
Test the connection to be safe.
Update the system clock (so vintage)
# timedatectl set-ntp true
Now it's time to partition the disks.
In a previous version of this tutorial I mentioned a few possibilities, LUKS, LVM, swap partition, swapfile. It's unnecessary to discuss all of them, so I'll just make the simplest choice for you: a single encrypted partition, and a swapfile inside it. No use bothering with LVM, and no use bothering with fixed-size swap and two partitions.
Nevertheless, start with the efi
partition: don't get stingy with the space, put at least
300MB, I'd even say 500. If the system already has one (my Macbook Pro did) you should leave
it there, although it might be small, so if you can move the contents somewhere else, expand it, and
move the stuff back, do it.
Use cfdisk
to partition the drive. If the disk is already partitioned (as above) you shouldn't
do much, otherwise you need to create a new GPT partition table.
As mentioned, allocate at least 500M to your efi
partition, which should be the
first, and set EFI
as its type, then create a big Linux
partition for the rest of the space.
Save and quit.
Now it's time to create the encrypted volume. We'll assume that sda1
is your efi
partition
and sda2
is the Linux
one you created above, but with NVMe SSDs it's possible that your drive
will be called nvme0n1
so you'll have nvme0n1p1
as efi
and nvme0n1p2
instead of sda2
.
# cryptsetup -y -v luksFormat /dev/sda2
# cryptsetup open /dev/sda2 main # use whichever name you want but it needs to match below
This will just create "encrypted space". From here you can either create a partition
(mkfs.ext4 /dev/mapper/main
) and mount it (mount /dev/mapper/main /mnt
), that's pretty much it.
Regardless of your setup during the installation phase whatever is your /
partition should
be mounted on /mnt
.
As for the swap file, nowadays there are a few options, and the good thing about it is that you don't have to worry about it now. For later, here are two pointers.
If you use zram it'll presumably have higher performance, but you'll lose hibernation, so pick whichever you like. This is reversible anyway (unlike using partitions).
Anyway:
- The root partition is created and mounted.
- The boot partition is mounted at the right place (
/mnt/boot
, not/boot
).
If both of the above are true, we can move to the next section. Some details of this setup will be crucial to make sure that the system boots, we'll mention them later.
- You can go full paranoid and have an encrypted boot partition. There's a way to do that with GRUB. The EFI partition can't be encrypted as far as I know so you'll still leave some system files there to be potentially tampered with by an attacker. There's always a line to be drawn somewhere and this is an option if you think you need to hide your kernels.
- Instead of using the above, you should set up secure boot. The overarching issue is that its setup is clunky and device-dependent, and there isn't "one way" to do it, but overall it's not very hard to set up. We'll talk about it later.
This is the easy part, but you probably still need a couple of pointers.
Install the base system
# pacstrap /mnt base linux linux-firmware
This basically installs only the base system plus the kernel plus essential Linux firmware: it won't install anything like "my webcam's firmware" or "external wifi drivers". We'll do that in a second.
Generate your fstab
file for this setup:
# genfstab -U /mnt >> /mnt/etc/fstab
This basically looks at what's mounted and where and generates a matching /etc/fstab
. Edit the paths
if they're wrong, e.g. if the efi
partition is mounted to /mnt/boot
instead of /boot
, keep in
mind that this is in what will become your setup, so no /mnt
there – hence genfstab /mnt
.
Now you can chroot to /mnt
and we'll operate as if everything is installed.
# arch-chroot /mnt
Set the time zone and sync the hardware clock:
# ln -sf /usr/share/zoneinfo/Europe/Oslo /etc/localtime # pick whichever time zone
# hwclock --systohc
Now you need to think of what you need to install in the system to make sure that once you reboot
you're not in some bizarre desert island. As I mentioned earlier, exotic wifi stuff isn't installed by
default, but luckily many things are in the Arch Linux repository. For instance, if you need the
Broadcom wl
module:
# pacman -S linux-headers broadcom-wl-dkms
Repeat this step for every peripheral you know that you will need (minus linux-headers
of course):
the most crucial one in general is just the WiFi because keyboards and screens should work out of
the box and maybe you just miss the nvidia
driver and stuff like that if you have a Nvidia card,
but since the open source driver is installed already, you should be fine for minimal usage.
Once you're sure that you have a working WiFi module installed, this is also the right time to
figure out how you want to use your new setup: if you want to fine tune it yourself and install
whichever minimal WM (e.g. i3), have fun, but be careful to install whichever tools you need to
connect to the internet. If you want to use gnome
on the other hand, just run:
# pacman -S gnome
And this should install everything on its own. If you use gnome
you need to have
Network Manager installed even though these days systemd
has a thingy that is able to
control the network. Check if wpa_supplicant
and networkmanager
are installed.
# pacman -Q wpa_supplicant networkmanager
If not, well, pacman -S
etc. etc..
As a rule of thumb, Arch Linux doesn't enable stuff for you after you install it,
when it comes to global systemd
configuration, so do this:
# systemctl enable NetworkManager.service
This makes sure Network Manager starts when you reboot, so that then you can use GNOME's GUI to configure your wifi, or wired connection.
Now it's a good moment to look at the guide and maybe follow the steps related to localisation and network configuration. You only need to set a hostname for your computer, not much else.
Create a root password:
# passwd
This is also a good moment to create your own user:
# useradd -m username
# passwd username
This is a matter of taste but I'd install your usual comfort zone packages now, e.g.
your favourite shell, your favourite text editor and so on. Not to imply that since
you'll fuck up your boot loader configuration it's better to have a nice text editor
and shell so that you won't be too annoyed when you'll have to fix your mistakes, you
never know what life has in store for you so it's just nicer to face adversities
from a nice zsh
prompt.
Alright: this is where you can't fuck stuff up. If you fuck stuff up here your system
won't boot. Typically when this happens it's recoverable from the install medium you
used, via arch-chroot
and so on. With encrypted setups doing this is annoying because
on every reboot with the install medium you always need to open the volume, mount the
root partition and so on, so every fuckup adds minutes to the debugging process. To
add insult to injury, debugging is often hard because the messages aren't very helpful.
Having said that, here we go.
What I'd do first is check the guide.
This is what my /etc/mkinitcpio.conf
with looks.like:
HOOKS="base systemd plymouth autodetect keyboard sd-vconsole modconf block sd-encrypt filesystems resume fsck
The order of stuff is very important here so even though you might not find some things yet
(e.g. plymouth
certainly isn't there).
If you don't have sd
-related things don't panic, we haven't added those yet. We'll do that in
a second.
Now it's a good time to run your first mkinitcpio
:
# mkinitcpio -P
Chances are that this has been run already by several of the commands we ran earlier.
We'll use systemd-boot
. A few principles:
- It will be installed in your EFI partition.
- It will grab loader entries from
/boot/loader/entries/
so once it's installed we'll make sure you have a valid one there.
Install it:
# bootctl install
There are ways to keep it updated. Either you just run bootctl update
every now and then or
add a hook so that it's done automatically
(this isn't a hard requirement).
The crucial thing is to get one working entry. Check out the contents of /boot/loader/entries
, there
might be something there already. Just in case, here's what a working entry looks like:
title Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options rd.luks.name=[PLACEHOLDER_1]=[PLACEHOLDER_2] root=[PLACEHOLDER_3] rw
Trivial things first: if you have an Intel CPU you should install the intel-ucode
package and keep that
line, otherwise if you have an AMD CPU you should install the amd-ucode
package and replace intel-ucode.img
with amd-ucode.img
.
Now with the three placeholders. We need to rewind a bit and do some matching. The third placeholder is the
easy one: this is the root partition's "device", the "thing that you mount". So /dev/mapper/main
or
whatever you decided to cryptsetup open
.
Let's run blkid
:
# blkid
/dev/nvme0n1p1: UUID="284C-3A64" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="0794ef09-5eb8-d144-b103-bc7b975f8963"
/dev/nvme0n1p2: UUID="79ac497a-7eac-4f16-af63-f362c52ed44c" TYPE="crypto_LUKS" PARTUUID="58319ad0-043c-fc48-9c4b-c466484d1135"
/dev/mapper/main: UUID="fd884ff1-12a0-4289-89ce-11ca73f4af89" BLOCK_SIZE="4096" TYPE="ext4"
The first and second placeholder are, respectively, the UUID of the outermost layer of the partitions onion:
options rd.luks.name=79ac497a-7eac-4f16-af63-f362c52ed44c=main root=/dev/mapper/main
Triple check that you're not using the UUID of /dev/mapper/main
. If you do that, your computer won't boot.
main
is the name of whatever you picked earlier with cryptsetup: unclear if there needs to be consistency
(there probably has to), so remember the general idea and keep tabs.
Save your new entry as /boot/loader/entries/linux.conf
. It should be fine to keep that as your only
entry.
Now back to /etc/mkinitcpio.conf
, check out the HOOKS
line again:
HOOKS="base systemd autodetect keyboard sd-vconsole modconf block sd-encrypt filesystems resume fsck"
To be safe, run mkinitcpio -P
again (no use not doing so).
Now you can reboot and cross your fingers.
If you see systemd-boot
's prompt (i.e. you see a Linux
entry) but then booting hangs the mistake
should be almost certainly because you messed up ID's and names. Don't despair, it's fixable without
having to start from scratch. Boot from the install medium and mount the root and boot partitions.
- Check
mkinitcpio.conf
just in case, compare with theHOOKS
above. - Check the UUID's in
/boot/loader/entries/linux.conf
(or whichever the UUIDs).
Fixing these mistakes is very annoying because each reboot is time consuming.
Well done, there isn't much left to do.
From here on I'll take a few things for granted, like that GNOME works and that your main
user can sudo
(and of course that sudo
is installed), etc.
For some strange reason, plymouth
hasn't made it out of the AUR. This is a good opportunity to
install an AUR helper, i.e. a piece of software that handles installation from the AUR automatically.
I recommend yay
but you might have a different opinion. Have a look
here on how to install it.
$ yay -S plymouth plymouth-theme-arch-charge
$ sudo plymouth-set-default-theme arch-charge
If you remember from earlier there's an extra mkinitcpio
hook to be added:
HOOKS="base systemd plymouth autodetect keyboard sd-vconsole modconf block sd-encrypt filesystems fsck"
Just that extra plymouth
.
Before rebooting you should also tell mkinitcpio
that you need to load your graphics module. This will
depend on which card you have. I can only vouch for Intel and NVIDIA. You need to edit the MODULES
section of mkinitcpio.conf
:
MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm) # for nvidia cards
MODULES=(i915) # for intel cards
No, you're not done yet. You need to add yet more kernel options to your /boot/loader/entries/linux.conf
.
Again, linux.conf
is the name I picked, you can choose whatever you like. In the options
line, append:
quiet splash loglevel=3 rd.udev.log_priority=3 vt.global_cursor_default=0
Once that is done, mkintcpio -P
will be enough: you can reboot now and you should be able to see the splash
screen on shutdown already.
Briefly, secure boot is a feature that only allows to boot signed files. If a file isn't signed the bootloader rejects it. The keys are stored in a module in your computer that only the BIOS can access, and, of course within your hard drive (or wherever else you want to store them, concretely).
In order for this to be secure, you must do the following:
- Secure boot must be enforced
- Your BIOS must be protected with a password
- The partition containing your keys must be encrypted
If 1. isn't true, someone could replace your signed kernel with a malicious one that you will boot without knowing. If 2. isn't true, someone could access your bios, disable secure boot, and you're back to point 1. If 3. isn't true, someone could sign a malicious kernel with your keys, without the need to tamper with the BIOS.
Another requirement is to use UKIs that replace the old initrd/vmlinuz combo, plus the boot parameters.
Reminder of our bootloader entry:
title Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options rd.luks.name=[PLACEHOLDER_1]=[PLACEHOLDER_2] root=[PLACEHOLDER_3] rw
It will become like this:
title Linux
efi /EFI/arch/linux-signed.efi
The microcode and initramfs part will go into /etc/mkinicpio.d/linux.preset
ALL_kver="/boot/vmlinuz-linux"
ALL_microcode=(/boot/*-ucode.img)
PRESETS=('default')
default_image="/boot/initramfs-linux.img"
default_uki="/boot/EFI/arch/linux-signed.efi"
As you can see default_uki
is the thing that is referenced in /boot/loader/entries/linux.conf
.
The other part, the kernel boot parameters can go into two different places, /etc/cmdline.d/*.conf
or /etc/kernel/cmdline
. I chose the latter but it's the same. Edit the file and put
rd.luks.name=[PLACEHOLDER_1]=[PLACEHOLDER_2] root=[PLACEHOLDER_3] rw # and all the other params
Basically the last line of the old bootloader entry minus options
.
If you now run mkinitcpio -P
you should see /boot/EFI/arch/linux-signed.efi
.
To then configure secure boot there are two options. One is manual but it gives you a bit more
control (but it is clunky). The other one is way easier, and it involves sbctl
(which you
need to install).
I will detail the essential procedure, as instructions are not universal.
- Create keys with
sbctl create-keys
. - Try
sbctl enroll-keys -m -f
. This command puts your newly created keys plus the Microsoft ones and the ones recommended by the firmware, into the BIOS. Chances are that it might fail because you need to be in "setup mode". This, in some cases, requires wiping the secure boot configuration, and with it the pre-enrolled keys. Check around if your computer needs them urgently to boot (it probably doesn't). If it doesn't, reboot into the BIOS, put your computer in setup mode (in the Framework Laptop case this is achieved by erasing all secure boot settings), then re-run the command again. If it succeeds, move on. If it fails, you'll need to dig more. - Run
sbctl verify
and you'll have a list of files that you need to sign. Typically the bootloader (/boot/EFI/BOOT/BOOTX64.EFI
) and the kernel UKI (/boot/EFI/arch/linux-signed.efi
). - Sign all of them with
sbctl sign -s
(don't forget-s
as it saves the path to the database so that every kernel/systemd upgrade will trigger a signature. - Run
sbctl status
andsbctl verify
and check that everything makes sense. - Reboot and enable secure boot.
This is also something you might need regardless of whether you're using a laptop.
Add the resume
hook between filesystems
and fsck
in mkinitcpio.conf
which you should be
best mates with by now, and run mkinitcpio -P
.
You must also tell the bootloader where to resume from, by adding the resume=
kernel option to the
loader entry.
If you're using a swap partition resume=UUID=PLACEHOLDER
where PLACEHOLDER
is of course the
UUID of the swap partition (sudo blkid
to obtain it). If you're using a swap file the logic is
a bit different. resume
should point to the device containing the file, e.g.:
resume=/dev/mapper/main # in the luks example above
Only one of those two of course. Then you should add a resume_offset
parameter that you obtain
this way:
$ sudo filefrag -v /swap
Filesystem type is: ef53
File size of /swap is 34359738368 (8388608 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 0: 514048.. 514048: 1:
1: 1.. 10239: 514049.. 524287: 10239: unwritten
2: 10240.. 272383: 557056.. 819199: 262144: 524288: unwritten
It should be the first physical_offset
value, i.e. in this case
resume_offset=514048
Since the system hasn't been booted with a kernel supporting hibernation even if you regenerate
the initramfs now (mkinitcpio -P
) you'll need to reboot to be able to use this feature.
This is pretty much it, I hope it's useful.
I got here searching on mounting my luks volume after I messed up grub on my fresh Arch install. Decided to follow your guide to the letter and it works great in 2023 on my 2012 Macbook. No issues with system-boot surprisingly! No caveats found and no changes were needed. Arch setup doesn't change much I guess 😅
Thanks for sharing it was indeed useful, fun and educational!