Arch Linux Installation Guide (2019)

This is an alternate Arch Linux installation guide created while setting up my workstation. Some of the instructions here might not suitable for different hardware configurations than what I have.

My Hardware Configuration

# lspci
00:00.0 Host bridge: Intel Corporation 3rd Gen Core processor DRAM Controller (rev 09)
00:01.0 PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (rev 09)
00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics Controller (rev 09)
00:14.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller (rev 04)
00:16.0 Communication controller: Intel Corporation 7 Series/C216 Chipset Family MEI Controller #1 (rev 04)
00:1a.0 USB controller: Intel Corporation 7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (rev 04)
00:1b.0 Audio device: Intel Corporation 7 Series/C216 Chipset Family High Definition Audio Controller (rev 04)
00:1c.0 PCI bridge: Intel Corporation 7 Series/C216 Chipset Family PCI Express Root Port 1 (rev c4)
00:1c.2 PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI Express Root Port 3 (rev c4)
00:1c.3 PCI bridge: Intel Corporation 7 Series/C216 Chipset Family PCI Express Root Port 4 (rev c4)
00:1d.0 USB controller: Intel Corporation 7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (rev 04)
00:1f.0 ISA bridge: Intel Corporation HM77 Express Chipset LPC Controller (rev 04)
00:1f.2 SATA controller: Intel Corporation 7 Series Chipset Family 6-port SATA Controller [AHCI mode] (rev 04)
00:1f.3 SMBus: Intel Corporation 7 Series/C216 Chipset Family SMBus Controller (rev 04)
01:00.0 3D controller: NVIDIA Corporation GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (rev a1)
03:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. RTL8411 PCI Express Card Reader (rev 01)
03:00.2 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 0a)
04:00.0 Network controller: Qualcomm Atheros AR9287 Wireless Network Adapter (PCI-Express) (rev 01)
# lsusb
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 004: ID 04f2:b335 Chicony Electronics Co., Ltd
Bus 003 Device 003: ID 04f3:0023 Elan Microelectronics Corp.
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Summary

Installation Media archlinux-2019.03.01-x86_64.iso
Bootloader systemd-boot
Kernel Arch Linux default kernel
Init systemd
Shell bash
Display/Login Manager -- none --
Window Manager i3-wm on Xorg
Application Launcher rofi
Terminal tilda

For a generic installations instructions see the official Arch Linux Installation Guide.

 

Preparing Partitions

Assumption: Storage device that we install the OS is connected as sda.

When setting up a new workstation, I usually wipe out the all partitions in the storage device with the following command.

WARNING: DO NOT do this if you have any data on the storage device that you want to keep. (instead you can manually clear the space new partitions.)

# dd if=/dev/zero of=/dev/sda bs=1M count=1

Create the following GPT partitions using fdisk.

Device Node Mount Point Type Size
/dev/sda1 /boot EFI 100MB
/dev/sda2 / Linux 10GB
/dev/sda3 /home Linux remainder

Note: if you get a warning as follows while creating partitions;

Partition #1 contains a vfat signature.

Do you want to reove the signature? [Y]es/[N]o:

Choose to remove the signature by pressing Y followed by the Enter key.

# fdisk /dev/sda

Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x640f873c.

Command (m for help): g
Created a new GPT disklabel (GUID: 7724150B-F303-394A-B1FA-78F31BA5169A).

Command (m for help): n
Partition number (1-128, default 1):
First sector (2048-125045390, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-125045390, default 125045390): +100M

Created a new partition 1 of type 'Linux filesystem' and of size 100 MiB.

Command (m for help): t
Selected partition 1
Partition type (type L to list all types): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.

Command (m for help): n
Partition number (2-128, default 2):
First sector (1050624-125045390, default 1050624):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1050624-125045390, default 125045390): +10G

Created a new partition 2 of type 'Linux filesystem' and of size 10 GiB.

Command (m for help): n
Partition number (3-128, default 3):
First sector (22022144-125045390, default 22022144):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (22022144-125045390, default 125045390):

Created a new partition 3 of type 'Linux filesystem' and of size 49.1 GiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

# fdisk -l /dev/sda
Disk /dev/sda: 59.6 GiB, 64023257088 bytes, 125045424 sectors
Disk model: TS64GSSD320
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 7724150B-F303-394A-B1FA-78F31BA5169A

Device        Start       End   Sectors  Size Type
/dev/sda1      2048   1050623   1048576  512M EFI System
/dev/sda2   1050624  22022143  20971520   10G Linux filesystem
/dev/sda3  22022144 125045390 103023247 49.1G Linux filesystem

Format each partition as follows:

