A pleasant Arch Linux setup
Recently I distrohopped back to Arch Linux on my laptop and, given the opportunity for a fresh start, wanted to keep the setup tidy. In this post I note down a bunch of small changes I made that make my system more neat, lean and aesthetically pleasant by my judgement. I will (hopefully) periodically update this post as I find and implement new improvements.
Environment variables
First order of business is setting environment variables since so
much else is configured through them. Traditionally one might put their
variables into shell initialization files, such a
~/.profile or ~/.bashrc. I don’t like this for
a few reasons. First it pollutes my home directory with configuration
files that don’t belong there, and second it’s not portable across
shells. If you opt to use fish
shell as I do then .profile will not be loaded by
default, you’ll have to create
a fishlogin file that sources it manually.
A better solution I found is to use systemd’s
environment.d to set variables set by the corresponding systemd user
service (user@<uid>.service). I created the
~/.config/environment.d directory and populated it with a
few files for different types of assignments. For example here’s the
file I use to set my XDG base directories:
# ~/.config/environment.d/10-user-dirs.conf
XDG_CONFIG_HOME=$HOME/.config
XDG_CACHE_HOME=$HOME/.cache
XDG_DATA_HOME=$HOME/.local/share
XDG_STATE_HOME=$HOME/.local/state
This approach has a few benefits and a few downsides. It means my
variables aren’t dependent on my shell, that they’re located in a common
location, and have a dead-simple format that’s not interspersed with
other shell stuff. However it also means that ~/.config/ is
necessarily my config home (after all you can’t read
$XDG_CONFIG_HOME before you’ve set it) and that reloading
my environment requires reloading the user service and all services
after it. So far the easiest way I’ve found to do this is to do a full
systemctl soft-reboot.
Keeping my $HOME clean
In our blessed year of 2026 a nontrivial amount of programs still don’t respect the XDG Base Directory Specification by default. Thankfully a lot of them have environment-based configuration options I can use to fix that. To detect such cases I periodically run xdg-ninja which helpfully lists out offending programs on my system as well as the fix, if any is available.
Most fixes tend to be environment variables, and as such I have the
following file in my environment.d
# ~/.config/environment.d/40-xdg-ninja.conf
CARGO_HOME=$XDG_DATA_HOME/cargo
RUSTUP_HOME=$XDG_DATA_HOME/rustup
# ...
SSH agent
Loading the SSH agent is yet another pain point when using a shell
based approach. The Arch wiki even recommends using a bash
snippet in your .bashrc that uses pgrep to
find the current running ssh agent instance and source its environment
variable in the current shell as a method of dealing with it. Too janky
for my tastes. Thankfully the very next section notes that a systemd
user service for the agent is included with the openssh
package that I can use it instead, so long as I set the
SSH_AUTH_SOCK environment variable manually.
Therefore an invocation of
systemctl --user enable ssh-agent.service along with
creating the following environment file solves my troubles.
# ~/.config/environment.d/30-ssh-agent.conf
SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent.socket
Xwayland
By default the xwayland-satellite package does not start
the satellite nor set up a service for it. It should be clear by now
that I prefer using systemd services for this sort of thing rather than
mechanisms like niri’s spawn-at-startup. Therefore I
dropped this service
file into my user services.
# ~/.config/systemd/user/xwayland-satellite.service
[Unit]
Description=Xwayland outside your Wayland
BindsTo=graphical-session.target
PartOf=graphical-session.target
After=graphical-session.target
Requisite=graphical-session.target
[Service]
Type=notify
NotifyAccess=all
ExecStart=/usr/local/bin/xwayland-satellite
# ^^ this needed adjustment ^^
StandardOutput=journal
[Install]
WantedBy=graphical-session.target
X based applications also expect the DISPLAY environment
variable to be set so I created put that into my wayland workarounds
environment file. That file also contains other environment-based hints
to programs that they should really use wayland pretty-please.
# ~/.config/environment.d/20-wayland-hints.conf
DISPLAY=:1
ELECTRON_OZONE_PLATFORM_HINT=wayland
_JAVA_AWT_WM_NONREPARENTING=1
I’m not sure whether the exact number you choose for the display has any effect.