Back to Arch Linux
Within a Ubuntu LTS pre-installed laptop
Why
It was October 2019. New job, new laptop.
I tried to tell myself to stay with the LTS that was given to me from the
Canonical and Dell overlords. To be honest, I did not remove Ubuntu from the
get-go was because I was unsure if I can run Nvidia’s CUDA toolkit on an
unlisted OS. In my old laptop (2011-2014) on which I had a Nvidia GPU and
which ran Manjaro, I would frequently total my installation every time I ran
pacman -Syu
. The X.org display server would just stop functioning and I
would be left with a terminal to figure out how to get back.
I thought I could just weed out the bloatware (Google Chrome, Amazon etc.) and be content with what I have. Trust the Ubuntu and Dell repositories.
Fast-forward to January 2020. Turns out, the project which I am on right now may not get started with CUDA development soon. Therefore, a good OS and GCC compiler toolchain is all that I need. I have a mutant Ubuntu LTS already with all the hacks under the sun to stay up-to-date:
- pyenv to have the latest Python
- flatpak to install some applications which are ancient in the official Ubuntu repos (Okular, Signal, KeepassXC, Zeal, Zotero etc.)
- appimage when flatpak’s sandbox is too restrictive (Neovim)
- PPA / unofficial
.deb
packages from GitHub when the start-up overhead of flatpak or appimage is way too high (Neovim, again 😅) or similar reasons as above (Nextcloud client, VSCodium etc.)
This is not good at all, I hear you. And I have to wait a good 4 more months for the next LTS release! The final blow came when I saw Vim 8.2 was released last month with popup support, and I do not have it yet! There is no practical way (apart from yet another PPA) to get the latest Vim, without compiling it from source. Either ways, it is also unacceptable to run a desktop environment (GNOME) which is lagging behind (version 3.28.2) the latest stable release (version 3.34) for so long!
How
There is a nice guide which demonstrates how to setup Arch Linux from an existing Linux OS. I started off by downloading the bootstrap image along with the GPG signature and verifying it:
$ gpg --keyserver-options auto-key-retrieve --verify archlinux-2020.01.01-x86_64.iso.sig gpg: assuming signed data in 'archlinux-2020.01.01-x86_64.iso' gpg: Signature made Wed 01 Jan 2020 06:21:41 AM CET gpg: using RSA key 4AA4767BBC9C4B1D18AE28B77F2D434B9741E8AC gpg: Good signature from "Pierre Schmitz <pierre@archlinux.de>" [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 4AA4 767B BC9C 4B1D 18AE 28B7 7F2D 434B 9741 E8AC
The key fingerprint was cross-checked to be doubly sure. Then I extracted the bootstrap image:
$ sudo su # tar xzf archlinux-bootstrap-2020.01.01-x86_64.tar.gz -C /tmp
When I skipped a few steps and went into the chroot
, I got this:
# /tmp/root.x86_64/bin/arch-chroot /tmp/root.x86_64/ ==> WARNING: /mnt/archlinux/root.x86_64/ is not a mountpoint. This may have undesirable side effects.
I understood that the chroot
should be a mount point:
# mount --bind /tmp/root.x86_64 /tmp/root.x86_64 # /tmp/root.x86_64/bin/arch-chroot /tmp/root.x86_64/
And the chroot
worked without any warnings. To clarify the shell I am
running I will prefix the commands with [chroot] #
from here on:
[chroot] # pacman-key --init [chroot] # pacman-key --populate archlinux
After editing the mirror list outside of the chroot
:
$ sudoedit /tmp/root.x86_64/etc/pacman.d/mirrorlist
I updated the bootstrap:
[chroot] # pacman -Syyu
And mounted the partitions to be bootstrapped:
[chroot] # mount /dev/nvme0n1p5 /mnt [chroot] # mount /dev/nvme0n1p4 /mnt/home [chroot] # genfstab -U /mnt >> /mnt/etc/fstab [chroot] # umount /mnt/home
and installed some essentials:
[chroot] # pacman -S base base-devel :: There are 24 members in group base-devel: :: Repository core 1) autoconf 2) automake 3) binutils 4) bison 5) fakeroot 6) file 7) findutils 8) flex 9) gawk 10) gcc 11) gettext 12) grep 13) groff 14) gzip 15) libtool 16) m4 17) make 18) pacman 19) patch 20) pkgconf 21) sed 22) sudo 23) texinfo 24) which ...
Did the same for the target Arch Linux partition mounted at /mnt
:
[chroot] # pacstrap /mnt base base-devel [chroot] # pacstrap /mnt linux-lts linux-firmware intel-ucode lsb-release
Thereafter I followed the official installation guide:
[chroot] # arch-chroot /mnt
Cleaning up and dual booting
Exit the chroot
and unmount everything:
[chroot in a chroot] # exit [chroot] # exit # umount -R /tmp/root.x86_64
The Ubuntu installation came with a GRUB boot loader and os-loader
package
which should detect the new Arch Linux installation (since we installed the
lsb-release
package). To make it happen, reboot? from Ubuntu run:
# sudo update-grub
That did not work! Turns out /etc/default/grub
had two offending lines:
GRUB_TIMEOUT_STYLE=hidden GRUB_DISABLE_OS_PROBER=true
which when commented out, it started working. Follow this by update-grub
or
grub-mkconfig -o /boot/grub/grub.cfg
and it is good to go.
Epilogue: some personal choices
What follows below are not necessary but I note it down for future reference. Here are the packages I chose to install:
neovim vim code # editors plasma kdegraphics-thumbnailers # KDE desktop meta package konsole acpi inetutils # many network commands, including hostname openssh parted # partitioning tool xonsh zsh # alternatives to bash tlp # CPU and FAN governor man-db # man pages arch-wiki-docs # provides wiki-search arch-wiki-lite # and wiki-search-html commands ttf-joypixels ttf-roboto adobe-source-sans-pro-fonts adobe-source-serif-pro-fonts ttf-arphic-uming terminus-font # extra fonts libreoffice-fresh # writer, calc, impress... gcc-fortran gcc-go rust # compilers pacman-contrib reflector # pacman utilities firefox thunderbird zeal okular ark nextcloud-client mplayer # ... and more applications flatpak # for sandboxing non-free applications
An AUR helper:
$ git clone https://aur.archlinux.org/yay.git $ cd yay && makepkg -s # pacman -U /home/avmo/.cache/makepkg/yay-*
Check and activate periodic TRIM for long-term performance:
$ lsblk --discard NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO nvme0n1 0 512B 2T 0 |-nvme0n1p1 0 512B 2T 0 |-nvme0n1p2 0 512B 2T 0 |-nvme0n1p3 0 512B 2T 0 |-nvme0n1p4 0 512B 2T 0 |-nvme0n1p5 0 512B 2T 0 `-nvme0n1p6 0 512B 2T 0 # systemctl enable fstrim.timer Created symlink /etc/systemd/system/timers.target.wants/fstrim.timer → /usr/lib/systemd/system/fstrim.timer.
Format a swap partition in the empty space available and mount it with TRIM
(discard
) support:
# parted /dev/nvme0n1 GNU Parted 3.3 Using /dev/nvme0n1 Welcome to GNU Parted! Type 'help' to view a list of commands. (parted) print Model: KXG60ZNV512G NVMe TOSHIBA 512GB (nvme) Disk /dev/nvme0n1: 512GB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 1 1049kB 819MB 818MB fat32 EFI system partition boot, esp 2 819MB 6188MB 5369MB fat32 Basic data partition msftres 3 6188MB 140GB 134GB ext4 4 194GB 301GB 107GB btrfs 5 405GB 512GB 107GB ext4 (parted) mkpart primary linux-swap 140GB 194GB (parted) print Model: KXG60ZNV512G NVMe TOSHIBA 512GB (nvme) Disk /dev/nvme0n1: 512GB Sector size (logical/physical): 512B/512B Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 1 1049kB 819MB 818MB fat32 EFI system partition boot, esp 2 819MB 6188MB 5369MB fat32 Basic data partition msftres 3 6188MB 140GB 134GB ext4 6 140GB 194GB 53.7GB linux-swap(v1) primary 4 194GB 301GB 107GB btrfs 5 405GB 512GB 107GB ext4 (parted) quit # mkswap /dev/nvme0n1p6 Setting up swapspace version 1, size = 50 GiB (53687087104 bytes) no label, UUID=6ce1daf4-6a66-44a8-a14b-bd4ea3eb9c40 # swapon --discard # echo "UUID=6ce1daf4-6a66-44a8-a14b-bd4ea3eb9c40 none swap defaults,discard 0 0" >> /etc/fstab
Installed an alternative shell (as listed in /etc/shells
) and added myself
as a user:
# useradd --no-create-home --uid 1001 --user-group avmo --shell /usr/bin/xonsh # passwd avmo
Then to make the desktop and essential components appear:
# systemctl enable sddm NetworkManager tlp
Configure sensors from lm_sensors
:
# sensors-detect # sensors Adapter: ISA adapter Package id 0: +45.0°C (high = +100.0°C, crit = +100.0°C) Core 0: +45.0°C (high = +100.0°C, crit = +100.0°C) Core 1: +44.0°C (high = +100.0°C, crit = +100.0°C) Core 2: +44.0°C (high = +100.0°C, crit = +100.0°C) Core 3: +47.0°C (high = +100.0°C, crit = +100.0°C) Core 4: +42.0°C (high = +100.0°C, crit = +100.0°C) Core 5: +42.0°C (high = +100.0°C, crit = +100.0°C) dell_smm-virtual-0 Adapter: Virtual device fan1: 2288 RPM fan2: 2317 RPM pch_cannonlake-virtual-0 Adapter: Virtual device temp1: +55.0°C acpitz-acpi-0 Adapter: ACPI interface temp1: +25.0°C (crit = +107.0°C) iwlwifi-virtual-0 Adapter: Virtual device temp1: +48.0°C BAT0-acpi-0 Adapter: ACPI interface in0: 12.80 V curr1: 1000.00 uA
Nvidia
The riskiest part, IMHO, although it is well documented. The driver package depends on the GPU model and the kernel. Thankfully no kernel panic occurred by installing:
# pacman -S nvidia xorg-xrandr
Option 1: Nvidia alone
Tried:
# nvidia-xconfig
However, SDDM did not start when X server was configured to use nvidia
display driver. The key was to run some commands before SDDM starts, with
the following lines in /usr/share/sddm/scripts/Xsetup
.
xrandr --setprovideroutputsource modesetting NVIDIA-0 xrandr --auto
Option 2: Optimus Prime
After reading a bit more, I chose NOT to do Option 1, but instead go for
switchable graphics. The following package provides a prime-run
command
and a X server configuration:
# pacman -S nvidia-prime
Rebooted and verified it:
$ xrandr --listproviders Providers: number : 2 Provider 0: id: 0x48 cap: 0xf, Source Output, Sink Output, Source Offload, Sink Offload crtcs: 3 outputs: 6 associated providers: 0 name:modesetting Provider 1: id: 0x2a3 cap: 0x0 crtcs: 0 outputs: 0 associated providers: 0 name:NVIDIA-G0 # pacman -S mesa-demos $ prime-run glxinfo | grep OpenGL
Finally
There was a small hiccup in detecting the external HDMI monitor. Turns out it
was regression due to a change in nvidia-utils
. It was fixed by adding
back the line:
Option "PrimaryGPU" "yes"
to /usr/share/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf
.
CUDA
# pacman -S cuda
Testing:
$ cp -r /opt/cuda/samples/ . $ cd samples/1_Utilities/deviceQuery $ make $ ./deviceQuery ./deviceQuery Starting... CUDA Device Query (Runtime API) version (CUDART static linking) Detected 1 CUDA Capable device(s) Device 0: "Quadro RTX 3000" CUDA Driver Version / Runtime Version 10.2 / 10.2 CUDA Capability Major/Minor version number: 7.5 Total amount of global memory: 5935 MBytes (6222839808 bytes) (30) Multiprocessors, ( 64) CUDA Cores/MP: 1920 CUDA Cores GPU Max Clock rate: 1380 MHz (1.38 GHz) Memory Clock rate: 7001 Mhz Memory Bus Width: 192-bit L2 Cache Size: 3145728 bytes Maximum Texture Dimension Size (x,y,z) 1D=(131072), 2D=(131072, 65536), 3D=(16384, 16384, 16384) Maximum Layered 1D Texture Size, (num) layers 1D=(32768), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(32768, 32768), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total number of registers available per block: 65536 Warp size: 32 Maximum number of threads per multiprocessor: 1024 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 3 copy engine(s) Run time limit on kernels: Yes Integrated GPU sharing Host Memory: No Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Disabled Device supports Unified Addressing (UVA): Yes Device supports Compute Preemption: Yes Supports Cooperative Kernel Launch: Yes Supports MultiDevice Co-op Kernel Launch: Yes Device PCI Domain ID / Bus ID / location ID: 0 / 1 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) > deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 10.2, CUDA Runtime Version = 10.2, NumDevs = 1 Result = PASS
Docker
Installing docker is straightforward, but I wanted to avoid adding my default
login into the docker
group which is root equivalent. So I created a
special user to do this:
# pacman -S docker # systemctl start docker # useradd --no-create-home -g docker docker # passwd $ su - docker
About the author
Ashwin Vishnu Mohanan, Ph.D. in Fluid mechanics