void-docs
void-docs copied to clipboard
session-management.md: Proper handling of `XDG_RUNTIME_DIR`
The docs have a section called XDG_RUNTIME_DIR which advises users that are not in a elogind
environment (which takes care of XDG_RUNTIME_DIR
automatically) to manually manage it through the shell:
Alternatively, manually set the environment variable through the shell. Make sure to create a dedicated user directory and set its permissions to 700. A good default location is /run/user/$(id -u).
This is not trivial to do while staying compliant to the XDG spec. Here's the relevant part:
$XDG_RUNTIME_DIR defines the base directory relative to which user-specific non-essential runtime files and other file objects (such as sockets, named pipes, ...) should be stored. The directory MUST be owned by the user, and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700.
The lifetime of the directory MUST be bound to the user being logged in. It MUST be created when the user first logs in and if the user fully logs out the directory MUST be removed. If the user logs in more than once he should get pointed to the same directory, and it is mandatory that the directory continues to exist from his first login to his last logout on the system, and not removed in between. Files in the directory MUST not survive reboot or a full logout/login cycle.
The directory MUST be on a local file system and not shared with any other system. The directory MUST by fully-featured by the standards of the operating system. More specifically, on Unix-like operating systems AF_UNIX sockets, symbolic links, hard links, proper permissions, file locking, sparse files, memory mapping, file change notifications, a reliable hard link count must be supported, and no restrictions on the file name character set should be imposed. Files in this directory MAY be subjected to periodic clean-up. To ensure that your files are not removed, they should have their access time timestamp modified at least once every 6 hours of monotonic time or the 'sticky' bit should be set on the file.
If $XDG_RUNTIME_DIR is not set applications should fall back to a replacement directory with similar capabilities and print a warning message. Applications should use this directory for communication and synchronization purposes and should not place larger files in it, since it might reside in runtime memory and cannot necessarily be swapped out to disk.
On IRC it was recently proposed to instead manage XDG_RUNTIME_DIR
via pam_rundir in environments without elogind
.
It seems there is also another alternative already packaged: rundird
The lifetime requirement is pretty pointless, if programs fail to handle unclean $XDG_RUNTIME_DIR
directories they are buggy, logging out of your desktop environment does not mean all sessions, i.e. ssh will be closed which in turn means the directory is not cleaned.
Note that the rundir repo is archived/unmaintained, and the original author has created an alternative that doesn't remove the directory.
At the moment I have a permanent 0700 dir in .config for each user, and
> cat /etc/profile.d/xdg_runtime_dir.sh
test -d $HOME/.config/$(id -u) && export XDG_RUNTIME_DIR=$HOME/.config/$(id -u)
Which is sort of similar to what the docs suggest, however I had issues with waypipe (ssh -X for wayland):
S10500: 62.445892 [src/server.c:504] Env. var XDG_RUNTIME_DIR not available, cannot place display socket for WAYLAND_DISPLAY="wayland-40PzNuz1sB"
This happens because ssh sessions aren't login sessions, and don't source remote profile scripts by default. Eventually, I solved the issue by putting the same line in ~/.zshenv
for each user.
Maybe dumb_runtime_dir or pam_rundir provide a more general way of doing it, I don't quite understand PAM yet though. If they work, I think it could be worth adding mentions to the docs. My other suggestion is to add a warning about the fact that setting XDG_RUNTIME_DIR
needs to be done for any session, not just "login sessions", so that it is also set when logging in with ssh.
@adigitoleo putting the runtime dir into $HOME
sounds interesting, though not sure why you then also name it by the user. (also, like Duncaen said below, it only works if programs actually follow spec)
that said, the approach using a global dir has the definitive benefit of being in a ramdisk (something usually a normal user can't just mount), thus providing faster access without drive wear, especially since it's pretty much only used for stuff like pid files, sockets, fifos and mmap and doesn't really require any significant space.
also note the specific requirement:
It MUST be created when the user first logs in and if the user fully logs out the directory MUST be removed. […] Files in the directory MUST not survive reboot or a full logout/login cycle.
so essentially you'd have to destroy and remake that directory whenever all "sessions" (however that's defined on your system) of a user quit, something that a simple shell script can't really provide reliably.
PAM / elogind and similar systems however can keep track of this.
My other suggestion is to add a warning about the fact that setting XDG_RUNTIME_DIR needs to be done for any session, not just "login sessions", so that it is also set when logging in with ssh.
but ssh is a login session. and handled by PAM/elogind just fine.
Deviating from /run/user/$UID/
comes with problems when programs don't actually follow the standard, as example chromium will not use XDG_RUNTIME_DIR
and hardcodes /run/user/$UID/
when it setups the sandbox, resulting in permission issues.
I see, thanks for the clarifications. I looked into pam_rundir but it seems there are some unresolved issues around the directory permissions. In this issue an artix guy mentions a fork of the project that apparently solves the issue. Void is not yet packaging that version.
Simple installation of the current pam_rundir package doesn't seem to work. I suppose I need to set up the pam module somehow?
My reservation about elogind does not come from an anti-systemd stance (although lack of systemd is probably an attractive feature of void for many users), but if all I want is to set up a directory and one environment variable, ~200k LOC seems rather overkill, so I'd prefer a simpler package for this.
As I understand, elogind also provides other features, but I don't seem to miss them. If they are really critical, I'd be happy to reconsider using it.
I tried to read through the Arch wiki on PAM but it's still a bit arcane to me. Setting up environment variables seems to be the easy part, but creating/destroying /run/user/$UID
at the right time with the right permissions looks to be tricky.
For the simplest possible solution, would it be reasonable to simply create the directory once, never destroy it (flaunting the spec) and use pam_env to set up the variable?
@adigitoleo I think, unfortunately, pam_env
should not be used to set this variable, since PAM deprecated reading of user environment variables:
Noteworthy changes in Linux-PAM 1.5.0
pam_env: Reading of the user environment is deprecated and will be removed at some point in the future.
https://github.com/linux-pam/linux-pam/releases
There don't seem to be any good alternatives yet: https://www.reddit.com/r/archlinux/comments/l0ascx/pam_env_is_being_deprecated_any_alternatives/
Maybe we just need to wait a bit longer, to see which of the different "PAM rundir" implementations are stable and maintained in the future.
Right now there is:
- rundird, in void repos, but was deprecated 3 days ago
-
dumb_runtime_dir, same author as
rundird
, will be packaged soon, but is only 5 days old. Not completely spec-compliant (doesn't destroy the rundir). From#voidlinux
(with permission):mx08 | My issues are (were?): not packaged, very new, not completely spec-compliant mx08 | All together that leaves me a bit unsure mx08 | (Not for personal usage, but officially recommending it in the docs) mx08 | E.g., what if it will be deprecated in a few months and there is a replacement in rust or so? ;) ifreund | mx08: I wrote it in C this time because I don't want to ever touch the code or think about XDG_RUNTIME_DIR again ifreund | also it's less than 50 lines of code, if you're worried about quality read it yourself ifreund | anyhow, I plan to "maintain" it with the current feature set indefinitely ifreund | "maintain" in quotes because I don't expect to ever need to change anything :P
- pam_rundir in void repos, currently issues on void, created 6 years ago, author does not seem to be very active, no Github release tags, no answers to PRs etc.
- the artix guy's fork of
pam_rundir
, not packaged in void, seems to work on void, 3 months old
Makes sense. I'll probably wait for the dumb_runtime_dir package myself, but I can understand not recommending it. Was lurking IRC today so I've seen that discussion ;)
Another alternative, my favorite is just to create the directories in rc.local and export the variable from profiles.
Closing because the alternatives to manage the lifetime of runtime directories all have issues, the lifetime requirement on runtime directories has not been demonstrated to have any appreciable merit, and this issue has not seen continued activity.