This document expands upon the official Arch Linux Wiki installation guide by covering some more steps:
- Arch Linux installation on a LUKS2 container on Btrfs
- Microsoft Windows 10/11 installation with BitLocker
- Install and configure GRUB as the default bootloader
- Configure an encrypted swapfile with full hibernation support
- Some basic post-installation steps to get you started quickly
The resulting setup will look like this:
This guide primarily serves as my personal installation log, but I hope it will also be useful to others. It may help advanced users quickly build a similar setup or assist beginners in learning more about the installation process. I’ve included many links for further reading.
The resulting setup is designed to be secure, encrypted, yet flexible enough for easy customization. I use this setup on my personal ThinkPad T14 (2024) and primarily stick with Linux. I use Windows for testing and certain work-related tasks.
Note: This guide does not provide a highly secure setup. While encryption will protect your data in case of theft or loss, there are no measures described (yet) for tamper-proofing the device when physically accessed.
If tamper protection is critical, consider using a single-boot setup with properly configured Secure Boot and TPM.
Before installing, it is advised to view the Arch Linux FAQ. For conventions used in this document, see Arch Linux Help Reading. Throughout this guide, code examples may contain placeholders (formatted in italics), which must be replaced manually. Prompts are indicated by the shell symbol #
for root commands and $
for user-level commands.
The Arch Linux installation medium offers accessibility features, detailed on the Install Arch Linux with Accessibility Options wiki page. For alternative means of installation, see Category: Installation Process.
Visit the Arch Linux download page and, depending on how you want to boot, acquire the ISO file or a netboot image, and the respective GnuPG signature.
It is recommended to verify the image signature before use, especially when downloading from an HTTP mirror. On a system with GnuPG installed, do this by downloading the ISO PGP signature (under Checksums on the Download page) to the ISO directory, and verifying it with:
$ gpg --keyserver-options auto-key-retrieve --verify archlinux-version-x86_64.iso.sig
Alternatively, from an existing Arch Linux installation run:
$ pacman-key -v archlinux-version-x86_64.iso.sig
Note:
- The signature itself could be manipulated if it is downloaded from a mirror site, instead of from archlinux.org as above. In this case, ensure that the public key, which is used to decode the signature, is signed by another, trustworthy key. The gpg command will output the fingerprint of the public key.
- Another method to verify the authenticity of the signature is to ensure that the public key's fingerprint is identical to the key fingerprint of the Arch Linux developer who signed the ISO-file. See Wikipedia: Public-key cryptography for more information on the public-key process to authenticate keys.
The ISO can be supplied to the target machine via a USB flash drive, an optical disc or a network with PXE: follow the appropriate article to prepare yourself an installation medium from the ISO file.
In this guide, we will use a USB flash drive. You may use Rufus on Windows to write the image to the thumb drive or if you’re on Linux, simply use cat:
# cat path/to/archlinux-version-x86_64.iso > /dev/disk/by-id/usb-My_flash_drive
Visit the download page and follow the instructions to either create a Windows 11 installation media using the "Media Creation Tool", or download the ISO.
If you’re on Windows, the "Media Creation Tool" will handle everything for you. Simply follow the wizard.
If you’re on Linux, download the ISO and retrieve the sha256 hash right from the download page. You may use the following commands to compare the provided checksum with the calculated checksum. This will use the sha256sum
command which comes bundled with most Linux distributions.
$ hash="D5A4C97C3...876044309"
$ file="Win11_24H2_EnglishInternational_x64.iso"
$ actual=$(sha256sum $file | awk '{print toupper($1)}'); echo -e "Expected hash: $hash\nActual hash: $actual\nIdentical: $(if [ "$hash" = "$actual" ]; then echo yes; else echo no; fi)"
If the checksum is identical, you may proceed with your preferred method from Cybercitis blog post about creating a bootable Windows 10 USB.
Before installing any OS, make sure your disk is empty and ready for the installation. Boot from the Arch Linux ISO as described in Step 4.1.
When recognized by the live system, disks are assigned to a block device such as /dev/sda
, /dev/nvme0n1
or /dev/mmcblk0
. To identify these devices, use lsblk
or fdisk
.
# fdisk -l
Results ending in rom
, loop
or airootfs
may be ignored. mmcblk*
devices ending in rpbm
, boot0
and boot1
can be ignored.
Note: If the disk does not show up, make sure the disk controller is not in RAID mode.
Tip: Check that your NVMe drives and Advanced Format hard disk drives are using the optimal logical sector size before partitioning.
Most solid state drives (SSDs) report their logical block address size as 512 bytes, even though they use larger blocks physically - typically 4 KiB, 8 KiB, or sometimes larger. To check the formatted logical block address size (FLBAS) of an NVMe drive, use the nvme-cli utility in addition with Identify Namespace command:
# nvme id-ns -H /dev/nvme0n1 | grep "Relative Performance"
LBA Format 0 : Metadata Size: 0 bytes - Data Size: 512 bytes - Relative Performance: 0x2 Good (in use)
LBA Format 1 : Metadata Size: 0 bytes - Data Size: 4096 bytes - Relative Performance: 0x1 Better
To change the logical block address size, use nvme format and specify the preferred value with the --lbaf parameter:
# nvme format --lbaf=1 /dev/nvme0n1
You are about to format nvme0n1, namespace 0x1.
WARNING: Format may irrevocably delete this device's data.
You have 10 seconds to press Ctrl-C to cancel this operation.
Use the force [--force] option to suppress this warning.
Sending format operation ...
Success formatting namespace:1
Create a new GPT table on the SSD:
sgdisk --zap-all /dev/nvme0n1
Point the current boot device to the one which has the Windows installation medium. Typically it is achieved by pressing a key during the POST phase, as indicated on the splash screen. Refer to your computer or motherboard's manual for details.
Once booted into the installation wizard, proceed following the instructions.
- Select your desired regional options.
- Select "Install"
- Select "I don't have a product key"
- Select "Windows 10 Pro" or "Windows 11 Pro" ("Pro" is needed for BitLocker)
- Inevitably accept the Terms and Conditions
- Select "Custom: Install windows only (advanced)"
- The partitioning wizard is the fastest way to get the default Windows partitions, but the outcome is quite unpredictable. I prefer entering some rough numbers here, then fix the layout using "Disk Management" and the
diskpart
command line interface later. - Click on "New"
- For example: if you want to assign 100 GB for the Windows installation, add some overhead for ESP, Windows Recovery Environment and MSR: 103’516 MB (roughly 102400 MB + 300 MB + 16 MB + 800 MB)
The wizard will then automatically propose the allocation for the 4 partitions. That’s okay. Both the System and the WinRE partition can be manipulated once Windows is booted. Start the installation and wait for the reboot.
The "Out-of-the-box-experience" wizard launches automatically after rebooting. It assists non-savvy users to get started quickly and onboard them to the Microsoft cloud. You can skip most of these steps.
Tip: Refrain from connecting the computer to the internet while completing the wizard to prevent being asked for a Microsoft Account. Simply select “I don’t have internet access”. If you’re installing Windows 11, this option will not be shown. To enforce it, hit Shift + F10 to launch Command Prompt. After entering “OOBE\BYPASSNRO”, hit enter. The procedure will start over, and an “I don’t have internet access” button will appear.
Tip: To circumvent security questions, don’t enter any password for the initial user account. Set the password later.
Once booted into Windows, launch cmd.exe
as administrator. Type diskpart
and hit enter. Type list disk
to see a list of your disk. Select the disk you just installed windows on using sel disk 0
. Type list part
and check whether the partitioning fits your needs. You may adjust it as needed.
Note: When installing windows with very limited space (as described), not only will the system partition have less space assigned, but also the WinRE partition. Check the space allocated to WinRE! To prevent issues with Windows Update, extend it to at least 700 MB. KB5028997: Instructions to manually resize your partition to install the WinRE update
I recommend disabling "fast startup" in windows. This will make sure the computer shuts down properly, and you will be able to select another operating system or boot device.
To disable Fast Startup, press the WinKey + R
to bring up the run dialog, type powercfg.cpl
and hit Enter. The Power Options window should appear. Click "Choose what the power buttons do" from the column on the left.
Scroll down to "Shutdown settings" and uncheck the box for "Turn on fast startup".
Tip:: To stop even more Windows shenenigans (telemetry, insecure defaults, and so on), you may want to run O&O ShutUp10+. The free tool allows you to apply several system tweaks with one click,
To dual boot Windows with Arch Linux, it is recommended to configure Windows to use UTC for the system clock, rather than Linux to use localtime. (Windows by default uses localtime)
This can be done by a simple registry fix. You can do this from an Administrator Command Prompt running:
C:\> reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f
Alternatively, create a *.reg
file (on the desktop) with the following content and double-click it to import it into registry:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
"RealTimeIsUniversal"=dword:00000001
Should Windows ask to update the clock due to DST changes, let it. It will leave the clock in UTC as expected, only correcting the displayed time.
If Windows shows the wrong time now, no need to worry. We will sync UTC time to the hardware clock during the Arch Linux installation process, which will correct Windows time as well.
BitLocker is a full-disk encryption feature included with Windows Pro, Enterprise, and Education versions. It supports various authentication methods and combinations.
By default, BitLocker will use the TPM only to unlock the disk. To enhance security, you can require a PIN or a USB key in addition to the TPM.
-
Open the Local Group Policy Editor (
gpedit.msc
) and navigate to:Computer Configuration > Administrative Templates > Windows Components > BitLocker Drive Encryption > Operating System Drives.
-
Find and open
Require additional authentication at startup
. -
Set the policy to
Enabled
. This setting controls the use of multiple types of startup authentication, such as a PIN, USB startup key, or password, in addition to TPM. -
In the same policy, you'll see several options to determine which combinations are allowed.
Allow BitLocker without a compatible TPM
is unchecked. This will be the first factor in the authentication process.Configure TPM startup
is set toDo not allow TPM
. We don't want to use the TPM as the sole factor.Configure TPM startup PIN
is set toAllow startup PIN with TPM
. Allows the user to set a PIN in addition to the TPM.Configure TPM startup key
is set toAllow startup key with TPM
. Allows the user to use a USB flash drive in addition to the TPM.Configure TPM startup key and PIN
is set toAllow startup key and PIN with TPM
. Allows the user to use a USB flash drive and a PIN in addition to the TPM.
-
In the same path, go to the policy
Enhanced PINs for startup
and set it toEnabled
. Enhanced PINs are alphanumeric and can include special characters. So you'll be able to use a secure password instead of a numeric PIN. -
These settings will not require a restart to take effect when locally configured. However, if the computer is part of a domain, a restart may be required.
-
Go to the Control Panel and search for
BitLocker
. Select the drive you want to encrypt (usually driveC:
) and click "Turn on BitLocker". -
Follow the wizard, set your desired authentication method, and save the recovery key in a safe place.
Note: Arch Linux installation images do not support Secure Boot. You will need to disable Secure Boot to boot the installation medium. If desired, Secure Boot can be set up after completing the installation.
- Point the current boot device to the one which has the Arch Linux installation medium. Typically it is achieved by pressing a key during the POST phase, as indicated on the splash screen. Refer to your motherboard's manual for details.
- When the installation medium's boot loader menu appears,
- if you used the ISO, select
Arch Linux install medium
and press Enter to enter the installation environment. - if you used the Netboot image, choose a geographically close mirror from Mirror menu, then select
Boot Arch Linux
and press Enter.
- if you used the ISO, select
Tip: The ISO uses systemd-boot for UEFI and syslinux for BIOS booting. Use respectively
e
orTab
to enter the boot parameters. The Netboot image uses iPXE and the boot parameters can be specified in the Boot options menu. See README.bootparams for a list. A common example of manually defined boot parameter would be the font size. For better readability on HiDPI screens—when they are not already recognized as such—using fbcon=font:TER16x32 can help. See HiDPI#Linux console (tty) for a detailed explanation.
- You will be logged in on the first virtual console as the root user, and presented with a Zsh shell prompt.
To switch to a different console—for example, to view this guide with Lynx alongside the installation — use the Alt + arrow
shortcut. To edit configuration files, mcedit, nano and vim are available. See pkglist.x86_64.txt for a list of the packages included in the installation medium.
The default console keymap is US. Available layouts can be listed with:
# localectl list-keymaps
To set the keyboard layout, pass its name to loadkeys(1). For example, to set a Swiss German keyboard layout:
# loadkeys de_CH-latin1
Console fonts are located in /usr/share/kbd/consolefonts/ and can likewise be set with setfont(8) omitting the path and file extension. For example, to use one of the largest fonts suitable for HiDPI screens, run:
# setfont ter-132b
To verify the boot mode, check the UEFI bitness:
# cat /sys/firmware/efi/fw_platform_size
If the command returns 64, then system is booted in UEFI mode and has a 64-bit x64 UEFI. If the command returns 32, then system is booted in UEFI mode and has a 32-bit IA32 UEFI; while this is supported, it will limit the boot loader choice to systemd-boot
and GRUB
. If the file does not exist, the system may be booted in BIOS (or CSM) mode. If the system did not boot in UEFI mode, refer to your motherboard's manual to enable UEFI booting.
To set up a network connection in the live environment, go through the following steps:
- Ensure your network interface is listed and enabled, for example with ip-link(8):
# ip link
- For wireless and WWAN, make sure the card is not blocked with rfkill.
- Connect to the network:
- Ethernet—plug in the cable.
- Wi-Fi—authenticate to the wireless network using iwctl.
[iwd]# device list
[iwd]# device name set-property Powered on
[iwd]# adapter adapter set-property Powered on
[iwd]# station name scan
[iwd]# station name get-networks
[iwd]# station name connect SSID
- Mobile broadband modem—connect to the mobile network with the mmcli utility.
- Configure your network connection:
- DHCP: dynamic IP address and DNS server assignment (provided by systemd-networkd and systemd-resolved) should work out of the box for Ethernet, WLAN, and WWAN network interfaces.
- Static IP address: follow Network configuration#Static IP address.
- The connection may be verified with ping:
# ping archlinux.org
Note: In the installation image, systemd-networkd, systemd-resolved, iwd and ModemManager are preconfigured and enabled by default. These packages and confiugrations in the live environment will not be carried over to the installed system. Persistent network configuration will be done after bootstrapping the base system.
If you’re in a virtual machine or simply prefer the convenience of a terminal with copy and paste capability, you may want to ssh
into your live system. After connecting the system to your network, simply set a password for root to allow ssh connections. ssh
is enabled and preconfiguried by default in the live environment.
# passwd
After entering the temporary root password twice, check the ip address of the system:
# ip addr
Use any other computer to establish an ssh connection. This even works on modern Windows systems:
$ ssh root@192.168.0.143
The authenticity of host '192.168.0.143 (192.168.0.143)' can't be established.
ED25519 key fingerprint is SHA256:5CwrBhtmrYmYq65avb34RyYfcwAdUefgd62+ZhjtnLw.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
In the live environment systemd-timesyncd is enabled by default and time will be synced automatically once a connection to the internet is established.
Use timedatectl(1) to ensure the system clock is synchronized:
# timedatectl
When recognized by the live system, disks are assigned to a block device such as /dev/sda
, /dev/nvme0n1
or /dev/mmcblk0
. To identify these devices, use lsblk
or fdisk
.
# fdisk -l
Remember the disk name. We will need it to create further partitions in the next step. In this guide, I’ll refer to /dev/nvme0n1
since this will apply in most cases when using a modern laptop. Replace it with your actual disk!
After installing Windows, the partition layout should look like this:
Disk /dev/nvme0n1: 953.87 GiB, 1024209543168 bytes, 250051158 sectors
Disk model: KXG8AZNV1T02 LA KIOXIA
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 092DF9B3-AD9A-4BB3-AAE8-DB8E21A569DD
Device Start End Sectors Size Type
/dev/nvme0n1p1 256 77055 76800 300M EFI System
/dev/nvme0n1p2 77056 81151 4096 16M Microsoft reserved
/dev/nvme0n1p3 81152 26295741 26214590 100G Microsoft basic data
/dev/nvme0n1p4 26295808 26500607 204800 800M Windows recovery environment
Figure 1: Current Partition Layout made by Windows
This is a GPT partition table, so we will be using sgdisk to create new partitions. This will allow us to give the partitions names, so we can access them conveniently later.
Figure 2: Partition Layout planned for Arch LinuxPrint the current partition table again using sgdisk to retrieve partition numbers:
# sgdisk -p /dev/nvme0n1
Disk /dev/nvme0n1: 250051158 sectors, 953.9 GiB
Model: KXG8AZNV1T02 LA KIOXIA
Sector size (logical/physical): 4096/4096 bytes
Disk identifier (GUID): 092DF9B3-AD9A-4BB3-AAE8-DB8E21A569DD
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 5
First usable sector is 6, last usable sector is 250051152
Partitions will be aligned on 256-sector boundaries
Total free space is 223550861 sectors (852.8 GiB)
Number Start (sector) End (sector) Size Code Name
1 256 77055 300.0 MiB EF00 EFI system partition
2 77056 81151 16.0 MiB 0C01 Microsoft reserved ...
3 81152 26295741 100.0 GiB 0700 Basic data partition
4 26295808 26500607 800.0 MiB 2700
Create the Linux EFI system partition starting with the next free partition number. In this case 5:
sgdisk --new=5:0:+300MiB --typecode=5:ef00 --change-name=5:linux_esp /dev/nvme0n1
Create the Linux Boot partition with the next free partition number. In this case 6:
sgdisk --new=6:0:+500MiB --typecode=6:8300 --change-name=6:linux_boot /dev/nvme0n1
Create the LUKS partition with the next free partition number. In this case 7:
sgdisk --new=7:0:0 --typecode=7:8309 --change-name=7:linux_crypt /dev/nvme0n1
You can check the typecodes using sgdisk -L
. Check the partitions again using:
# sgdisk -p /dev/nvme0n1
...
Number Start (sector) End (sector) Size Code Name
1 256 77055 300.0 MiB EF00 EFI system partition
2 77056 81151 16.0 MiB 0C01 Microsoft reserved ...
3 81152 26295741 100.0 GiB 0700 Basic data partition
4 26295808 26500607 800.0 MiB 2700
5 26500608 26577407 300.0 MiB EF00 linux_esp
6 26577408 26705407 500.0 MiB 8300 linux_boot
7 26705408 250051152 852.0 GiB 8309 linux_crypt
For some reason, the partition containing the Windows Recovery Environment did not have a label. I added one like this:
# sgdisk --change-name=4:WinRE /dev/nvme0n1
Note: I created two ESP partitions to keep Windows boot files isolated and ensure compatibility with Windows updates or recovery.
Create the encrypted system partition. Note that we explicitly specify LUKS2 as well as our encryption parameters. Open the new encrypted system partition right after creating it.
# cryptsetup luksFormat --type luks2 -s 256 -c aes-xts-plain64 /dev/disk/by-partlabel/linux_crypt
# cryptsetup open /dev/disk/by-partlabel/linux_crypt linux_crypt
Our encrypted container is now mapped to: /dev/mapper/linux_crypt
Create the file system and temporarily mount it to /mnt, so we can create further sub volumes there.
# mkfs.btrfs --label linux_crypt /dev/mapper/linux_crypt
# mount -t btrfs LABEL=linux_crypt /mnt
Create the root sub volume (this will be '/' on the final system)
# btrfs subvolume create /mnt/@root
Create the home directory sub volume (this will hold all user data, ‘/home’ on the final system)
# btrfs subvolume create /mnt/@home
Create a sub volume for snapshot storage (this will hold snapshots, ‘/.snapshots’ on the final system)
# btrfs subvolume create /mnt/@snapshots
Create a sub volume for swap (this will hold the swap file, ‘/swap’ on the final system)
# btrfs subvolume create /mnt/@swap
Unmount root and any possibly mounted sub volumes, so we can remount them with additional options.
# umount -R /mnt
Remount the root sub volume with options. The compression here is optional, zstd
offers the strongest compression but you may prefer a different algorithm for speed (e.g. lzo
) or omit entirely. Check this gist for a detailed comparison.
Only use ssd
if the sub volumes are on an SSD. You can also enable atime if desired, but it comes with some overhead.
You only need to specify additional btrfs options on the first mount. Other sub volumes will inherit these options.
# mount -t btrfs -o defaults,x-mount.mkdir,compress=lzo,ssd,noatime,subvol=@root LABEL=linux_crypt /mnt
Mount the home, snapshots, and swap sub volumes:
# mount -t btrfs -o defaults,x-mount.mkdir,subvol=@home LABEL=linux_crypt /mnt/home
# mount -t btrfs -o defaults,x-mount.mkdir,subvol=@snapshots LABEL=linux_crypt /mnt/.snapshots
# mount -t btrfs -o defaults,x-mount.mkdir,subvol=@swap LABEL=linux_crypt /mnt/swap
Note: It’s safe to enable compression, even though swap does not support it. Btrfs allows to disable compression on a single file (NoCOW attribute). That’s what Btrfs automatically does in the next step.
In the following steps, we will set up a swapfile in the @swap sub volume.
Use Btrfs to create a swap file. I chose 36 GiB since my computer has 32 GiB of RAM and it’s recommended to add some overhead for proper hibernation support:
# btrfs filesystem mkswapfile --size 36G /mnt/swap/swapfile
Secure the swap file by restricting access. Btrfs should’ve done this by default, but we can check again, if permissions were set correctly:
# ls -lisha /mnt/swap/swapfile
If the permissions aren’t -rw-------
and owner root
, we can set them with chmod:
# chmod 600 /mnt/swap/swapfile
Format the file as swap:
# mkswap /mnt/swap/swapfile
Enable the Swap File:
# swapon /mnt/swap/swapfile
Confirm that the swap is active and check the free space:
# swapon –show
# free -h
Note: The size of the swap file depends on your RAM and usage needs. A rule of thumb: For hibernation: Swap size >= RAM size. For general use: 2–4 GiB is usually sufficient.
Format the boot partition as ext4, with the label linux_boot
# mkfs.ext4 /dev/disk/by-partlabel/linux_boot
Create the mount directory and mount it:
# mkdir -p /mnt/boot
# mount /dev/disk/by-partlabel/linux_boot /mnt/boot
Format the partition as FAT-32, with label linux_esp
# mkfs.fat -F32 -n EFI /dev/disk/by-partlabel/linux_esp
Create the mount directory and mount it:
# mkdir -p /mnt/boot/efi
# mount /dev/disk/by-partlabel/linux_esp /mnt/boot/efi
Before installing the base system, make sure all the mounts are there.
# mount | grep boot
Example output:
tmpfs on /run/credentials/systemd-firstboot.service type tmpfs (ro,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap)
/dev/nvme0n1p6 on /mnt/boot type ext4 (rw,relatime)
/dev/nvme0n1p5 on /mnt/boot/efi type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)
# mount | grep btrfs
Example output:
/dev/mapper/linux_crypt on /mnt type btrfs (rw,noatime,compress=lzo,ssd,space_cache=v2,subvolid=256,subvol=/@root,x-mount.mkdir)
/dev/mapper/linux_crypt on /mnt/home type btrfs (rw,relatime,compress=lzo,ssd,space_cache=v2,subvolid=257,subvol=/@home,x-mount.mkdir)
/dev/mapper/linux_crypt on /mnt/.snapshots type btrfs (rw,relatime,compress=lzo,ssd,space_cache=v2,subvolid=258,subvol=/@snapshots,x-mount.mkdir)
/dev/mapper/linux_crypt on /mnt/swap type btrfs (rw,relatime,compress=lzo,ssd,space_cache=v2,subvolid=259,subvol=/@swap,x-mount.mkdir)
Looks good! So let’s bootstrap the base system. You can substitute a different kernel here if desired.
# pacstrap /mnt base linux linux-firmware
Generate the file system table. Unlike the default installation guide, we choose to use labels instead of UUIDs for mounts.
# genfstab -L -p /mnt >> /mnt/etc/fstab
Finally check the resulting fstab
-file by printing it:
# cat /mnt/etc/fstab
Example fstab:
# Static information about the filesystems.
# See fstab(5) for details.
# <file system> <dir> <type> <options> <dump> <pass>
# /dev/mapper/linux_crypt UUID=52613eed-75d4-4c66-9868-5dcd1bce66c8
LABEL=linux_crypt / btrfs rw,noatime,compress=lzo,ssd,space_cache=v2,subvol=/@root 0 0
# /dev/mapper/linux_crypt UUID=52613eed-75d4-4c66-9868-5dcd1bce66c8
LABEL=linux_crypt /home btrfs rw,relatime,compress=lzo,ssd,space_cache=v2,subvol=/@home 0 0
# /dev/mapper/linux_crypt UUID=52613eed-75d4-4c66-9868-5dcd1bce66c8
LABEL=linux_crypt /.snapshots btrfs rw,relatime,compress=lzo,ssd,space_cache=v2,subvol=/@snapshots 0 0
# /dev/mapper/linux_crypt UUID=52613eed-75d4-4c66-9868-5dcd1bce66c8
LABEL=linux_crypt /swap btrfs rw,relatime,compress=lzo,ssd,space_cache=v2,subvol=/@swap 0 0
# /dev/nvme0n1p6 UUID=9e08a044-e7f7-4bd8-93ec-4323b2439287
/dev/nvme0n1p6 /boot ext4 rw,relatime 0 2
# /dev/nvme0n1p5 UUID=07C5-D362
LABEL=EFI /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=rem>
/swap/swapfile none swap defaults 0 0
Change root into the new system:
# arch-chroot /mnt
# pacman -Syu networkmanager base-devel btrfs-progs gptfdisk nano zsh sudo ttf-dejavu sbctl amd-ucode polkit man-db
Make sure to select the right microcode package *-ucode
for your architecture.
I chose NetworkManager since I will primarily be using GNOME on Wayland and hyprland. NetworkManager is neatly integrated in GNOME with an applet, which can easily be added to hyprbar
as well. The applet allows us to quickly connect to a WiFi, set up WWAN or set static IP addresses on interfaces.
Set the time zone (replace area and city according to your needs):
# ln -sf /usr/share/zoneinfo/Europe/Zurich /etc/localtime
Run hwclock(8) to generate /etc/adjtime
:
# hwclock --systohc
This command assumes the hardware clock is set to UTC
. To prevent clock drift and ensure accurate time, set up time synchronization using a Network Time Protocol (NTP) client such as systemd-timesyncd
.
I use a swiss german keyboard but I prefer US english interfaces and formats. Adjust them to your needs!
Edit /etc/locale.gen
and uncomment appropriate locales. I only chose en_US.UTF-8 UTF-8
. Then generate the locales by running:
# locale-gen
Create the locale.conf(5) file, and set the LANG
and optionally LC_ALL
variable accordingly:
/etc/locale.conf
LANG="en_US.UTF-8"
LC_ALL="en_US.UTF-8"
If you set the console keyboard layout earlier, make the changes persistent in vconsole.conf(5):
/etc/vconsole.conf
KEYMAP=de_CH-latin1
Create the /etc/hostname
file. The string you write to this file will be your computers identifier in certain network scenarios and it will be shown in your bash prompt.
# echo potato > /etc/hostname
Set the root password:
# passwd
Creating a new initramfs
is usually not required, because mkinitcpio was run on installation of the kernel package with pacstrap. Since we’re using btrfs
and LUKS2
, we will add correspondig HOOKS
to /etc/mkinitcpio.conf
, then recreate the iniramfs
.
Add encrypt
, btrfs
, and resume
between filesystems
and fsck
.
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block filesystems encrypt btrfs resume fsck)
Afterwards, recreate the initramfs
image:
# mkinitcpio -P
Run the following command to install the GRUB package and additional tools.
# pacman -S grub efibootmgr dosfstools os-prober mtools memtest86+
Install GRUB on the ext4
Partition (linux_boot
) and efi binaries on the fat32
partition (linux_esp
).
# grub-install --target=x86_64-efi --efi-directory=/boot/efi --boot-directory=/boot --bootloader-id='GRUB'
--efi-directory
: Specifies where the GRUB EFI executable will be placed (on linux_esp).--boot-directory
: Points to where GRUB's files (grub.cfg
, etc.) will be located (on linux_boot).--bootloader-id
: Creates an entry in the EFI firmware under the name "GRUB"
Now we need to point the machines EFI boot manager (NVRAM) to use linux_esp as the starting point. Add a boot entry:
# efibootmgr --create --disk /dev/nvme0n1 --part 5 --label "Arch Linux GRUB" --loader "\EFI\GRUB\grubx64.efi"
--disk /dev/nvme0n1
: Specifies the disk containing the EFI partition.--part 5
: Refers to the EFI partition (linux_esp).--loader "\EFI\GRUB\grubx64.efi"
: Path to the GRUB binary in the EFI partition.
To be able to unlock the LUKS container, we need to set or update the GRUB_CMDLINE_LINUX
entry in /etc/default/grub
with the following parameters:
GRUB_CMDLINE_LINUX="cryptdevice=LABEL=linux_crypt:linux_crypt root=/dev/mapper/linux_crypt rootflags=subvol=@root rw"
We don’t necessarily need to install and use os-prober
. Let’s proceed with a manual entry for Windows instead:
/etc/grub.d/40_custom
if [ "${grub_platform}" == "efi" ]; then
menuentry "Windows 11 Pro" {
insmod part_gpt
insmod fat
insmod search_fs_uuid
insmod chain
# After --set=root, add the Windows EFI partition's UUID.
# (can be found with "blkid" command)
search --fs-uuid --set=root A61F-FF49
chainloader /EFI/Boot/bootx64.efi
}
fi
search --fs-uuid --set=root
: The--set=root
command sets the root partition for the chainloader. You can find this UUID usingblkid
orlsblk -f
.chainloader
: points to the Windows boot loader.
Now we need to write these changes to our boot partition. It is important to note, that the grub.cfg
file is generated by grub-mkconfig
and should not be edited manually. To apply the settings made in the etc files, we need to run grub-mkconfig
again:
grub-mkconfig -o /boot/grub/grub.cfg
Exit the chroot environment by typing exit
or pressing Ctrl + d
.
Disconnect swap:
swapoff /mnt/swap/swapfile
Optionally manually unmount all the partitions with umount -R /mnt
: this allows noticing any "busy" partitions, and finding the cause with fuser(1).
Finally, restart the machine by typing reboot
: any partitions still mounted will be automatically unmounted by systemd
. Remember to remove the installation medium and then select our newly created EFI boot entry Arch Linux GRUB
. In the GRUB menu, select Arch Linux
to boot into the system. Enter the LUKS password when prompted. Then log in as root with the password you set earlier.
If the system does not boot as expected, refer to the 5. Troubleshooting
section of this guide.
We earlier installed NetworkManager
, so you should already have an internet connection when connected with a cable and DHCP available on the network. If not, we need to enable and start the service:
# systemctl enable NetworkManager
# systemctl start NetworkManager
If you depend on WiFi, use nmcli
to connect to the wireless network again:
# nmcli c up id ‘wifi-ssid’ –ask
You don’t want to browse the web or check your emails as the root user. So let’s create a separate user login which can elevate commands using sudo. We earlier installed sudo, so it’s ready to configure and use.
Let’s enable sudo for the group wheel
. Open the sudoers file with visudo
. If you're not familiar with vi
, you can change the editor to something (e.g. nano
) by setting the EDITOR
environment variable right before running visudo
:
# EDITOR=nano visudo
Scroll to the bottom of the file and uncomment the following line:
%wheel ALL=(ALL:ALL) ALL
Save and exit the editor. Then create a new user and add it to the group wheel. I created the user n0c
:
# useradd -m -G wheel -s /bin/bash n0c
Finally set the users password:
# passwd n0c
If you want to use GNOME as the default desktop environment, follow these steps:
# pacman -S gnome gdm
Then enable the gdm
service to autostart GNOME. You may immediately start the service afterwards to get into GNOME without a reboot.
# systemctl enable gdm
# systemctl start gdm
Note: When logging in to GNOME, there might be a wrong keyboard layout selected. Once started, go to GNOME settings and set your preferred keyboard layout there as well.
We're done with the basic setup. Happy hacking!
In case anything went wrong and something is missing after the reboot (e.g. no network connection, missing mount points, missing partitions, erroneous bootloader, whatever), you can always get back into the live environment and fix things from there.
- Boot into the live system again (step 4.1.)
- Optionally: Set keyboard layout and font again (step 4.2.) and connect to the internet (step 4.4.)
- Do not delete any partitions or sub volumes already created (unless something is wrong with them) but do all the mounts and
cryptsetup open
in above mentioned order until you’re at the point, where you suspect something went wrong. - If you’re still unsure where the mistake happened, you can unmount everything and recreate all the partitions and sub volumes, starting from step 4.7.
If you’re still stuck, you can always ask for help in the Arch Linux Forums or on the Arch Linux subreddit. Or kindly ask here in the comments. If anything is unclear or you have suggestions for improvements, please let me know!
After some updates and further tinkering, the Bootloader stopped asking for the encryption password in my case. For some reason, the Partition Label could not be resolved. To fix this, I had to change the GRUB_CMDLINE_LINUX
entry in /etc/default/grub
to use the UUID of the encrypted partition. You can find the UUID with blkid
. The entry will then look like this:
GRUB_CMDLINE_LINUX="cryptdevice=UUID=7fab1...7117:linux_crypt root=/dev/mapper/linux_crypt rootflags=subvol=@root"
Especially terminal inputs were lagging behind. When typing fast, the terminal would not keep up with the input. I solved this issue by lowering the refresh rate of the display from 120Hz to 60Hz. This can be done in the Gnome settings under "Displays". This might not be the most elegant solution, but it worked for me.
It seems like the T14 Gen5 AMD is still in its early stages of linux support. One of the issues I encountered was that the laptop did not suspend properly and drained the battery. Literally, like 50% in 2-3 hours. To fix this, I had to add the following kernel parameters to /etc/default/grub
, then regenerate the grub.cfg
using grub-mkconfig -o /boot/grub/grub.cfg
:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash acpi.ec_no_wakeup=1"
- v0.2.1, 2024-12-15: Added further troubleshooting steps for Lenovo ThinkPad T14 Gen5 AMD
- v0.2, 2024-11-16: Installation on a Lenovo ThinkPad T14 Gen5 AMD
- Completely revised the guide according to the Arch Linux Wiki Installation Guide, added more detailed explanations
- Added an illustration representing the partition layout
- Added a change log
- v0.1, 2022-10-15: Installation on a Dell Latitude 7390
- Initial version
As of v0.2, this guide is mainly based on the following sources:
- Arch Linux Wiki: Official Installation Guide: The official guide for installing Arch Linux.
- Zach Hilman’s Guide: Covers Btrfs and LUKS2, including Secure Boot options.
- mjnaderi’s Guide: Details further installation steps involving encryption and UEFI.
Additional steps, were taken from various Arch Linux Wiki pages and the Microsoft Documentation.