Skip to content

installation

Arch Installation

(I) Create a bootable USB

There are 2 method. If you don't care about the utilizing the rest of the space on the usb you can use plain dd:

dd if=/home/vector/Downloads/archlinux-2024.10.01-x86_64.iso of=/dev/sda status=progress oflag=sync bs=4M

Or you can do it manually like so:

First partition the usb drive with fdisk, MBR partitioning scheme doesn't matter, you can still boot the USB in UEFI mode.

Try to get this partitioning scheme (this was how a working bootable arch usb created using rufus looked like in fdisk):

1740930709.png

Note that the type is W95 Fat32 (LBA). Also toggle the bootable flag to enabled in fdisk with a.

mkfs.fat -F32 /dev/sda1
mount /dev/disk/by-id/usb-SanDisk_Ultra_4C531001470309118144-0:0-part1 /mnt
bsdtar -x -f ~/Downloads/archlinux-2024.10.01-x86_64.iso -C /mnt
sync
umount /mnt
syslinux --directory boot/syslinux --install /dev/disk/by-id/usb-SanDisk_Ultra_4C531001470309118144-0:0-part1
dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/bios/mbr.bin of=/dev/disk/by-id/usb-SanDisk_Ultra_4C531001470309118144-0:0

(II) Prepare for booting into the usb

This is just general advice. You can skip it.

If you plan to connect to the internet via wifi, create a wpa_supplicant.conf in your bootable usb, this will prove handy after you've booted into the usb.

wpa_supplicant.conf
1
2
3
4
5
6
7
ctrl_interface=/run/wpa_supplicant
update_config=1

network={
    ssid="WifiSSID"
    psk="WifiPassword"
}

Copy some files over. This is to make your insallation process a lot smoother.

mount /dev/sda1 /mnt/vector
cp /etc/wpa_supplicant/wpa_supplicant.conf /mnt/vector
cp -r ~/.ssh /mnt

Remember the permission for ssh (700 for the .ssh folder and 600 for the private file, and 644 for authorized_keys).

(III) Boot into Live USB

Get internet access:

# reveals your wifi device (mine is wlp3s0)
ip link 
wpa_supplicant -B -i wlp3s0 -c wpa_supplicant.conf
# to check if you've internet. might need to wait for dhcpcd
ip addr

Set keybindings (I want left caps to be ctrl)

sudo pacman -S keyd
cd /etc/keyd
lftp -c "mirror --parallel=100 https://configs.vectorspace.xyz/keyd ;exit"
mv keyd/default.conf ./
rm -rf keyd
systemctl start keyd

/etc/keyd/default.conf
1
2
3
4
5
6
7
8
[ids]

*

[main]

# Maps capslock to escape when pressed and control when held.
capslock = overload(control, esc)

You can fetch a simple tmux.conf file from my site with:

lftp -c "mirror --parallel=100 https://configs.vectorspace.xyz/tmux ;exit"

