One of the nice perks of having a new job is that with it comes a new laptop and an oportunity to redocument getting Arch in it. The people at Jodel were super kind and got me a brand new Thinkpad P51s and I spent the last week playing with it and learning a lot in the process.
But for me, this exercise is more than just installing the OS. One of the promises of Arch is to be your whatever you want it to be. After all, you install it and you only have the terminal and the root user. So for me, going through several iterations of installing Arch gives me a chance to add new features and remove old things that ended up not working so well.
For this iteration, here’s what I want to do:
- Do as much as possible relying only on systemd and udev;
- Get rid of GRUB and move fully to UEFI boot;
- Use a swapfile instead of swap partition;
- Come up with a different Window Manager (already tried xmonad, i3 and sprectwm – this time ended up with AwesomeWM);
- Getting rid of a few things which I didn’t like (xscreensaver, wicd,
- Be much more deliberate in the area of automation and power management.
These were all things which I did not focus on in my last build and so it’s time to set up a new baseline.
The installation follows pretty much what the Arch Wiki says. I relied almost completely in it so in this document I mostly explain the things I changed.
EFI Boot and a bootloader
Turns out that the requirements to have the system boot from EFI are pretty straightforward, but do require you to read some stuff before jumping into the instalation. Besides guaranteeing that your system booted in UEFI mode, spend some time reading about the boot loaders you have available. I opted for systemd-boot and this was my reading list:
Note that in the instalation guide, this step comes at the end. However, there is quite a bit of reading and checking that needs to be done so spending the time upfront doing this is a good idea.
Network connection and system clock
It goes without saying that it’s better to be connected to the internet as you do all of this. You’ll also need to enable network time synchronization:
timedatectl set-ntp true
Here’s my partitioning scheme:
- No swap partition (I’ll create a swapfile later in this guide);
/bootpartition is of type
/partition is the rest of the disk space (
- The naming of the devices is different because my SSD is connected via PCIe.
Formatting and mounting
mkfs.ext4 /dev/nvme0n1p2 mkfs.fat -F32 /dev/nvme0n1p1 mount /dev/nvme0n1p2 /mnt mkdir /mnt/boot mount /dev/nvme0n1p1 /mnt/boot
I followed the installation guide to the letter. I still leave the individual commands I issued here for completion:
Installing base system
pacstrap /mnt base genfstab -U /mnt >> /mnt/etc/fstab
Chroot and System Configuration
arch-chroot /mnt pacman -Syyu emacs-nox connman intel-ucode wpa_supplicant
ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime hwclock --hctosys
Confirm that the time is correct with
Locale and Console
emacs /etc/locale.gen and uncommented
en_GB.UTF-8 UTF-8. After that:
locale-gen echo 'LANG=en_GB.UTF-8' > /etc/locale.conf echo `KEYMAP=pt-latin9` > /etc/vconsole.conf echo `FONT=Lat2-Terminus16` >> /etc/vconsole.conf
My new machine is called voyager.
echo 'voyager' > /etc/hostname echo '127.0.1.1 voyager.localdomain voyager' >> /etc/hosts
As I mentioned before, there is a lot more to these steps. I went through some trial and error but this is, essentially, what you need:
bootctl --path=/boot install cp /usr/share/systemd/bootctl/loader.conf /boot/loader/loader.conf cp /usr/share/systemd/bootctl/arch.conf /boot/loader/entries/arch.conf
With these files in place, you’ll have to run
blkid -s PARTUUID -o value /dev/nvme0n1p2 to find out the UUID of the root partition and add it to
/boot/loader/entries/arch.conf. That file will look something like this:
title Arch Linux linux /vmlinuz-linux initrd /initramfs-linux.img options root=PARTUUID=14420948-2cea-4de7-b042-40f67c618660 rw
mkinitcpio -p linux
Passwd and reboot
Finally we give a password to root, exit the chroot shell, unmount the system and reboot:
passwd exit umount -R /mnt systemctl reboot
After rebot you should now be in your freshly installed Arch Linux. We’re ready to configure it.
Settinng up Wifi
wpa_supplicant were already installed, it’s now time to play with it. Following the instructions in the connman page should be enough:
systemctl --type=service to check if there’s any other network service running and if so disable it. Then:
systemctl enable connman.service systemctl reboot
After rebooting, the sequence of commands should be something like:
connmanctl technologies connmanctl enable wifi connmanctl services
The last command should show you the nearby SSIDs. If that worked, it’s time to permanently connect, using connmanctl in interactive mode:
connmanctl scan wifi services agent on connect wifi_... quit
Disconnect the wired connection and reboot. You should end up with wifi connected and in the SSID you chose.
I also added some configuration to
[General] AllowHostnameUpdates=false PreferredTechnologies=ethernet,wifi SingleConnectedTechnology=true
Fish and adding a user
pacman -S sudo
visudo and uncomment the
wheel group line. Now let’s ge Fish and set it up for root and the new user:
pacman -S fish chsh -s /usr/bin/fish
Exit and login again. If Fish is working fine for root, we add the new user:
useradd --shell /usr/bin/fish --create-home -m -G wheel luis passwd luis
From now on, I’ll always assume the user is no longer root (and therefore will be sudoing everything which needs to be sudoed).
Graphics and Xorg
Since my system has dual graphics setup, we can’t go about this just by installing the
nvidia package. We’re going to use
bumblebee for Optimus:
sudo pacman -S bumblebee mesa nvidia xf86-video-intel bbswitch sudo gpasswd -a luis bumblebee sudo gpasswd -a root bumblebee sudo systemctl enable bumblebeed.service sudo systemctl reboot
We’ll now verify this setup by installing Xorg and minimal window manager:
sudo pacman -Syyu xorg xorg-xinit awesome echo 'exec awesome' > ~/.xinitrc localectl set-x11-keymap pt pc104 "" caps:ctrl_modifier,terminate:ctrl_alt_bksp startx
You should now see the awesome window manager and your mouse and keyboard should work fine.
Last thing we’ll do is to enable Early Kernel Mode Setting, by adding two modules to
sudo mkinitcpio -p linux and
reboot. You should notice the terminal with higher quality from way sooner in the boot process.
I have most of my config for xinit, awesome and many other things in my dot files repo but to eventually change it I need to have the SSH-Agent up and running.
There’s many ways to go about it. I went with adding it to my
fish.config, which required some effort to export the environment variables which
############################################### ## SSH Agent setenv SSH_ENV $HOME/.ssh/environment function start_agent ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV chmod 600 $SSH_ENV . $SSH_ENV > /dev/null ssh-add end function test_identities ssh-add -l | grep "The agent has no identities" > /dev/null if [ $status -eq 0 ] ssh-add if [ $status -eq 2 ] start_agent end end end if [ -n "$SSH_AGENT_PID" ] ps -ef | grep $SSH_AGENT_PID | grep ssh-agent > /dev/null if [ $status -eq 0 ] test_identities end else if [ -f $SSH_ENV ] . $SSH_ENV > /dev/null end ps -ef | grep $SSH_AGENT_PID | grep -v grep | grep ssh-agent > /dev/null if [ $status -eq 0 ] test_identities else start_agent end end
After this, you should be able to run
ssh-add ~/.ssh/id_rsa from any terminal.
Following the instructions is enough and I did nothing special to set up a swap file:
sudo fallocate -l 32G /swapy sudo chmod 600 /swapy sudo mkswap /swapy sudo swapon /swapy echo '/swapy none swap defaults 0 0' | sudo tee --append /etc/fstab
Let’s also take the oportunity to set a lower swappiness setting:
echo 'vm.swappiness=5' | sudo tee /etc/sysctl.d/99-sysctl.conf
Reboot and then confirm the new swapiness level with
sudo cat /proc/sys/vm/swappiness
For power management we’re going to rely completely on systemd, and not use the acpid service.
Enable hibernate to swap file
Following the instructions in the power management page was enough to make this work:
sudo filefrag -v /swapy to find the offset of the swap file. Then add it along with the partition UUID of the root partition to the boot loader arch entry file:
echo 'resume=PARTUUID=3e44d3f3-d4c2-4347-9a87-8ac529c615f2 resume_offset=7421952..' | sudo tee --append /boot/loader/entries/arch.conf
Then add the
resume hook to the hooks section in
sudo mkinitcpio -p linux, reboot and then try to force a hibernate:
Pressing the power button after hibernate should bring you back from hibernation.
Hibernate on lid down
By default, when I bring the lid down the laptop suspends, rather than hibernating. Here’s how to make it hibernate:
echo 'HandleLidSwitch=hibernate' | tee --append /etc/systemd/logind.conf
Reboot and it should be working.
Lock screen when coming out of hibernate and suspend
sudo pacman -S slock
sudo emacs /etc/systemd/system/slock@.service and add the following to it:
[Unit] Description=Lock X session using slock for user %i Before=sleep.target [Service] User=%i Environment=DISPLAY=:0 ExecStartPre=/usr/bin/xset dpms force suspend ExecStart=/usr/bin/slock [Install] WantedBy=sleep.target WantedBy=hibernate.target
Enable it with
systemctl enable email@example.com.
Screen backlight control
sudo pacman -S xorg-xbacklight xbindkeys
xbacklight --help to learn how to use it and assign the appropriate keys to increasing and decreasing the screen luminosity in a
echo "blacklist bluetooth" | sudo tee /etc/modprobe.d/bluetooth.conf echo "blacklist btusb" | sudo tee /etc/modprobe.d/btusb.conf
sudo emacs /etc/mkinitcpio.conf and make the
FILES section include our two new files:
sudo mkinitcpio -p linux reboot
Enabling powersave for the audio card
lspci -k to find out your sound card’s driver and then (maybe replacing
echo "options snd_hda_intel power_save=1" | sudo tee /etc/modprobe.d/audio_powersave.conf
cp /usr/share/X11/xorg.conf.d/40-libinput.conf /etc/X11/xorg.conf.d/
And then change it accordingly:
Section "InputClass" Identifier "Touchpad" MatchIsTouchpad "on" MatchDevicePath "/dev/input/event*" Option "Tapping" "on" Option "DisableWhileTyping" "true" Driver "libinput" EndSection
The only thing I had to do, to control the sound with the keyboard keys (and set them with xbindkeys), was to install
We’re going to use the
reflector package to have an updated mirror list at all times.
sudo pacman -S reflector
We now set it so that reflector runs on two occasions: when pacman updates its mirror list, and automatically, every week.
When pacman updates its mirror list
sudo emacs /etc/pacman.d/hooks/mirrorupgrade.hook
and then use the following code:
[Trigger] Operation = Upgrade Type = Package Target = pacman-mirrorlist [Action] Description = Updating pacman-mirrorlist with reflector and removing pacnew... When = PostTransaction Depends = reflector Exec = /usr/bin/env sh -c "reflector --sort score -c Germany -c Denmark -c Poland -c "Czech Republic" -c Switzerland -c Austria -c Netherlands -c France -c Luxembourg -c Belgium -a 24 -p https --save /etc/pacman.d/mirrorlist; if [[ -f /etc/pacman.d/mirrorlist.pacnew ]]; then rm /etc/pacman.d/mirrorlist.pacnew; fi"
Automatically, every week
We need two files, first the actual unit we’ll be running:
sudo emacs /etc/systemd/system/reflector.service
[Unit] Description=Pacman mirrorlist update [Service] Type=oneshot ExecStart=/usr/bin/reflector --sort score -c Germany -c Denmark -c Poland -c "Czech Republic" -c Switzerland -c Austria -c Netherlands -c France -c Luxembourg -c Belgium -a 24 -p https --save /etc/pacman.d/mirrorlist
and then the systemd timer
sudo emacs /etc/systemd/system/reflector.timer
[Unit] Description=Run reflector daily [Timer] OnCalendar=weekly RandomizedDelaySec=2h Persistent=true [Install] WantedBy=timers.target
We enable and start the timer:
sudo systemctl enable reflector.timer sudo systemctl start reflector.timer
Some closing remarks
It is clear that having a good command of systemd and udev is quite essential to do (local) system administration in (Arch) Linux. The nice thing is that they are both quite well documented and both are thought from the ground up as a base to build a lot of automation.
As I just went through this installation log, I cannot help but think that there’s already more things I would like to change:
- When coming out of suspend and hibernate, connman sometimes has no connection. I would prefer to forcefully disable wifi when hibernating and then enabling it when resuming;
- There is a systemd service to control backlight, which I’m not using;
- Making backlight controls more intelligent would also be cool, like bringing it down as the night approaches;
- Something like f.lux for linux would also be really nice;
- udev can do so many things… one interesting one would be to load an
arandrprofile when I connect a VGA or HDMI cable to the laptop;
- obviously I still have none of the development dependencies installed… from docker to go there’s plenty of work to still be done here.
But for now, what’s done is finished.