# A pleasant Arch Linux setup
# ~/.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](https://specifications.freedesktop.org/basedir/latest/)
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](https://github.com/b3nj5m1n/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](https://wiki.archlinux.org/title/SSH_keys#ssh-agent) 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](https://github.com/Supreeeme/xwayland-satellite/blob/main/resources/xwayland-satellite.service)
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.