# mkfs.vfat -F32 /dev/sda1
--- output not shown here ---
# mkfs.ext4 /dev/sda2
--- output not shown here ---
# mkfs.ext4 /dev/sda3
--- output not shown here ---

NOTE: I'm not creating a swap partition here, because I don't use swap on my workstations. However, I will be including the instruction to create swap file in a later stage.

 

Prepare for base system installation

File System

Mount the partition which eventually be the root of the system (/dev/sda2) to /mnt, and create sub-directories.

# mount /dev/sda2 /mnt
# mkdir -m 0755 -pv \
> /mnt/{boot,dev,etc/{systemd/network,wpa_supplicant},home,run,var/{cache/pacman/pkg,lib/pacman,log}}
mkdir: created directory '/mnt/boot'
mkdir: created directory '/mnt/dev'
mkdir: created directory '/mnt/etc'
mkdir: created directory '/mnt/etc/systemd'
mkdir: created directory '/mnt/etc/systemd/network'
mkdir: created directory '/mnt/etc/wpa_supplicant'
mkdir: created directory '/mnt/home'
mkdir: created directory '/mnt/run'
mkdir: created directory '/mnt/var'
mkdir: created directory '/mnt/var/cache'
mkdir: created directory '/mnt/var/cache/pacman'
mkdir: created directory '/mnt/var/cache/pacman/pkg'
mkdir: created directory '/mnt/var/lib'
mkdir: created directory '/mnt/var/lib/pacman'
mkdir: created directory '/mnt/var/log'
# mkdir -m 0555 -pv /mnt/{proc,sys}
mkdir: created directory '/mnt/proc'
mkdir: created directory '/mnt/sys'
# mkdir -m 1777 -pv /mnt/tmp
mkdir: created directory '/mnt/tmp'

Mount remaining partitions.

# mount /dev/sda1 /mnt/boot
# mount /dev/sda3 /mnt/home

Swapfile (optional)

# dd if=/dev/zero of=/mnt/swap bs=512M count=1
--- output not shown here ---
# chmod 600 /mnt/swap
# mkswap /mnt/swap
--- output not shown here ---
# swapon /mnt/swap

Connect installation environment to LAN/Internet

Assumption: Your system connects to LAN/Internet using the interface wlp1s0.

Enable WIFI connection using WPA2. When using a wired connection this steps in this section may be skipped partly or completely.

Connect to WIFI (optional)

# wpa_passphrase ESSID secret | sed '/#psk=/d' > /mnt/etc/wpa_supplicant/wifi.conf
# ln -sv /mnt/etc/wpa_supplicant/wifi.conf /etc/wpa_supplicant/wpa_supplicant-wlp1s0.conf
'/etc/wpa_supplicant/wpa_supplicant-wlp1s0.conf' -> '/mnt/etc/wpa_supplicant/wifi.conf'
# systemctl start rfkill-unblock@wifi
# systemctl start wpa_supplicant@wlp1s0

Then, create a network configuration file (in the target FS), and sym-link it to the installation system.

# cat > /mnt/etc/systemd/network/any-network-name.network << EOF
[Match]
Name=wlp1s0

[Network]
DHCP=yes
EOF
# ln -sv /mnt/etc/systemd/network/any-network-name.network /etc/systemd/network
'/etc/systemd/network/any-network-name.network' -> '/mnt/etc/systemd/network/any-network-name.network'

Start systemd-networkd and systemd-resolved services.

# systemctl start systemd-networkd
# systemctl start systemd-resolved

 

Install base system

[NOTE TO SELF] Use local pacman cache

Mount cache server into /var/cache/pacman/pkg of the installation environment.

# mkdir -pv /var/lib/pacman/sync
mkdir: created directory '/var/lib/pacman/sync'
# mount -o nolock SERVER_IP:/path/to/sync /var/lib/pacman/sync
# mount -o nolock SERVER_IP:/path/to/cache /var/cache/pacman/pkg

[/NOTE TO SELF]

Mount pseudo file systems to the target

# mount -t devtmpfs udev /mnt/dev
# mount -t proc proc /mnt/proc
# mount -t sysfs sys /mnt/sys
# mount -t tmpfs tmp /mnt/tmp

For the installation you can use mirror closest to you and later do a full system upgrade using an up-to-date repository. Select the closest mirror and move it to the top of /etc/pacman.d/mirrorlist.

Note: install all the packages from base-devel group.

# pacman -Sy -r /mnt linux intel-ucode wpa_supplicant dhcpcd nfs-utils base-devel
--- output not shown here ---

 

Make the new installation bootable

Bootloader configuration

