I bought and librebooted a Thinkpad T480 several months ago, and had yet to do anything with it outside of that. I messed around with installing OpenBSD with full-disk encryption, but I was not familiar enough with the BSD differences to really be comfortable diving in to using it as my daily driver. I also had no idea what kind of package support it had compared to distros I had used in the past.
It’s no secret that my daily driver laptop is a pretty hefty Dell Latitude 5540 - I love the laptop, but there are a couple downsides. For one, it’s my work laptop. Not the biggest deal in the world, since we’re a small enough company to not have any sort of MDM or restrictions on software, and I’ve been able to mangle it to my heart’s content. But the main thing is that it’s running Windows 11. I used to have a Linux laptop as my daily driver for several years before being forced into Windows (not really forced, but I didn’t feel like fighting the good fight given events in my life at the time).
Finally though, I’ve gotten 1) the vacation time and 2) the gumption to dive back in.
Selecting a distribution
I looked at several options. My primary criteria was that it was non-systemd, but rolling release was a bonus, and a distribution with a large userbase and maintainer team was preferred. I looked at Artix (Arch-based) and Devuan (Debian-based) primarily - since I wasn’t ready for the dive into OpenBSD, and I had used Arch in the past and still use Debian as my server distribution. I tried out Devuan about a month ago, but I was getting the strangest error on booting the live disk and could never figure out why, so I couldn’t even try to install it. I didn’t try Artix although I seriously considered it. What I ended up landing on was tried and true Void Linux - what I used as my daily driver after Arch. I was, and still am, a little worried about the fact that it’s a smaller team and independent distribution, but it’s stayed under active development for the entire time I’ve been absent from the Linux desktop world. I also remember it being very stable and usable, the repos containing the majority of the packages I needed/wanted, it having a solid documentation website, and their internal tools (e.g. package manager) being great despite the horrible-to-type name of xbps-install (but that’s what aliases are for).
After my experience with Devuan, I expected to run into some funny business installing Void, but I experienced no such issues. It was mostly smooth sailing.
Installation process
- https://docs.voidlinux.org/installation/guides/fde.html
- https://docs.voidlinux.org/installation/guides/chroot.html
I of course intended to install Void with full-disk encryption, as I have done with it and other distributions (Arch and Debian) previously. They have a solid documentation page outlining this process, and I’ve installed and reinstalled Arch so many times by hand (albeit quite a while ago) that I didn’t run into many problems knocking this out. I will leave the majority of the process untyped, as I followed the guide that I already linked 95%. I will outline the steps that I tend to forget, though.
The first was that I had to use the initial SeaBIOS payload in Libreboot to boot from the encrypted disk after installation. In the future I believe that I will re-flash and fully swap to just a SeaBIOS payload in Libreboot, because I don’t think the grub menu has successfully booted anything, despite it touting “including fully encrypted disks” on first menu option. Maybe that’s a user error, but I can’t be bothered. What matters is that the SeaBIOS payload boots my disk just fine.
The second was using LUKS2 instead of LUKS1. I took issue with the documentation page stating that the default LUKS2 key derivation function didn’t work with grub, and specifying to use LUKS1 instead of an alternative KDF as was implied possible by the documentation. I altered the initial cryptsetup command to be the following:
cryptsetup luksFormat --pbkdf pbkdf2 /dev/sdx
This worked just fine. I will note that the first time I ran through the install, I didn’t do this - I simply tried vanilla LUKS2 as an act of rebellion - and it didn’t boot correctly. I’m not sure if I screwed something else up in the process, or if this was the reason for the failure. In any event, the first time I tried this KDF, it worked.
After this, partition your new crypt disk using LVM:
# Create physical volume (pv)
pvcreate /dev/mapper/matrix
# Create volume group (vg)
vgcreate matrix /dev/mapper/matrix
# Create logical volumes (lv)
lvcreate -n root -L 75G matrix
lvcreate -n swap -L 10G matrix
lvcreate -n home -l 100%FREE matrix
Of note here, my RAM size is 32G and my swap size I only set at 10G. I will be going back to correct this, as I’m already running into issues with hibernation.
The remainder of this configuration I’ve already written out in my Debian VPS install.
- Create filesystems using
mkfs.ext4andmkswap - Mount all partitions to the appropriate locations
- Add a keyfile to the drive to unlock at boot (after initial password entry)
- Edit
/etc/crypttab - Create
/etc/fstab(in this case usingxgenfstab)
Last thing to note is the following packages need to be installed for FDE:
xbps-install cryptsetup lvm2
Initial setup
References
Void translations
I’m so used to Debian and systemd at this point that it was weird going back to Void. Here are some of the more common things you’ll run into making this transition:
apt search <pkg-name>=xbps-query -Rs <pkg-name>apt update && apt upgrade=xbps-install -Syusystemctl start <service> && systemctl enable <service>=ln -s /etc/sv/<service> /var/servicesystemctl restart <service>=sv restart <service>journalctl -xeu <service>orsystemctl status service=svlogtail <service>orgrep -r <pattern> /var/log/socklogapt-mark showmanual | sort -u=xbps-query -mxbps-query -m | rev | cut -d- -f2- | rev- one-liner to remove package version
Links
- https://voidlinux.org/
- https://voidlinux.org/download/
- https://voidlinux.org/packages/
- https://docs.voidlinux.org/installation/guides/fde.html
- https://docs.voidlinux.org/installation/guides/chroot.html
- https://docs.voidlinux.org/config/index.html
Basics
Things that I know by heart at this point and don’t need to waste time writing out, but deserve mention here.
- Add a sudo user (wheel group)
- Change root password and user password
- Set locale
- Change timezone (
ln -sf /usr/share/zoneinfo/<country>/<city> /etc/localtime) - Install basic packages
xbps-install git curl wget zsh zsh-syntax-highlighting lf tmux neovim net-tools lsof
Connecting to wifi
I struggled with this, as I am used to the systemd networking stack. I didn’t realize you needed to enable the dhcpcd service for DNS and DHCP so I ended up setting a static IP address and editing /etc/resolv.conf initially. During the install process, there’s a TUI application to connect to wifi which made it easy, but afterwards you have to do some blind fumbling if you’re unfamiliar.
- Enable the
wpa_supplicantservice - Enable the
dhcpcdservice (for DHCP and DNS) - Use
wpa_passphraseto configure your SSID and passphrase
ln -s /etc/sv/wpa_supplicant /var/service
ln -s /etc/sv/dhcpcd /var/service
wpa_passphrase <ssid> <password> >> /etc/wpa_supplicant/wpa_supplicant.conf
sv restart wpa_supplicant
It should auto-connect afterwards. If necessary you can use wpa_cli to connect manually, although this command’s interface / subshell always gives me a migraine.
Setting up a desktop environment
I’ve been somewhat following the Linux desktop world, and in recent years I’ve noticed Wayland coming onto the scene as a potential replacement for Xorg. I tried it out, but I gave up pretty quickly and will spare the details. I wanted to have a functional desktop and spend the rest of my vacation time tinkering as opposed to spending the entire time trying to get Wayland up and running, then re-learning all my configurations and rewriting all my dotfiles to work. I ended up back on Xorg fairly quickly.
Here’s the installs for basic Xorg, as well as the programs that I use for my desktop “environment”.
Basics for Xorg
xbps-install xorg-minimal xorg-fonts mesa-dri
This installs the very minimum Xorg packages, as well as a font package and graphics drivers.
Power and session/seat management
xbps-install elogind dbus turnstile tlp
I tried to get the acpid, seatd, and turnstile stack working (so as to stay away from elogind), but I could not get acpid to play nice with locking the screen, suspending, and hibernating. (I was able to set up custom user hooks for zzz and ZZZ, but whenever I ran it through the /etc/acpi/handler.sh, it wouldn’t work.) I ended up going with elogind.
elogind- user logins, system power / ACPI eventsdbus- I had to install and enable its service to getelogindnot to fail silently.
turnstile- session managementtlp- battery saving
Install all 4 of these and enable their services, make sure to disable the acpid service. Also make sure to set manage_rundir = no in /etc/turnstile/turnstiled.conf.
Logging
Since this isn’t enabled by default: install socklog-void, enable socklog-unix and nanoklogd services.
Alternatively, rsyslog is packaged for Void, and I might move to that since I’m more used to it. (I think it must be a user error, but I’m not doing very well for myself with socklog so far.)
Sound
Install alsa-utils and apulse. Enable the alsa service to retain volume level through a reboot.
Specific programs
I was super happy with how almost all programs that I had previously used just slotted right in, with minor adjustments for different hardware. Considering my extreme rustiness and the fact that it’s been several years for these programs to go potentially unmaintained, everything went very well.
Terminal - alacritty
In the past, I have used suckless’s programs - in this case st - as I liked their minimal approach. What I do not like is having to recompile every time I want to change a minor setting, and while editing their “config” file is relatively easy, I do not code, and definitely not in C. So I decided to try out alacritty again, as I had a config file for it that I obtained at some unknown time and some unknown place. With a few edits, as well as converting from yaml to toml (which they provided a very neat command to do), I had a perfectly functional graphical terminal running.
There’s not much of note here, most of my configuration happens within the shell as opposed to the temrinal program. I just want sane defaults, unlike xterm’s ungodly 6pt black-on-white text (like seriously?).
Window manager - bspwm
I use bspwm primarily because that’s what I used in the past and I have a perfectly functional config file.
It’s a tiling window manager first and foremost, which is a must for me, and I adore that you can control its functionality from shell commands - meaning that instead of having multiple places to maintain keybinds, I have my one hotkey daemon configuration file and that’s it.
Despite being several years since I’ve used a proper tiling WM, I got used to my keybinds again quite quickly. It also helps that I can rebind on a whim if I don’t like something, but I haven’t really changed anything.
Hotkey daemon - sxhkd
Stands for simple X hotkey daemon. Keyword X - this is the primary reason I gave up on Wayland - all these hotkeys were going to be a bitch to recreate.
The config for this is fantastic. The gist is the following:
super + Return # hotkey combination here
$TERMINAL # command to run here
I can run any command or script that I want, bound to any key, with basically no restrictions, by adding or editing two lines of text in a config file. It’s the best thing since sliced bread.
Launcher - rofi
Another one that previously I would have used a suckless tool - dmenu. And another one I decided to replace, because I couldn’t be bothered to unearth my old configuration, and generally wanted to move away from that style to a more modern dotfile approach. I installed rofi, and it mostly works out of the box, just with a bit of a learning curve and odd non-POSIX style options (in the same vein as find - full word options with a single dash, like rofi -show).
The most time I spent on this one was getting it to look and function like dmenu. I was editing the wrong theme file and having trouble with the format, but it was mostly a breeze once that was corrected.
Taskbar - polybar
I discovered my laptop had two batteries while setting this up! This is another one that I had done extensive work on previously, and didn’t need to reinvent the wheel, just some edits to fit the new hardware.
Compositor - picom
Because my monkey brain likes transparency and fade effects. Not much to say here, as this one isn’t super necessary.
Notification manager - dunst
Not that I use this much, but it is nice (and I already had a config). Simple, and scripts nicely. (For an example of its scripting: I wrote a dead simple “now playing” script that would run every time I would play/pause music by piping current music information from mpc to notify-send. And with sxhkd, xi was as simple as binding a key to mpc toggle && nowplaying.
File manager - lf
pcmanfm as a GUI backup, but TUI file managers are just strictly superior. lf is another that scripts very nicely and I had previously done a ton of work (mostly pilfering) on my config file.
Editor - neovim
I think this goes without saying. And it doesn’t really count as a desktop environment program, but it’s a mainstay of my workflow and deserves mention.
Screen locker - slock
I fought with acpid and its configuration file /etc/acpi/handler.sh for quite some time, as it is the default standalone that comes with Void, as I mentioned above in the power/session/seat management bit. Turns out xss-lock works great alongside elogind.
Miscellaneous other programs
redshift- to filter that accursed blue lighttdrop- for a dropdown Quake-style terminalxcape,xmodmap,xinput,xset,setxkbmap- for key remaps (namely, caps lock to escape)sxiv- image viewerzathura- PDF viewermpv- video playerbc- for CLI mathmaim- for screenshotssyncthing- for syncing files between laptops/phonexwallpaper- to set my pretty picturefastfetch(RIPneofetch)font-awesomeandgucharmap- for supporting and browsing icons/emoticons, respectivelymononokifont for default monospace - not available in repos, need to download and install to font directorytrash-cli(becauserm -rfis too much power sometimes)keepassxc,yubikey-manager,pcsc-ccid,pcsclite,u2f-hidraw-policy,gnupg2-scdaemon- password management and Yubikey support (more below)firefox(the least worst modern web browser)
Miscellaneous
Tailscale
Run this command once so you don’t need to run it as sudo every time from then on:
sudo tailscale up --operator $(whoami)
Typical command for me to run Tailscale is the following (I think the accept DNS is true by default, but why not specify just in case):
tailscale up --accept-dns=true --accept-routes=true
I was also encountering Tailscale and dhcpcd fighting over the /etc/resolv.conf file, which I had to fix by adding the following line to /etc/dhcpcd.conf and restarting the service:
# /etc/dhcpcd.conf
nohook resolvconf
This gives Tailscale full reign over the /etc/resolv.conf file. In a pinch, if Tailscale isn’t up, can still edit it manually to a public resolver.
zsh
I realized remarkably late into this whole configuration process that my ~/.profile configuration was not being sourced at all. I’m really confused by this, because I used zsh extensively in the past, and I must have encountered this at some point. And I know that file was being sourced. Not sure.
Anyway, the fix is to create a ~/.zprofile with the following contents:
emulate sh
. ~/.profile
emulate zsh
The other thing I figured out was all this weird highlighting going on ever since I refactored my .zshrc file. Turns out, it wasn’t really the file edits, it was the location of the zsh-syntax-highlighting configuration. I never got an error because the error output gets piped down the toilet to /dev/null in my configuration.
In my Debian WSL, the highlighting was mostly fine and more an annoyance than anything. In this new setup, for whatever reason, all typed text and terminal output was getting highlighted green. I fixed the filepath and now syntax highlighting is working again.
Yubikey support
Helpful reference: https://blog.pauljako.de/voidlinux/yubikey/2025/11/23/voidlinux-and-yubikeys.html
I don’t know if all these packages are strictly necessary - all I want to do is have access to my Yubikey to unlock my Keepass database, not use it for unlocking the drive (among other things) as is outlined in the reference post above.
# Install packages
xbps-install u2f-hidraw-policy gnupg2-scdaemon yubikey-manager pcsc-ccid pcsclite
# Enable service
ln -s /etc/sv/pcscd /var/service
# Add user to plugdev group
usermod -aG plugdev user
Screen lock, sleep, and hibernate
Target configuration:
- Lock the screen and sleep on 15 minutes of inactivity.
- Lock the screen and sleep on lid close.
- After sleeping, hibernate to disk after 30 minutes.
- Ignore hibernation if plugged into AC or dock.
Configuration steps:
xbps-install elogind xss-lock slock
# ~/.xprofile
# ...
xset s 600 s blank & # blank the screen after 10 minutes
xss-lock slock & # subscribe to acpi and dpms events with slock
# /etc/elogind/logind.conf
[Login]
# ...
HandleLidSwitch=suspend-then-hibernate
HandleLidSwitchExternalPower=suspend
HandleLidSwitchDocked=suspend
# ...
IdleAction=suspend-then-hibernate
IdleActionSec=15min
# ...
# /etc/elogind/sleep.conf
# ...
[Sleep]
AllowSuspend=yes
AllowHibernation=yes
AllowSuspendThenHibernate=yes
# ...
HibernateDelaySec=30min
# ...
Hotkeys - add sleep time to make sure locker activates before sleeping.
# .config/sxhkd/sxhkdrc
# ...
# lock the screen then sleep
super + z
xset s activate; sleep 2; loginctl sleep-then-hibernate
# lock the screen
super + c
xset s activate
(From what I understand, this should be working, and it mostly does, but what I don’t get is that it won’t automatically sleep on idle. If I close the lid, it works fine; if I execute loginctl sleep-then-hibernate, it also works fine, but just letting the laptop chill the only thing that happens is the screen blanking after 10 minutes.)
AppImages
Some packages aren’t available via the default repositories. I ended up installing AppImages wherever possible, and just putting their executables into my ~/.local/bin/ directory.
Betterbird (email client, Thunderbird fork) was especially awkward. They include a script to install it, but then the executable is in a really odd location that I don’t want to add to my PATH variable. So, I just symlinked the executable to my scripts directory.
Todoist was also a pain - not surprising with a proprietary GUI program - it wants me to register it with AppImageLauncher every time I open it, and I haven’t figured out a workaround yet.
SSH authentication
All my devices are gated behind both publickey and password authentication, so I had to 1) generate a new SSH key (using a better algorithm this time, I’m still using RSA on my WSL), 2) edit the SSH config on each device to alllow password authentication, 3) log in to each device and ssh-copy-id the new key, and 4) re-enable the publickey and password authentication.
To generate a new SSH key:
ssh-keygen -t ed25519 -C "default"
Resizing swap partition
In my case, I had 391G allocated to my /home partition, and 10G allocated for swap. Wanted to increase the swap size to 40G for hibernation purposes - probably overkill, as my RAM is 32G, but I have a lot of extra space.
# Make sure volumes are unmounted and off
umount -R /home
swapoff /dev/mapper/matrix-swap
# Check and reduce size of filesystem
e2fsck -f /dev/mapper/matrix-home
resize2fs /dev/mapper/matrix-home 361G
# Reduce size of logical volume - AFTER reducing size of filesystem, to avoid data loss
lvreduce -L 361G /dev/mapper/matrix-home
# Increase size of swap
lvextend -L +30G /dev/mapper/matrix-swap
# Remount filesystems, re-enable swap
mount /dev/mapper/matrix-home /home
swapon /dev/mapper/matrix-swap
Syncthing
Pulled from https://github.com/syncthing/syncthing/blob/main/etc/linux-runit/README.md
- Install
syncthing. - Edit the run file given in the repository - add your username and the location of the syncthing binary.
- Add this to the
/etc/sv directory and rename it tosyncthing-user` or something so it doesn’t conflict with the system-wide service (if it exists). - Link it to the
/var/servicedirectory so it starts automatically.
Launch window manager with dbus
I’ll be honest, I’m still trying to wrap my head around session bus vs system bus, seat management, session management, ttys, and all the associated programs - seatd, turnstile, elogind, dbus, etc. But notifications seemed not to be working with dunst for programs like Signal and Todoist. Adding this to my ~/.xinitrc seemed to do the trick, as opposed to just exec /bin/bspwm.
# ~/.xinitrc
#!/bin/sh
[ -f ~/.xprofile ] && . ~/.xprofile
exec dbus-launch /bin/bspwm
Items remaining
Many of these will probably warrant their own posts.
- Configure dock and second monitor
xrandroutputbspwmsecondary monitorsxhkdkeybinds to navigate between monitorspolybarfor second monitor- Can I get sound to output to my expensive speakers?
- Set up
neomuttas TUI email client - Configure
lf- install dependencies for preview and opening files, set keybinds - Configure
xrdb/Xresourcesfor default desktop colors and fonts - Clean up scripts and dotfiles, backup to git repository
- Figure out Quick Add for Todoist - somehow, the Linux version doesn’t include support for this keybind??? Or maybe - this is finally my cue to replace it.
- Set up
rclonefor access to remote backups
List of manually installed packages
For future reference:
Signal-Desktop
alacritty
alsa-utils
apulse
base-system
bc
bspwm
cifs-utils
cryptsetup
curl
dbus
dunst
elogind
fastfetch
firefox
font-awesome
git
gnupg2-scdaemon
grub
gucharmap
jq
keepassxc
lf
libreoffice
lsof
lvm2
maim
mesa-dri
mpv
neovim
net-tools
nmap
openresolv
pcmanfm
pcsc-ccid
picom
polkit
polybar
redshift
rofi
seatd
setxkbmap
slock
socklog
socklog-void
speedtest-cli
sxhkd
sxiv
syncthing
tailscale
tdrop
tlp
tmux
trash-cli
turnstile
u2f-hidraw-policy
void-repo-nonfree
wget
xautolock
xcape
xclip
xdg-utils
xinput
xmodmap
xorg-fonts
xorg-minimal
xrandr
xrdb
xset
xss-lock
xterm
xwallpaper
xz
yubikey-manager
zathura
zsh
zsh-syntax-highlighting
Wrap-up
I’ve been working on this post for the better part of 3 weeks now, because I wanted to get everything perfect as a reference if I ever had to run through this process again. As per usual, though, nothing is perfect, and I’m learning while iterating, so some of this is already outdated. I’ve had to adjust as I went.
And now, I’ve completely switched distributions after fighting with elogind and hibernation failures. I realized that while I like Void a lot, Artix probably meets my requirements while giving me access to the Arch infrastructure (including the AUR and vanilla Arch packages), while having more active development. It also comes with your choice of init system, including runit.
The main reason behind this is when I was troubleshooting the hibernation issues (about 50% of the time, hibernation would have a memory mismatch), I found that Void’s kernel had last been updated about 7 months prior. It was (and still is as I write this) on version 6.12, whereas the current kernel version is on version 6.18. I don’t know if the kernel version was actually the issue, but at the time I made the decision to switch, I had been fighting other issues and I figured this was a sign of things to come.
Much of the knowledge is transferable anyhow! And much of my configs should be transferable too, but we’ll get to that in my next post…
EOF