rss logo

My ArchLinux installation guide

ArchLinux logo

I will describe how I install ArchLinux on my personal desktop. Hopefully, this guide will prove useful not only to others but also to you!

However, when it comes to servers, I prefer using Debian instead of ArchLinux. But that's a different topic altogether.

Note: This tutorial draws significant inspiration from the official installation guide: https://wiki.archlinux.org.

Installation medium

  • First, download the ISO media from the official download webpage (refer to here to verify the signature):

https://archlinux.org/download/

  • Identify the USB media:
[root@host ~]# fdisk -l
  • Personally, I create a USB boot media:
[root@host ~]# dd if=archlinux-XXXX.XX.XX-x86_64.iso of=/dev/sdX bs=16M status=progress; sync
  • Disable UEFI secure boot (since the installation media does not support this feature) and boot from the USB drive.

Pre-Install

  • Set the console keyboard layout (e.g., fr for French, us for US, de for German, etc.):
root@archiso ~ # loadkeys fr
  • Verify that we are in UEFI boot mode:
root@archiso ~ # if [ -d /sys/firmware/efi/efivars ]; then echo "UEFI OK"; else echo "UEFI KO"; fi

Network Configuration

  • List and identify network interfaces:
root@archiso ~ # ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000 link/ether 00:50:56:80:0b:32 brd ff:ff:ff:ff:ff:ff altname enp11s0
  • Obtain network configuration via DHCP:
root@archiso ~ # dhclient ens192
  • Or set IP manually:
root@archiso ~ # ip addr add 192.168.1.10/24 dev ens192 root@archiso ~ # ip route add default via 192.168.1.254 root@archiso ~ # echo 'nameserver 192.168.1.254' >> /etc/resolv.conf
  • Check internet connectivity:
root@archiso ~ # ping 46.105.57.169
  • Check name resolution:
root@archiso ~ # host std.rocks std.rocks has address 46.105.57.169 std.rocks has IPv6 address 2001:41d0:301::20 std.rocks mail is handled by 1 mx4.mail.ovh.net. std.rocks mail is handled by 10 mx3.mail.ovh.net. Note: From this step, if necessary, you can log in to the installation program as root via SSH from another machine. Just use the "passwd" command beforehand to set a password.
  • Update the system clock:
root@archiso ~ # timedatectl set-ntp true

Partition the disk

I will partition my 40GB disk as follows:

Partition Note Filesystem Size
EFI EFI partition FAT32 512M
/boot Boot partition ext2 500M
swap Swap partition Swap on LUKS 2G
/ Root partition Btrfs on LUKS 37G
  • The graphical view of the disk partitioning:
A Linux disk partitioned with EFI, boot, swap, and root partitions

⚠️ Please note that the sda disk will be completely erased, resulting in data loss. ⚠️

  • Identify the destination disk:
root@archiso ~ # fdisk -l Disk /dev/sda: 40 GiB, 42949672960 bytes, 83886080 sectors Disk model: Virtual disk Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk /dev/loop0: 683.24 MiB, 716427264 bytes, 1399272 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes
  • Start partitioning, using the /dev/sda device:
root@archiso ~ # gdisk /dev/sda GPT fdisk (gdisk) version 1.0.9 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT.
  • Delete existing partitions:
Command (? for help): d
  • Create the EFI partition:
Command (? for help): n Partition number (1-128, default 1): First sector (34-83886046, default = 2048) or {+-}size{KMGTP}: Last sector (2048-83886046, default = 83884031) or {+-}size{KMGTP}: +512M Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): EF00 Changed type of partition to 'EFI system partition'
  • Create the /boot partition:
Command (? for help): n Partition number (2-128, default 2): First sector (34-83886046, default = 1050624) or {+-}size{KMGTP}: Last sector (1050624-83886046, default = 83884031) or {+-}size{KMGTP}: +500M Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to 'Linux filesystem'
  • Create the encrypted swap partition:
Command (? for help): n Partition number (3-128, default 3): First sector (34-83886046, default = 2074624) or {+-}size{KMGTP}: Last sector (2074624-83886046, default = 83884031) or {+-}size{KMGTP}: +2G Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): 8309 Changed type of partition to 'Linux LUKS'
  • Create the encrypted / partition:
Command (? for help): n Partition number (4-128, default 4): First sector (34-83886046, default = 6268928) or {+-}size{KMGTP}: Last sector (6268928-83886046, default = 83884031) or {+-}size{KMGTP}: Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): 8309 Changed type of partition to 'Linux LUKS'
  • Check and write the partitions to the disk:
Command (? for help): p Disk /dev/sda: 83886080 sectors, 40.0 GiB Model: Virtual disk Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 45AB06C7-DDAF-45D4-A781-B5C33DAF56D2 Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 83886046 Partitions will be aligned on 2048-sector boundaries Total free space is 4029 sectors (2.0 MiB) Number Start (sector) End (sector) Size Code Name 1 2048 1050623 512.0 MiB EF00 EFI system partition 2 1050624 2074623 500.0 MiB 8300 Linux filesystem 3 2074624 6268927 2.0 GiB 8309 Linux LUKS 4 6268928 83884031 37.0 GiB 8309 Linux LUKS Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): Y OK; writing new GUID partition table (GPT) to /dev/sda. The operation has completed successfully.

Format the partitions

  • Format the EFI partition:
root@archiso ~ # mkfs.fat -F32 /dev/sda1
  • Format the /boot partition:
root@archiso ~ # mkfs.ext2 /dev/sda2
  • Create a LUKS partition for the swap:
Note: The complexity of the password will not be important here because we will use a random password for the swap partition afterwards. root@archiso ~ # cryptsetup luksFormat /dev/sda3 WARNING! ======== This will overwrite data on /dev/sda3 irrevocably. Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /dev/sda3: STDp@$$ Verify passphrase: STDp@$$ cryptsetup luksFormat /dev/sda3 16.55s user 1.08s system 86% cpu 20.303 total
  • Decrypt the swap partition:
root@archiso ~ # cryptsetup luksOpen /dev/sda3 swap Enter passphrase for /dev/sda3: STDp@$$
  • Check if the swap device is present:
root@archiso ~ # ls /dev/mapper control swap
  • Format the swap device:
root@archiso ~ # mkswap /dev/mapper/swap
  • Create a LUKS partition for /:
root@archiso ~ # cryptsetup luksFormat /dev/sda4 WARNING: Device /dev/sda4 already contains a 'dos' partition signature. WARNING! ======== This will overwrite data on /dev/sda4 irrevocably. Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /dev/sda4: ComplexSTDp@$$ Verify passphrase: ComplexSTDp@$$ cryptsetup luksFormat /dev/sda4 9.72s user 0.68s system 75% cpu 13.721 total
  • Decrypt the / (root) partition:
root@archiso ~ # cryptsetup luksOpen /dev/sda4 root Enter passphrase for /dev/sda3: ComplexSTDp@$$
  • Check if the root device is present:
root@archiso ~ # ls /dev/mapper control root swap
  • Format the / (root) partition:
root@archiso ~ # mkfs.btrfs /dev/mapper/root

Mount the file system and chroot to /mnt/

Mount to /mnt

  • Mount the / (root) partition:
root@archiso ~ # mount /dev/mapper/root /mnt/
  • Enable the swap partition:
root@archiso ~ # swapon /dev/mapper/swap
  • Mount the /boot partition:
root@archiso ~ # mount --mkdir /dev/sda2 /mnt/boot
  • Mount the /efi partition:
root@archiso ~ # mount --mkdir /dev/sda1 /mnt/efi
Create Btrfs subvolumes (Optional)

If necessary, we can add Btrfs subvolumes at this point. For example, let's create a /home subvolume:

  • Create the /home subvolume:
root@archiso ~ # btrfs subvolume create /mnt/home
  • Mount the /home subvolume:
root@archiso ~ # mount /dev/mapper/root -o subvol=home /mnt/home

Install

Install essential packages

  • Install essential packages:
root@archiso ~ # pacstrap /mnt base linux linux-firmware btrfs-progs vim grub efibootmgr
  • Generate the fstab file:
root@archiso ~ # genfstab -U /mnt >> /mnt/etc/fstab
  • Edit the /mnt/etc/fstab file and replace the swap entry with this line:
/dev/mapper/swap none swap defaults 0 0
  • Chroot to /mnt:
root@archiso ~ # arch-chroot /mnt

Time zone

  • Identify your Time zone:
[root@archiso /]# ls /usr/share/zoneinfo/
  • Set your Time zone:
[root@archiso /]# ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
  • Example:
[root@archiso /]# ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
  • Generate the /etc/adjtime file:
[root@archiso /]# hwclock --systohc

Localization

  • Edit the /etc/locale.gen file and uncomment the en_US.UTF-8 UTF-8 line, along with any other needed locales. For example:
[…] #en_SG ISO-8859-1 en_US.UTF-8 UTF-8 #en_US ISO-8859-1 […] #fr_CH ISO-8859-1 fr_FR.UTF-8 UTF-8 #fr_FR ISO-8859-1
  • Generate the locales:
[root@archiso /]# locale-gen
  • Create the /etc/locale.conf file and set the LANG variable accordingly:
    • For example:
[root@archiso /]# echo 'LANG=en_US.UTF-8' > /etc/locale.conf [root@archiso /]# echo 'LANG=fr_FR.UTF-8' > /etc/locale.conf
  • Set keyboard layout:
    • For examples:
[root@archiso /]# echo 'KEYMAP=fr' > /etc/vconsole.conf [root@archiso /]# echo 'KEYMAP=us' > /etc/vconsole.conf

Network configuration

  • Set the hostname:
[root@archiso /]# echo 'stdesktop' > /etc/hostname

Initramfs

  • Edit the /etc/mkinitcpio.conf file to enable luks (to decrypt encrypted devices):
MODULES=(dm_mod ext2 btrfs ext4 xfs) […] #add lvm2, mdadm if needed HOOKS=(base udev autodetect modconf block keyboard keymap encrypt filesystems usr fsck shutdown)
  • Generate a new initramfs:
[root@archiso /]# mkinitcpio -P
  • Add the swap entry in the /etc/crypttab file to set a random key for the encrypted swap partition:
[root@archiso /]# echo 'swap /dev/sda3 /dev/urandom swap,cipher=aes-cbc-essiv:sha256,size=256' >> /etc/crypttab

Boot Loader

  • Edit the /etc/default/grub file. Here, you can:
    • Use amdgpu.audio=0 to disable HDMI/DP Audio if it is not needed. (See complete module parameters here).
    • Specify your crypted root device as /dev/sda4:root.
    • Remove the quiet option if you prefer a verbose boot for debugging purposes.
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 amdgpu.audio=0" #we can use /dev/sda4 UUID like that: cryptdevice=UUID=XXXX-XXXX-XXXX:root if we prefer GRUB_CMDLINE_LINUX="cryptdevice=/dev/sda4:root"
  • Install the GRUB EFI application to /efi/ (sda1):
[root@archiso /]# grub-install --target=x86_64-efi --efi-directory=/efi/ --bootloader-id=GRUB Installing for x86_64-efi platform. Installation finished. No error reported.
  • Generate the main configuration file grub.cfg:
[root@archiso /]# grub-mkconfig -o /boot/grub/grub.cfg Generating grub configuration file ... Found linux image: /boot/vmlinuz-linux Found initrd image: /boot/initramfs-linux.img Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img Warning: os-prober will not be executed to detect other bootable partitions. Systems on them will not be added to the GRUB boot configuration. Check GRUB_DISABLE_OS_PROBER documentation entry. Adding boot menu entry for UEFI Firmware Settings ... done

