Linux to my taste
2026-03-26
LinuxIn this post I’ll document some of the tweaks I made to customize Linux to my taste. It is the third part of a series about installing Linux on my work laptop.
Living without NetworkManager
This time I decided not to install NetworkManager. I’ll try to only use command-line tools and configuration to manually achieve internet connectivity.
WiFi
I saw iwd for the first time in the Arch Linux
installation ISO, which uses it for WiFi connectivity. In the past, when
I installed Arch, I was always plugged to an ethernet cable, so I didn’t
even notice this tool. I found the experience quite enjoyable, so I
installed it in my main system, too. At every boot, I run:
sudo systemctl start iwd systemd-resolved
The very first time I also had to run iwctl and follow
the instructions, but then iwd will remember the networks
and passwords previously entered. I also enabled
its DHCP client.
While iwd can do DHCP if enabled, it doesn’t have a
built-in DNS resolver, so I use systemd-resolved. Perhaps
in the future I’ll replace both the built-in DHCP client and
systemd-resolved with dnsmasq.
Further reading for my future self:
- https://tailscale.com/blog/sisyphean-dns-client-linux
- https://zwischenzugs.com/2018/06/08/anatomy-of-a-linux-dns-lookup-part-i/
Ethernet
I haven’t had the chance to connect to a wired network yet.
VPN
I use either openconnect or openvpn to
connect to my workplace’s VPNs. For my home lab, I use
wireguard. Everything happens over the command line.
Power saving
In case you have missed the previous chapter, my laptop configuration tries hard to copy a MacBook. One of the best features of Apple hardware is the long battery life, so I had to do something about that. My initial idea was to scale down the CPU frequency, or even try to underprioritize some of the cores. I did a bit of research and I tried auto-cpufreq, but I wasn’t enthusiastic at the idea of having a daemon constantly running in the background. My requirement was much simpler: I didn’t care about fine-tuning and optimization, I just wanted to completely obliterate the CPU frequency when running on battery.
Accomplishing this is quite easy with udev rules. This
is an event-driven system that reacts to changes in the peripherals of
the computer. Users and administrators can define rules that
are triggered upon such events. Initially I wrote my own rules1, but then, after a bit more
research, I decided to install TLP.
Basically, it does the same thing, but with more care and thought than I
could ever hope to put into this project. Not only can it tune the CPU
frequency, but it also does other things to prevent power leaks, such as
turning off unused USB devices and network interfaces. Here is how I
installed it:
sudo pacman -S tlp
sudo systemctl mask systemd-rfkill.service systemd-rfkill.socket
sudo systemctl enable --now tlp
And this is the custom configuration file that I dropped under
/etc/tlp.d/:
DEVICES_TO_ENABLE_ON_STARTUP="wifi"
PLATFORM_PROFILE_ON_AC=balanced
PLATFORM_PROFILE_ON_BAT=low-power
PLATFORM_PROFILE_ON_SAV=low-power
CPU_ENERGY_PERF_POLICY_ON_AC=balance_performance
CPU_ENERGY_PERF_POLICY_ON_BAT=power
CPU_ENERGY_PERF_POLICY_ON_SAV=power
CPU_SCALING_MIN_FREQ_ON_AC=0
CPU_SCALING_MAX_FREQ_ON_AC=4972435
CPU_SCALING_MIN_FREQ_ON_BAT=0
CPU_SCALING_MAX_FREQ_ON_BAT=405914
CPU_SCALING_MIN_FREQ_ON_SAV=0
CPU_SCALING_MAX_FREQ_ON_SAV=405914
On battery, besides enabling the power saving mode, the maximum CPU
frequency is nailed down to 405914 kHz (which is the absolute minimum my
CPU can stand), while on AC power it the limit is brought back to
4972435 kHz. Unfortunately, I couldn’t find a way to set these values
dynamically, but I used tlp-stat -p to find out about the
min and max frequency limits of my CPU.
It is particularly cool to watch the CPU frequency change happen in real time. Under normal usage, I wouldn’t even notice that anything changed, but I can run
watch -n1 "grep MHz /proc/cpuinfo"
to follow the CPU frequency, and see what happens when I unplug the
laptop. Another useful command to debug udev rules is
udevadm control --log-priority=debug; journalctl -f
which shows the events in the system log.
Another thing I tried to do was to set custom charge intervals, so that, for example, the battery only starts to recharge when it’s level goes under a given threshold.
smbios-battery-ctl --set-custom-charge-interval=95 100`
It seems however that my Dell laptop doesn’t support this.
Last but not least, I made sure that hibernation and suspend worked. I didn’t even have to do anything, they just worked out of the box, even with disk encryption and logical volume management. Now if I close my laptop’s lid, it goes into hibernation. At the next startup, I enter the password to decrypt the partition and am immediately brought back to where I was.
Keyboard shortcuts
This section attempts to tracks my shortcuts and how they were set.2
Copying and pasting
Alt+C: copyAlt+V: pasteShift+Alt+V: show clipboard
# File: hypr.conf
# Ref: https://satya164.page/posts/macos-like-shortcuts-in-hyprland
exec-once = wl-paste --primary --watch cliphist store
bind = $mainMod SHIFT, V, exec, cliphist list | wofi --dmenu --pre-display-cmd "echo '%s' | cut -f 2 | tr -d '\n'" | cliphist decode | wl-copy
bind = $mainMod, C, sendshortcut, CTRL, INSERT,
bind = $mainMod, V, sendshortcut, SHIFT, INSERT,
Miscellanea
Virtual console
At boot, I am asked for the password to decrypt the SSD. This prompt
changes the resolution of the screen, for some reason. What is even
weirder is that resolution appears to change 1 second after the prompt
appears, and after I press enter, the resolution goes back to the
original. I found this
post which suggests to disable early KMS start, and it did improve
somewhat: now the resolution changes immediately when the prompt is
shown, not after 1 second. The same user here
suggested that this might just be a bug in the sd-encrypt
hook.
I installed Plymouth and added the corresponding HOOK to
/etc/mkinitcpio.conf, and it did kind of improve the
display. There are still some flickers, though.
I wonder if using a different virtual console, such as KMSCON, would help.
Here they are, for reference:
↩︎SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="0", RUN+="/bin/sh -c 'for policy in `ls /sys/devices/system/cpu/cpufreq/policy*/energy_performance_preference`; do echo power > $$policy; done'" SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="0", RUN+="/bin/sh -c 'for policy in `ls /sys/devices/system/cpu/cpufreq/`; do cat /sys/devices/system/cpu/cpufreq/$${policy}/cpuinfo_min_freq > /sys/devices/system/cpu/cpufreq/$${policy}/scaling_max_freq; done'" SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="0", RUN+="/bin/sh -c 'echo 0 > /sys/devices/system/cpu/cpufreq/boost'" SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="1", RUN+="/bin/sh -c 'for policy in `ls /sys/devices/system/cpu/cpufreq/policy*/energy_performance_preference`; do echo balance_performance > $$policy; done'" SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="1", RUN+="/bin/sh -c 'for policy in `ls /sys/devices/system/cpu/cpufreq/`; do cat /sys/devices/system/cpu/cpufreq/$${policy}/cpuinfo_max_freq > /sys/devices/system/cpu/cpufreq/$${policy}/scaling_max_freq; done'" SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="1", RUN+="/bin/sh -c 'echo 1 > /sys/devices/system/cpu/cpufreq/boost'"Sometimes, if I don’t use a shortcut for an extended period of time, I forget that I had already set it.↩︎
 Marginalia
Leave a comment