With the below tmux conf you can enter "visual mode" with <C-b>[. You can select and then copy selection with y.

tmux.conf
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

set -g mode-keys vi
bind-key -T copy-mode-vi 'v' send -X begin-selection
bind-key -T copy-mode-vi 'C-v' send -X rectangle-toggle
bind-key -T copy-mode-vi 'y' send -X copy-selection

bind-key -T copy-mode-vi v

(IV) Partition drives

In these instructions I'm installing arch into the drive /dev/sdb.

After partition of sdb:

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda           8:0    0 931.5G  0 disk
└─sda1        8:1    0 931.5G  0 part
sdb           8:16   0 465.8G  0 disk
├─sdb1        8:17   0     1G  0 part
├─sdb2        8:18   0     4G  0 part
└─sdb3        8:19   0 460.8G  0 part
nvme0n1     259:0    0 476.9G  0 disk
├─nvme0n1p1 259:1    0     1G  0 part /boot
├─nvme0n1p2 259:2    0     8G  0 part [SWAP]
└─nvme0n1p3 259:3    0 467.9G  0 part /
Partition scheme:
Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         2099199   1024.0 MiB  EF00  EFI system partition
   2         2099200        10487807   4.0 GiB     8200  Linux swap
   3        10487808       976769023   460.8 GiB   8300  Linux filesystem

(V) Cryptsetup: Encryption

Optional (read more at archwiki):

dd if=/dev/urandom of=/dev/sdb3 bs=4096 iflag=fullblock status=progress

cryptsetup luksFormat /dev/sdb3
cryptsetup open /dev/sdb3 root

Check the result of lsblk. Note the name root under sdb3 which we used in earlier cryptsetup open command. Now this partition is available for mounted at /dev/mapper/root, but it has to be formatted with a file system first.

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda           8:0    0 931.5G  0 disk
└─sda1        8:1    0 931.5G  0 part
sdb           8:16   0 465.8G  0 disk
├─sdb1        8:17   0     1G  0 part
├─sdb2        8:18   0     4G  0 part
└─sdb3        8:19   0 460.8G  0 part
  └─root    253:0    0 460.7G  0 crypt
nvme0n1     259:0    0 476.9G  0 disk
├─nvme0n1p1 259:1    0     1G  0 part  /boot
├─nvme0n1p2 259:2    0     8G  0 part  [SWAP]
└─nvme0n1p3 259:3    0 467.9G  0 part  /

You can find this device in /dev/mapper/root.

(VI) Format partitions

mkfs.fat -F32 /dev/sdb1
mkswap /dev/sdb2
# mkfs.ext4 /dev/mapper/root
mkfs.btrfs /dev/mapper/root

(VII) Mount partitions, create subvolume in btrfs partition, pacstrap and genfstab

mount /dev/mapper/root /mnt
cd /mnt
btrfs subvolume create root
umount /mnt

Note

You had to mount the btrfs partition and cd into it to create the subvolumes.

# https://youtu.be/Qgg5oNDylG8?t=1379
# pay special attention that you mention the subvol with 
mount -o noatime,ssd,compress=zstd,space_cache=v2,discard=async,subvol=root /dev/mapper/root /mnt
## https://gist.github.com/orhun/02102b3af3acfdaf9a5a2164bea7c3d6?permalink_comment_id=4755423#gistcomment-4755423
mkdir /mnt/boot
mount -o fmask=0137,dmask=0027 /dev/sdb1 /mnt/boot

Note

When mentioning the packages you need in the below pacstrap, remember they form the console environment you boot into. So mention the crucials ones: to get internet, a text editor, keyd to set keybindings, etc.

pacstrap -K /mnt base base-devel btrfs-progs linux-zen linux-zen-headers linux-firmware amd-ucode neovim \
  wpa_supplicant dhcpcd man-db texinfo efibootmgr zsh zsh-syntax-highlighting zoxide tmux fzf \
    rsync git mosh aria2 unzip tree fd ripgrep keyd

Use genfstab command (part of arch install scripts) to generate fstab

genfstab -U /mnt >> /mnt/etc/fstab

(VIII) Chroot into the install and set root password

arch-chroot /mnt
# get rid of the annoying beep
rmmod pcspkr
# Set the root password
passwd

(IX) Setting up initramfs for decrypting encryped root and mounting btrfs root

We need prepare the kernel for decrypting the root partition. This is done by editing HOOKs in /etc/mkinitcpio.conf and setting kernel arguments in /etc/kernel/cmdline.

The systemd hook tells mkinitcpio that we need a systemd-based initramfs as opposed to a busybox-based initramfs. sd-encrypt hook is for decrypting the root partition.

/etc/mkinitcpio.conf
# vim:set ft=sh
# MODULES
# The following modules are loaded before any boot hooks are
# run.  Advanced users may wish to specify all system modules
# in this array.  For instance:
#     MODULES=(usbhid xhci_hcd)
MODULES=(btrfs)

# BINARIES
# This setting includes any additional binaries a given user may
# wish into the CPIO image.  This is run last, so it may be used to
# override the actual binaries included by a given hook
# BINARIES are dependency parsed, so you may safely ignore libraries
BINARIES=()

# FILES
# This setting is similar to BINARIES above, however, files are added
# as-is and are not parsed in any way.  This is useful for config files.
FILES=()

# HOOKS
# This is the most important setting in this file.  The HOOKS control the
# modules and scripts added to the image, and what happens at boot time.
# Order is important, and it is recommended that you do not change the
# order in which HOOKS are added.  Run 'mkinitcpio -H <hook name>' for
# help on a given hook.
# 'base' is _required_ unless you know precisely what you are doing.
# 'udev' is _required_ in order to automatically load modules
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
# Examples:
##   This setup specifies all modules in the MODULES setting above.
##   No RAID, lvm2, or encrypted root is needed.
#    HOOKS=(base)
#
##   This setup will autodetect all modules for your system and should
##   work as a sane default
#    HOOKS=(base udev autodetect modconf block filesystems fsck)
#
##   This setup will generate a 'full' image which supports most systems.
##   No autodetection is done.
#    HOOKS=(base udev modconf block filesystems fsck)
#
##   This setup assembles a mdadm array with an encrypted root file system.
##   Note: See 'mkinitcpio -H mdadm_udev' for more information on RAID devices.
#    HOOKS=(base udev modconf keyboard keymap consolefont block mdadm_udev encrypt filesystems fsck)
#
##   This setup loads an lvm2 volume group.
#    HOOKS=(base udev modconf block lvm2 filesystems fsck)
#
##   This will create a systemd based initramfs which loads an encrypted root filesystem.
#    HOOKS=(base systemd autodetect modconf kms keyboard sd-vconsole sd-encrypt block filesystems fsck)
#
##   NOTE: If you have /usr on a separate partition, you MUST include the
#    usr and fsck hooks.
HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap consolefont block sd-encrypt filesystems fsck)