Make UEFI boot directories for systemd-boot (without using bootctl), copy boot loader firmware and create loader configuration files manually.

# mkdir -pv /mnt/boot/{EFI/systemd,loader/entries}
mkdir: created directory '/mnt/boot/EFI'
mkdir: created directory '/mnt/boot/EFI/systemd'
mkdir: created directory '/mnt/boot/loader'
mkdir: created directory '/mnt/boot/loader/entries'
# cp /mnt/lib/systemd/boot/efi/systemd-bootx64.efi /mnt/boot/EFI/systemd
# cat > /mnt/boot/loader/loader.conf << EOF
> default loader-name
> timeout 0
> EOF
# cat > /mnt/boot/loader/entries/loader-name.conf << EOF
> title Arch Linux
> linux /vmlinuz-linux
> initrd /intel-ucode.img
> initrd /initramfs-linux.img
> options root=/dev/sda2 init=/usr/lib/systemd/systemd rw quiet
> EOF

If there are any dump-* files in the /sys/firmware/efi/efivars directory, delete them all, and then run;

# efibootmgr --create --disk /dev/sda --part 1 --loader /EFI/systemd/systemd-bootx64.efi --label "Arch Linux"

 

Setup system via chroot

# chroot /mnt /bin/bash

Connect the system to network on boot

# ln -sv wifi.conf /etc/wpa_supplicant/wpa_supplicant-wlp1s0.conf
'/etc/wpa_supplicant/wpa_supplicant-wlp1s0.conf' -> 'wifi.conf'
# systemctl enable wpa_supplicant@wlp1s0 systemd-networkd systemd-resolved
--- output not shown here ---

Initialize pacman keys

# pacman-key --init
--- output not shown here ---
# pacman-key --populate archlinux
--- output not shown here ---
# sed -i 's/^#\(Server =.\+\)$/\1/' /etc/pacman.d/mirrorlist

Although it might nor be necessary for a net installation, do a system update.

# pacman -Syu
--- output not shown here ---

Create /etc/fstab

# cat >> /etc/fstab << EOF
> 
> /dev/sda2 / ext4 rw,relatime,noatime,nodiratime,discard,errors=remount-ro 0 1
> /dev/sda1 /boot vfat rw,relatime,fmask=0022,dmask=0022,shortname=mixed,errors=remount-ro 0 2
> /dev/sda3 /home ext4 rw,relatime,noatime,nodiratime,discard,errors=remount-ro 0 2
> EOF

[NOTE TO SELF] Mount local pacman cache when required

# cat >> /etc/fstab << EOF
> 
> SERVER_IP:/path/to/sync /var/lib/pacman/sync nfs4 noauto,x-systemd.automount,noexec,nolock,noatime,nodiratime,rsize=32768,wsize=32768,timeo=14,intr 0 0
> SERVER_IP:/path/to/cache /var/cache/pacman/pkg nfs4 noauto,x-systemd.automount,noexec,nolock,noatime,nodiratime,rsize=32768,wsize=32768,timeo=14,intr 0 0
> EOF

[/NOTE TO SELF]

Set /etc/hostname

# echo 'machine-name' > /etc/hostname

Time zone and clock settings

Setting time zone to Asia/Colombo. Make sure you change the Asia/Colombo text & the zoneinfo directory to match your time zone.

# echo 'Asia/Colombo' > /etc/timezone
# rm /etc/localtime
# ln -sv /usr/share/zoneinfo/Asia/Colombo /etc/localtime
'/etc/localtime' -> '/usr/share/zoneinfo/Asia/Colombo'
# hwclock --hctosys --utc
# date
Sun Mar  3 01:59:02 +0530 2019

[NOTE TO SELF] Enable synchronization with local NTP server

Set systemd-timesyncd to synchronize system time via NTP.

# sed -i 's/^\(NTP=\)/\1NTP_SERTVER_IP/; s/^#\(FallbackNTP=.\+\)/\1/' /etc/systemd/timesyncd.conf
# systemctl enable systemd-timesyncd

[/NOTE TO SELF]

Optionally, if the system time need to be changed:

# date MMDDhhmmYYYY
# hwclock --systohc --utc
# date
DDD MMM DD hh:mm:?? +0530 YYYY

Generate locale

# cat >> /etc/locale.gen << EOF
> en_US.UTF-8 UTF-8
> si_LK.UTF-8 UTF-8
> EOF
# locale-gen
Generating locales...
  en_US.UTF-8 UTF-8... done
  si_LK.UTF-8 UTF-8... done
Generation complete.

Note: at this point systemd will not allow us to set locale using localectl. We will do that after booting into the new system.

systemd adjustments

Stop console clearing at login prompt

