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 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (rev 08) 00:02.0 VGA compatible controller: Intel Corporation Skylake GT2 [HD Graphics 520] (rev 07) 00:14.0 USB controller: Intel Corporation Sunrise Point-LP USB 3.0 xHCI Controller (rev 21) 00:14.2 Signal processing controller: Intel Corporation Sunrise Point-LP Thermal subsystem (rev 21) 00:15.0 Signal processing controller: Intel Corporation Sunrise Point-LP Serial IO I2C Controller #0 (rev 21) 00:16.0 Communication controller: Intel Corporation Sunrise Point-LP CSME HECI #1 (rev 21) 00:17.0 SATA controller: Intel Corporation Sunrise Point-LP SATA Controller [AHCI mode] (rev 21) 00:1c.0 PCI bridge: Intel Corporation Sunrise Point-LP PCI Express Root Port #5 (rev f1) 00:1c.5 PCI bridge: Intel Corporation Sunrise Point-LP PCI Express Root Port #6 (rev f1) 00:1f.0 ISA bridge: Intel Corporation Sunrise Point-LP LPC Controller (rev 21) 00:1f.2 Memory controller: Intel Corporation Sunrise Point-LP PMC (rev 21) 00:1f.3 Audio device: Intel Corporation Sunrise Point-LP HD Audio (rev 21) 00:1f.4 SMBus: Intel Corporation Sunrise Point-LP SMBus (rev 21) 01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 15) 02:00.0 Network controller: Qualcomm Atheros QCA9377 802.11ac Wireless Network Adapter (rev 30) # lsusb Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 001 Device 005: ID 0bda:0129 Realtek Semiconductor Corp. RTS5129 Card Reader Controller Bus 001 Device 004: ID 04f2:b51f Chicony Electronics Co., Ltd HD WebCam Bus 001 Device 003: ID 04ca:3015 Lite-On Technology Corp. Bus 001 Device 002: ID 045e:0084 Microsoft Corp. Basic Optical Mouse Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Summary
Installation Media | archlinux-2020.05.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 | 15GB |
/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): +15G Created a new partition 2 of type 'Linux filesystem' and of size 15 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 15G 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,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/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 0750 -pv /mnt/var/lib/iwd mkdir: created directory '/mnt/var/lib/iwd' # 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 iwd
. When using a wired connection this steps
in this section may be skipped partly or completely.
Connect to WIFI (optional)
# systemctl start iwd # systemctl start rfkill-unblock@wifi # iwctl device wlp1s0 set-property Powered on # iwctl [iwd]# station wlp1s0 connect ESSID Type the network passphrase for ESSID psk. Passphrase: secret [iwd]# exit # sed '/^Passphrase=/d' /var/lib/iwd/ESSID.psk > /mnt/var/lib/iwd/ESSID.psk # chmod 0600 /mnt/var/lib/iwd/ESSID.psk
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
Note: You might have to symlink /run/systemd/resolve/stub-resolv.conf
to
/etc/resolv.conf
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 linux-firmware intel-ucode iwd 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
# systemctl enable iwd systemd-networkd systemd-resolved --- output not shown here --- # ln -sfv /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf '/etc/resolv.conf' -> '/run/systemd/resolve/stub-resolv.conf'
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 not be necessary for a new 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 nfs noauto,x-systemd.automount,noexec,nolock,noatime,nodiratime,rsize=32768,wsize=32768,timeo=14,nfsvers=3 0 0 > SERVER_IP:/path/to/cache /var/cache/pacman/pkg nfs noauto,x-systemd.automount,noexec,nolock,noatime,nodiratime,rsize=32768,wsize=32768,timeo=14,nfsvers=3 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\|VerbosePkgLists\)/\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/su -ls /usr/bin/bash > EOF
WARNING: however above may leave your system insecure in some situations and you may 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
Disable shell history at system level
Note: users may enable/override this from their shell configuration.
# cat >> /etc/profile << EOF > > # Disable shell history recording for all users > unset HISTFILE > export HISTFILESIZE=0 > EOF
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 iwd # 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 --- 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 noto-fonts{,-emoji} --- output not shown here ---
Programming languages and Development Tools
Node.js & pnpm
First install pnpm
into temporary directory, and then use that installation
as a bootstrap to install pnpm
under $HOME
. See pnpm documentation for details.
$ sudo pacman -S nodejs --- output not shown here --- $ curl -L https://raw.githubusercontent.com/pnpm/self-installer/master/install.js | \ > PNPM_DEST=/tmp PNPM_BIN_DEST=/tmp/bin node --- output not shown here --- $ /tmp/bin/pnpm -g install pnpm
Rust
Install rust
via rustup
.
$ sudo pacman -S rustup --- output not shown here --- $ rustup default stable --- output not shown here --- $ rustup update --- output not shown here ---
PHP & Composer
$ sudo pacman -S composer --- output not shown here ---
GUI Applications & Tools
$ yay -S claws-mail evince filezilla ghex gimp inkscape gnome-calculator gnucash \ > gvfs keepassxc libreoffice-fresh meld thunar transmission-gtk vlc rtv file-roller \ > unrar screen mycli dunst --- 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 $ sudo pacman -S dbus-glib --- output not shown here ---
Dropbox
$ yay -S dropbox --- output not shown here ---
After first run of dropbox
completes, and files are synchronized exit Dropbox
and, do the following to avoid conflict with Dropbox's auto update.
$ rm -fr ~/.dropbox-dist $ install -dm0 ~/.dropbox-dist
Syncthing
$ sudo pacman -S syncthing --- output not shown here --- $ mkdir -pv $HOME/Sync mkdir: created directory '/home/username/Sync'
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 iproute2 iputils openssh tree veracrypt
Telegram
$ curl -sL https://telegram.org/dl/desktop/linux | tar xJ -C $HOME/opt Telegram/Telegram