# COMPRESSION
# Use this to compress the initramfs image. By default, zstd compression
# is used for Linux ≥ 5.9 and gzip compression is used for Linux < 5.9.
# Use 'cat' to create an uncompressed image.
#COMPRESSION="zstd"
#COMPRESSION="gzip"
#COMPRESSION="bzip2"
#COMPRESSION="lzma"
#COMPRESSION="xz"
#COMPRESSION="lzop"
#COMPRESSION="lz4"

# COMPRESSION_OPTIONS
# Additional options for the compressor
#COMPRESSION_OPTIONS=()

# MODULES_DECOMPRESS
# Decompress loadable kernel modules and their firmware during initramfs
# creation. Switch (yes/no).
# Enable to allow further decreasing image size when using high compression
# (e.g. xz -9e or zstd --long --ultra -22) at the expense of increased RAM usage
# at early boot.
# Note that any compressed files will be placed in the uncompressed early CPIO
# to avoid double compression.
#MODULES_DECOMPRESS="no"

Now you need to create the file /etc/kernel/cmdline, which should look like this.

/etc/kernel/cmdline
rd.luks.name=e789d34e-224b-49f6-be22-87f08131e3ad=root root=/dev/mapper/root rootflags=subvol=root rw ps1=1

This is how I do it:

blkid > /etc/kernel/cmdline
nvim /etc/kernel/cmdline

Note

Delete every line except that which contains TYPE="crypto_LUKS". This is has the UUID of the encrypted partition our kernel has to decrypt. Edit this file to look like the /etc/kernel/cmdline above. rootflags=subvol=root is necessary for our btrfs setup.

Don't call mkinitcpio yet because we don't want an initramfs file but a UKI.

(X) Creating UKI

We now need to create the single image file that UEFI will directly call to boot the system. That's right there's no intermediary bootloader like grub or systemd-boot in this setup.

To create the UKI we edit the the preset file for our kernel found in /etc/mkinitcpio.d and comment out the lines that create UKI and comment the lines that create a separate initrams.img file.

The UKI will be created in /boot/EFI/Linux. So make it first.

mkdir -p /boot/EFI/Linux

Note

Make sure default_uki and fallback_uki point to the right location, which here is /boot/EFI/Linux/arch-linux-zen.efi and /boot/EFI/Linux/arch-linux-zen-fallback.efi

/etc/mkinitcpio.d/linux-zen.preset
# mkinitcpio preset file for the 'linux-zen' package

#ALL_config="/etc/mkinitcpio.conf"
ALL_kver="/boot/vmlinuz-linux-zen"

PRESETS=('default' 'fallback')

#default_config="/etc/mkinitcpio.conf"
#default_image="/boot/initramfs-linux-zen.img"
default_uki="/boot/EFI/Linux/arch-linux-zen.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"

#fallback_config="/etc/mkinitcpio.conf"
#fallback_image="/boot/initramfs-linux-zen-fallback.img"
fallback_uki="/boot/EFI/Linux/arch-linux-zen-fallback.efi"
fallback_options="-S autodetect"

Finally build the UKI:

mkinitcpio -p linux-zen

(XI) Create a UEFI boot entry, set timezone, locale, hostname

efibootmgr --create --disk /dev/sdb --part 1 --label "archlinux" --loader '\EFI\Linux\arch-linux-zen.efi' --unicode

While you're at it, you may want to remove some UEFI boot entries. Check out efibootmgr.

ln -sf /usr/share/zoneinfo/Asia/Kolkata /etc/localtime
timedatectl set-timezone Asia/Kolkata
hwclock --systohc

Edit /etc/locale.gen and uncomment en_US.UTF-8 UTF-8

locale-gen

/etc/locale.conf
LANG=en_US.UTF-8
/etc/hostname
hostname

Now exit chroot with <Ctrl-d>. Unmount partition and close cryptsetup.

umount -R /mnt
cryptsetup close root

Now you can finally reboot.

reboot

(XII) Finishing up

Add your key user.

useradd -m -G wheel -s /usr/bin/zsh vector
passwd vector
# Now uncomment the setting to allow wheel group to use sudo
EDITOR=nvim visudo
su vector
cd ~
fzf --zsh > ~/.fzf.zsh 
cp /mnt/vector/.zshrc ~/
cp /mnt/vector/.zsh_history ~/
chown vector:vector ~/.zshrc ~/.zsh_history