# mkdir -pv /etc/systemd/system/getty@tty1.service.d
mkdir: created directory '/etc/systemd/system/getty@tty1.service.d'
# cat > /etc/systemd/system/getty@tty1.service.d/noclear.conf << EOF
> [Service]
> TTYVTDisallocate=no
> EOF

Limit number of TTYs

# sed -i 's/#\(NAutoVTs=\).*/\12/' /etc/systemd/logind.conf

Limit journal disk usage

# sed -i 's/#\(SystemMaxUse=\).*/\116M/' /etc/systemd/journald.conf

Mask unnecessary systemd units that cause delay in system startup

# systemctl mask lvm2-monitor systemd-backlight@

pacman configurations

[NOTE TO SELF] Block pacman from installing mono and/or java runtime.

# sed -i 's/#\(IgnorePkg\s*=.*\)/\1 mono mono-* *-openjdk-headless/' /etc/pacman.conf

[/NOTE TO SELF]

Enable color in pacman output

# sed -i 's/#\(Color\)/\1/' /etc/pacman.conf

Disable webcam

# cat >> /etc/modprobe.d/modprobe.conf << EOF
> blacklist uvcvideo
> EOF

Create user(s)

# useradd -m -s /bin/bash -G systemd-journal,wheel -U new_username
# passwd new_username
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

sudo capability

Add this user to /etc/sudoers as we will be blocking root from login in the system.

# cat >> /etc/sudoers << EOF
> new_username machine_name=(root) /usr/bin/pacman
> EOF

You may allow regular user to gain access to a root shell via sudo during the setup in order to prevent any lock-up situation;

# cat >> /etc/sudoers << EOF
> new_username machine_name=(root) /usr/bin/bash
> EOF

WARNING: however above may leave your system insecure in some situations and you must remove this capability once it is no longer needed.

Lockout root from login into console or from SSH in. Optionally remove the password hash for root from /etc/shadow.

# rm /etc/securetty
# sed -i 's#\(root:x:0:0::/root:/bin/\).\+#\1false#' /etc/passwd
# sed -i 's/\(root:\)[^:]*\(:.\+\)/\1!!\2/' /etc/shadow

At this point you should reboot into newly installed system, and login as a regular user.

Exit chroot, unmount and reboot

# exit
exit
# umount -Rv /mnt
unmount: /mnt/boot unmounted
unmount: /mnt/home unmounted
unmount: /mnt/dev unmounted
unmount: /mnt/proc unmounted
unmount: /mnt/sys unmounted
unmount: /mnt/tmp unmounted
unmount: /mnt unmounted
# systemctl reboot

First-boot configuration

Unblock RF-Kill

# systemctl start rfkill-unblock@wifi
# systemctl restart wpa_supplicant@wlp4s0
# systemctl restart systemd-networkd
# systemctl restart systemd-resolved

Set locale

# localectl set-locale LANG=en_US.UTF-8

pacman mirror list

Setup reflector to update pacman mirror list every time system boots.

# pacman -S reflector
--- output not shown here ---
# cat > /etc/systemd/system/reflector.service << EOF
> [Unit]
> Description=Pacman mirrorlist update
> Wants=network-online.target
> After=network-online.target
> 
> [Service]
> Type=oneshot
> ExecStart=/usr/bin/reflector --protocol https --latest 30 --number 20 --fastest 10 --sort rate --save /etc/pacman.d/mirrorlist
> EOF
# cat > /etc/systemd/system/reflector.timer << EOF
> [Unit]
> Description=Pacman mirrorlist update runner
> 
> [Timer]
> OnCalendar=daily
> RandomizedDelaySec=1day
> Persistent=true
> 
> [Install]
> RequiredBy=timers.target
> EOF
# systemctl enable reflector.timer

Install yay AUR helper

$ sudo pacman -S git
--- output not shown here ---
$ git clone https://aur.archlinux.org/yay /tmp/yay
--- output not shown here ---
$ cd /tmp/yay
$ makepkg -si
--- output not shown here ---
$ sudo pacman -Rcnsu go
--- output not shown here ---

Use yay to reinstall yay, so that all AUR packages in out system is properly installed using yay.

$ yay --removemake -S yay
--- output not shown here ---

Optionally, do a full system update using yay.

$ yay --removemake --combinedupgrade -Syu
--- output not shown here ---

 

GUI

Xorg

Install appropriate video driver.

$ sudo pacman -S xf86-video-vendor
--- output not shown here ---
$ sudo pacman -S xorg-{server,xinit}
--- output not shown here ---

Configure Xorg to start on user login.