Reboot

  • Set the root password:
[root@archiso /]# passwd
  • Remove the boot media and reboot the system:
[root@archiso /]# exit root@archiso ~ # reboot

Post-Install

Add a user

  • Create a new user:
[root@stdesktop ~]# useradd -m newuser
  • Set a password for the new user:
[root@stdesktop ~]# passwd newuser

Network

We can configure the network manually, statically, or via DHCP.

  • The first thing to do is identify your network interface:
[root@stdesktop ~]# ip link show 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 24:1f:fe:d3:bc:2a brd ff:ff:ff:ff:ff:ff

Manually with ip commands

Note: This configuration will be reset after each reboot.

  • Enable the network interface:
[root@stdesktop ~]# ip link set ens192 up
  • Set the IP address:
[root@stdesktop ~]# ip addr add 192.168.1.10/24 dev ens192
  • Set the gateway:
[root@stdesktop ~]# ip route add default via 192.168.1.254
  • Set the DNS:
[root@stdesktop ~]# echo 'nameserver 80.67.169.12' > /etc/resolv.conf

Statically with systemd-networkd

  • Create a /etc/systemd/network/ens192.network file:
[Match] Name=ens192 [Network] Address=192.168.1.10/24 Gateway=192.168.1.254 DNS=192.168.1.254
  • Enable and start the systemd-networkd service:
[root@stdesktop ~]# systemctl enable systemd-networkd.service && systemctl start systemd-networkd.service

DHCP with systemd-networkd

  • Create a /etc/systemd/network/ens192.network file:
[Match] Name=ens192 [Network] DHCP=yes
  • Enable and start the systemd-networkd service:
[root@stdesktop ~]# systemctl enable systemd-networkd.service && systemctl start systemd-networkd.service

Desktop environment

  • Install GNOME (simply press enter to each question):
[root@stdesktop ~]# pacman -S gnome
  • If you are not using the qwerty keyboard layout, set the gdm keyboard layout according to your language:
[root@stdesktop ~]# localectl set-x11-keymap fr
  • Enable and start the gdm service:
[root@stdesktop ~]# systemctl enable gdm [root@stdesktop ~]# systemctl start gdm archlinux gdm screen waiting to log in

Misc

Hardware acceleration for the AMD FirePro W5000

If you have an AMD FirePro W5000, you may want to enable hardware video acceleration.

  • Install the libva-mesa-driver and mesa-vdpau packages:
[root@stdesktop ~]# pacman -S libva-mesa-driver mesa-vdpau
  • Install the vainfo, vdpauinfo, and radeontop tools:
[root@stdesktop ~]# pacman -S libva-utils vdpauinfo radeontop
  • Create the /etc/modprobe.d/amdgpu.conf file:
options amdgpu si_support=1
  • Create the /etc/modprobe.d/radeon.conf file:
options radeon si_support=0 options radeon cik_support=0
  • Edit the /etc/mkinitcpio.conf file:
MODULES=(dm_mod ext2 btrfs ext4 xfs amdgpu) [...] HOOKS=(base udev autodetect modconf block keyboard keymap encrypt lvm2 filesystems usr fsck shutdown)
  • Generate a new initramfs:
[root@archiso /]# mkinitcpio -P
  • Reboot and check if the amdgpu driver is loaded:
[newuser@stdesktop ~]$ lspci -k | grep -A 3 -E "(VGA|3D)" 01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Pitcairn LE GL [FirePro W5000] Subsystem: Advanced Micro Devices, Inc. [AMD/ATI] Device 0b06 Kernel driver in use: amdgpu Kernel modules: radeon, amdgpu
  • Add the VDPAU_DRIVER environment variable:
[newuser@stdesktop ~]$ echo 'export VDPAU_DRIVER=radeonsi' >> ~/.bashrc
  • Verify VA-API:
[newuser@stdesktop ~]$ vainfo vainfo: VA-API version: 1.15 (libva 2.15.0) vainfo: Driver version: Mesa Gallium driver 22.1.7 for ATI FirePro V(FireGL V) Graphics Adapter (pitcairn, LLVM 14.0.6, DRM 3.47, 5.19.9-arch1-1) vainfo: Supported profile and entrypoints VAProfileMPEG2Simple : VAEntrypointVLD VAProfileMPEG2Main : VAEntrypointVLD VAProfileVC1Simple : VAEntrypointVLD VAProfileVC1Main : VAEntrypointVLD VAProfileVC1Advanced : VAEntrypointVLD VAProfileH264ConstrainedBaseline: VAEntrypointVLD VAProfileH264Main : VAEntrypointVLD VAProfileH264High : VAEntrypointVLD VAProfileNone : VAEntrypointVideoProc
  • Verify VDPAU:
[newuser@stdesktop ~]$ vdpauinfo display: :0 screen: 0 API version: 1 Information string: G3DVL VDPAU Driver Shared Library version 1.0 Video surface: name width height types ------------------------------------------- 420 16384 16384 NV12 YV12 422 16384 16384 UYVY YUYV 444 16384 16384 Y8U8V8A8 V8U8Y8A8 420_16 16384 16384 422_16 16384 16384 444_16 16384 16384 Decoder capabilities: […]

Open applications at login

When logging in, you can have your most frequently used applications open automatically.

  • Create the ~/.config/autostart/ folder:
[newuser@stdesktop ~]$ mkdir ~/.config/autostart
  • Create the ~/.config/autostart/apps.desktop file:
[Desktop Entry] Name=AutostartScript GenericName=Gnome Auto Start Script Comment=Script wich launch applications at startup Exec=/home/newuser/.config/autostart.sh Terminal=false Type=Application X-GNOME-Autostart-enabled=true
  • Create the ~/.config/autostart.sh file:
#Open terminal gnome-terminal& #Open Firefox firefox & #Open Explorer nautilus&
  • Add execution rights:
[newuser@stdesktop ~]$ chmod +x ~/.config/autostart.sh

Crontab

I usually use cron as a task scheduler. While there are implementations of cron in ArchLinux, none of them are pre-installed. By default, the base system uses systemd/Timers. Here, we will see how to create a systemd/Timers task.

  • Create a /etc/systemd/system/mytask.service file that will run a program (in this example, we copy /home/newuser/a_file to a /backup location using the date command substitution):
[Unit] Description=Copy a file Wants=mytask.timer [Service] Type=oneshot User=newuser #Normaly $(/usr/bin/date +%Y%m%d) but $ and % need to be escaped ExecStart=/bin/bash -c '/usr/bin/cp /home/newuser/a_file /backup/a_file.$$(/usr/bin/date +%%Y%%m%%d)' [Install] WantedBy=multi-user.target
  • Create the associated /etc/systemd/system/mytask.timer file where we will set the trigger:
[Unit] Description=Copy a file trigger Requires=mytask.service [Timer] Unit=mytask.service #It will run each day at 19h00 OnCalendar=*-*-* 19:00:00 [Install] WantedBy=timers.target
  • Enable the timer and reload the systemd configuration:
[root@stdesktop ~]# systemctl enable mytask.timer && systemctl daemon-reload
  • Check the status of mytask.timer:
[root@stdesktop ~]# systemctl status mytask.timer ● mytask.timer - Copy a file Loaded: loaded (/etc/systemd/system/mytask.timer; enabled; preset: disabled) Active: active (waiting) since Sun 2022-09-25 16:28:31 CEST; 26min ago Until: Sun 2022-09-25 16:28:31 CEST; 26min ago Trigger: Sun 2022-09-25 19:00:00 CEST; 2h 4min left Triggers: ● mytask.service sept. 25 16:28:31 stddesktop.local systemd[1]: Started Copy a file.

References

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :

contact mail address