(XIII) Setting up graphical environment: Xorg or Wayland

(XIV) Setting up audio: pipewire

After setting your grahpical environment, its time to set up audio.

See audio and bluetooth

(XV) Setting up secure-boot

Its great that we have an encrypted root partition. But our boot partition which contains the EFI stub kernel is unencrypted. We don't want the bios launching a possibly modified kernel. Therefore we need to configure secure-boot functionality in UEFI that permits only running binaries that are signed with our keys. For this we have to enrol our own public keys into the firmware.

After setting up secure-boot in your motherboard uefi, you need to boot back into your system and check that its in setup mode.

sudo sbctl status

This is how it appears before entering setup mode:

vector@ArchLinuxVS ~ $ sudo sbctl status
[sudo] password for vector:
Installed:      ✗ sbctl is not installed
Setup Mode:     ✓ Disabled
Secure Boot:    ✗ Disabled
Vendor Keys:    microsoft

Resetting the secure boot keys will make it enter setup mode. After secure boot was enabled and keys were deleted, this is how it appears:

vector@ArchLinuxVS ~ $ sudo sbctl status
[sudo] password for vector:
Installed:      ✗ sbctl is not installed
Setup Mode:     ✗ Enabled
Secure Boot:    ✗ Disabled
Vendor Keys:    none

Create keys:

# sbctl create-keys

Enrol keys:

[root@ArchLinuxVS vector]# sbctl enroll-keys -m
Enrolling keys to EFI variables...
With vendor keys from microsoft...✓
Enrolled keys to the EFI variables!

Status after enrolling keys

[root@ArchLinuxVS vector]# sbctl status
Installed:      ✓ sbctl is installed
Owner GUID:     8g3zd782-fn29-8365-rv78-261fgh673159
Setup Mode:     ✓ Disabled
Secure Boot:    ✗ Disabled
Vendor Keys:    microsoft

Run sbctl verify to find out the files that have to be signed:

[root@ArchLinuxVS vector]# sbctl verify
Verifying file database and EFI images in /boot...
✗ /boot/EFI/Linux/arch-linux-zen-fallback.efi is not signed
✗ /boot/EFI/Linux/arch-linux-zen.efi is not signed
✗ /boot/vmlinuz-linux-zen is not signed

Sign them

sbctl sign -s /boot/EFI/Linux/arch-linux-zen-fallback.efi
sbctl sign -s /boot/EFI/Linux/arch-linux-zen.efi
sbctl sign -s /boot/vmlinuz-linux-zen

Verify they're signed:

[root@ArchLinuxVS vector]# sbctl verify
Verifying file database and EFI images in /boot...
✓ /boot/vmlinuz-linux-zen is signed
✓ /boot/EFI/Linux/arch-linux-zen-fallback.efi is signed
✓ /boot/EFI/Linux/arch-linux-zen.efi is signed

Reboot and check sbctl status:

vector@ArchLinuxVS ~ $ sudo sbctl status
[sudo] password for vector:
Installed:      ✓ sbctl is installed
Owner GUID:     8g3zd782-fn29-8365-rv78-261fgh673159
Setup Mode:     ✓ Disabled
Secure Boot:    ✓ Enabled
Vendor Keys:    microsoft

Setting up screenlock

FDE protects our data when powered off and secure boot gives us some degree of confidence that the files in our unencrypted boot partition have not been tampered with. Given that we've configured these two, it would be ironic if our device gets hacked owing to the lack of a simple screenlock

sudo pacman -S slock
/etc/X11/xorg.conf.d/screenlock.conf
Section "ServerFlags"
        Option "DontVTSwitch" "True"
        Option "DontZap"      "True"
EndSection

Always execute slock if you're leaving your computer powered on.

TODOs:

  • make console loadkeys automatic

(XIII) Setting my archlinux desktop

Tips

makepkg and PKGBUILD

See makepkg, PKGBUILD.

Set default apps

xdg-mime default zathura.desktop application/pdf
xdg-mime default sxiv.desktop image/png

Skip annoying gpg checks

makepkg -sri --skippgpcheck

Steps to add a custom repository in archlinux

Create the repository root in /home owned by the current user

# install -d /home/custom-testing-pkgs -o $USER

Create a signed repository database

  • Note that the name I specified in pacman.conf was custom-testing.
  • The database file pacman expects in the root directory is custom-testing.db.
  • When adding the database through repo-add -s, I specifiy the same custom-testing.db but in compressed form custom-testing.db.tar.gz.
$ repo-add -s /home/custom-testing-pkgs/custom-testing.db.tar.gz

Edit /etc/pacman.conf to add a new entry for our repository

# sudo vim /etc/pacman.conf

[custom-testing]
SigLevel = Optional TrustAll
Server = file:///home/custom-testing-pkgs

Comments