$ cat >> ~/.bash_profile << EOF
> 
> if [[ ! \$DISPLAY && \$XDG_VTNR -eq 1 ]]; then
>   exec startx
> fi
> EOF

Fonts

$ sudo pacman -S ttf-{dejavu,droid}
--- output not shown here ---

i3 Window Manager

Install i3 window manager, and set Alt key as $mod.

$ sudo pacman -S i3-wm
--- output not shown here ---
$ cat > ~/.xinitrc << EOF
> exec i3 > /dev/null 2>&1
> EOF
$ mkdir -pv ~/.config/i3
mkdir: created directory '/home/suda/.config/i3'
$ cat > ~/.config/i3/config << EOF
> set \$mod Mod1
> EOF

rofi launcher

$ sudo pacman -S rofi
--- output not shown here ---
$ cat >> ~/.config/i3/config << EOF
> 
> bindsym \$mod+d exec --no-startup-id rofi -show run
> EOF

Terminal

Install tilda terminal emulator & launch it when i3 starts.

$ sudo pacman -S tilda
--- output not shown here ---
$ cat >> ~/.config/i3/config << EOF
> 
> exec --no-startup-id tilda
> EOF

 

Sound: ALSA Support

ALSA support is enabled in the kernel by default. Following installs a set of utilities for configuration and integration need that applies to all hardware.

$ sudo pacman -S alsa-{utils,oss,plugins} pulseaudio{,-alsa}
--- output not shown here ---

Do the necessary adjustments using alsamixer and test and save settings.

$ alsamixer
$ speaker-test -c 2
--- output not shown here ---
# alsactl store

 


Following instructions are for my personal setup choices.

Bash completion

$ sudo pacman -S bash-completion
--- output not shown here ---

Man pages & viewer

$ sudo pacman -S man-db
--- output not shown here ---

playerctl

Install playerctl to control volume via keyboard.

$ sudo pacman -S playerctl
--- output not shown here ---

iBus

$ sudo pacman -S ibus{,-m17n}
--- output not shown here ---
$ cat >> ~/.bashrc << EOF
> 
> export GTK_IM_MODULE=ibus
> export XMODIFIERS=@im=ibus
> export QT_IM_MODULE=ibus
> export XIM_PROGRAM=/usr/bin/ibus-daemon
> EOF

Xorg extra

$ sudo pacman -S xorg-{xbacklight,xrandr,xset}
--- output not shown here ---

Extra Fonts

$ yay -S ttf-lklug otf-fira-{code,mono,sans} otf-font-awesome
--- output not shown here ---

Programming languages and Development Tools

$ sudo pacman -S npm
--- output not shown here ---

Install rust via rustup.

$ curl -sSf https://sh.rustup.rs | sh
--- output not shown here ---
$ source $HOME/.cargo/env
$ rustup update
--- output not shown here ---
$ rustup run stable cargo install rustfmt --force
--- output not shown here ---

GUI Applications & Tools

$ sudo pacman -S claws-mail evince filezilla ghex gimp gnome-calculator gnucash \
> gvfs keepassxc libreoffice-fresh meld thunar transmission-gtk vlc
--- output not shown here ---

Firefox nightly

$ mkdir -pv $HOME/opt
mkdir: created directory '/home/username/opt'
$ curl -sL "https://download.mozilla.org/?product=firefox-nightly-latest-ssl&os=linux64&lang=en-US" | \
> tar xj -C $HOME/opt

Dropbox & Thunar plugin

$ yay -S {,thunar-}dropbox
--- output not shown here ---

After first run of dropbox completes, and files are synchronized exit Dropbox and, do the following had to avoid conflict with Dropbox's auto update.

$ rm -fr ~/.dropbox-dist
$ install -dm0 ~/.dropbox-dist

GTK & Icon themes

$ sudo pacman -S arc-gtk-theme papirus-icon-theme
--- output not shown here ---

Vim

$ sudo pacman -S gvim
--- output not shown here ---

And, also install spell checking tools.

$ sudo pacman -S aspell-en hunspell-en_US ispell
--- output not shown here ---
$ mkdir -pv $HOME/.vim/spell
mkdir: created directory '/home/username/.vim'
mkdir: created directory '/home/username/.vim/spell'
$ ln -sv $HOME/.aspell.en.pws $HOME/.vim/spell/en.utf-8.add
'/home/username/.vim/spell/en.utf-8.add' -> '/home/username/.aspell.en.pws'

conky

$ sudo pacman -S conky

Other Tools

$ sudo pacman -S cmake iproute2 iputils openssh tree veracrypt

Telegram

$ curl -sL https://tdesktop.com/linux | tar xJ -C $HOME/opt Telegram/Telegram