Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: Set up XDG Base Directory environment variables #224525

Open
3 tasks done
SuperSamus opened this issue Apr 3, 2023 · 14 comments
Open
3 tasks done

Documentation: Set up XDG Base Directory environment variables #224525

SuperSamus opened this issue Apr 3, 2023 · 14 comments

Comments

@SuperSamus
Copy link
Contributor

SuperSamus commented Apr 3, 2023

Problem

XDG Base Directories are environment variables that allow to organize the location of configuration, data, etc. in the home directory.
Even with the default values, they make the user's $HOME much cleaner: for example, Git by default stores its configuration in ~/.gitconfig, but with XDG_CONFIG_HOME set then it will be stored in XDG_CONFIG_HOME/git/config.

The problem is: in NixOS, how does one set up these environment variables declaratively?

A solution could be Home Manager, which has the option programs.xdg.enable (which needs to be combined with programs.<shell>.enable in order to work). However, using Home Manager for such a simple thing is a bit overkill.

Another solution, according to the Arch Wiki, would appear to be:

environment.sessionVariables = {
  XDG_CACHE_HOME  = "@{HOME}/.cache";
  XDG_CONFIG_HOME = "@{HOME}/.config";
  XDG_DATA_HOME   = "@{HOME}/.local/share";
  XDG_STATE_HOME  = "@{HOME}/.local/state";
}

However, environment.sessionVariables doesn't support @{HOME}. You could use \${HOME} instead, however it may not be initialized when pam_env sets up these environment variables. It happens for example when logging in via TTY to a Fish shell.

Basically, every way I found to set up these variables has a flaw.

Proposal

Maybe creating some NixOS options specifically for setting up the XDG Base Directories?

Checklist

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Apr 3, 2023

You could use ${HOME}instead, however it may not be initialized when pam_env sets up these environment variables. It happens for example when logging in via TTY to a Fish shell.

I have been using this

  environment.sessionVariables = {
    XDG_CONFIG_HOME = "$HOME/etc";
    XDG_DATA_HOME   = "$HOME/var/lib";
    XDG_CACHE_HOME  = "$HOME/var/cache";
  };

for a number of years now and never noticed any issue.

@SuperSamus
Copy link
Contributor Author

You could use \${HOME} instead, however it may not be initialized when pam_env sets up these environment variables. It happens for example when logging in via TTY to a Fish shell.

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Apr 4, 2023

It works for me: I actually use fish and always log in a tty before starting the graphical session. I'm quite surprised to hear you say this.

@SuperSamus
Copy link
Contributor Author

SuperSamus commented Apr 4, 2023

I get this error after logging in:

error: can not save history
warning-path: Unable to locate data directory derived from $XDG_DATA_HOME: '/.local/share/fish'.
warning-path: The error was 'Permission denied'.
warning-path: Please set $XDG_DATA_HOME to a directory where you have write access.
error: can not save universal variables or functions
warning-path: Unable to locate config directory derived from $XDG_CONFIG_HOME: '/.config/fish'.
warning-path: The error was 'Permission denied'.
warning-path: Please set $XDG_CONFIG_HOME to a directory where you have write access.
/nix/store/lyicmql3ws929d7azr65h25b2hyakmb6-coreutils-9.1/bin/mkdir: cannot create directory þ/generated_completionsþ: Permission denied
mkdir: cannot create directory þ/completionsþ: Permission denied
mkdir: cannot create directory þ/conf.dþ: Permission denied
mkdir: cannot create directory þ/functionsþ: Permission denied
warning: An error occurred while redirecting file '/config.fish'
open: Permission denied
Welcome to fish, the friendly interactive shell
Type help for instructions on how to use fish

@SuperSamus
Copy link
Contributor Author

I'll describe the setup and symptoms in more detail.

The computer I'm using has two users.
System-wide, the shell is the default one (Bash).

My user has set users.myname.shell = pkgs.fish;. When logging in via TTY, $HOME isn't loaded before the other XDG envs. By launching fish inside it, though, this is fixed. Even without that, I can launch Plasma X11/Wayland just fine both via TTY and SDDM.

The other user however uses the default shell. When logging in via TTY, they have no problem. However, launching Plasma Wayland (and not X11) through SDDM, causes it to not load. Looking at journalctl, it's because the XDG envs aren't set up correctly.

@rnhmjoj Do you replicate these behaviors with the settings I just described?

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Apr 6, 2023

No, I can't reproduce your issue. I just tried this:

nix-build -E '(import <nixpkgs/nixos> { configuration = { pkgs, ... }:
    { users.users.vm = {
        password = "vm";
        isNormalUser = true;
        shell = pkgs.fish;
     };
     environment.sessionVariables.XDG_CONFIG_HOME = "$HOME/etc";
    };
  }).vm'

Running the VM and logging in:

image

I also tried without shell = pkgs.fish, so bash, and the variable is also being set correctly.
I'm not sure what could be causing this: I guess some other option/module is interfering or there is some kind of race condition, though the variable is always set reliably for me.

I would try to pinpoint the issue by removing parts of your configuration, or starting with nothing and adding piece by piece.

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Apr 6, 2023

Anyway, I would be in favour of a more user friendly option to set these variables. There are already options like xdg.portal, xdg.mime, etc. so something like xdg.directories would be ideal.

@SuperSamus
Copy link
Contributor Author

So, replacing \${HOME} with $HOME solved all the issues I mentioned above... why? I don't even know if I should complain...
(Anyway, leaving open for the documentation/options factor)

@jtojnar
Copy link
Member

jtojnar commented Apr 7, 2023

Anyway, I would be in favour of a more user friendly option to set these variables. There are already options like xdg.portal, xdg.mime, etc. so something like xdg.directories would be ideal.

Those other options are required to have a XDG compliant system. But you should never need to set those variables unless you want to override the defaults so having the option under xdg namespace feels dirty. At best, you could name it xdg.setBasedirEnvironmentVariablesToDefaultValuesForNoncompliantApps.

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Apr 7, 2023

But you should never need to set those variables unless you want to override the defaults

Yes, that's exactly the reason to have this option. I'm not sure what non-compliant applications have to do with this: they are not going to read the variables anyway.

@jtojnar
Copy link
Member

jtojnar commented Apr 7, 2023

They are non-compliant in that they do not use the implicit default values as described in the basedir spec. Maybe we could call them “partially compliant” but I felt that was long enough and it sounds a bit like “partially pregnant”.

@rnhmjoj
Copy link
Contributor

rnhmjoj commented Apr 7, 2023

They are non-compliant in that they do not use the implicit default values

I've never come across anything like this. Anyway, I think the point of these variables is to customise the default locations of the XDG directories, without setting hunders of application-specific variables. For example, I like them to be visible so I rename them to etc, bin, var.
I don't understand why you're saying this is something "dirty" to have in the xdg namespace.

@l0b0
Copy link
Contributor

l0b0 commented Feb 15, 2024

For the record, these are the defaults mentioned in the XDG Base Directory Specification:

{
  environment.sessionVariables = {
    XDG_CACHE_HOME = "$HOME/.cache";
    XDG_CONFIG_DIRS = "/etc/xdg";
    XDG_CONFIG_HOME = "$HOME/.config";
    XDG_DATA_DIRS = "/usr/local/share/:/usr/share/";
    XDG_DATA_HOME = "$HOME/.local/share";
    XDG_STATE_HOME = "$HOME/.local/state";
  };
}

(Please note XDG_CONFIG_DIRS, XDG_DATA_DIRS, and others are specified by other options; in my case (output pretty-printed with alejandra):

nix repl --file '<nixpkgs/nixos>'
nix-repl> pkgs.lib.attrsets.filterAttrs (name: value: pkgs.lib.strings.hasPrefix "XDG_" name) config.environment.sessionVariables    
{
  XDG_CACHE_HOME = "$HOME/.cache";
  XDG_CONFIG_DIRS = "/etc/xdg";
  XDG_CONFIG_HOME = "$HOME/.config";
  XDG_DATA_DIRS = "/nix/store/vihazwfjqbwl76gzpsj3r9nr5bbsmw4q-gnome-mimeapps/share:/nix/store/nh03g2vz8by412ywv1kbqqlnrzk9h7cm-desktops/share";
  XDG_DATA_HOME = "$HOME/.local/share";
  XDG_DESKTOP_PORTAL_DIR = "/nix/store/bif15j4523chg85ydf99d7mjjmmsk4ss-xdg-portals/share/xdg-desktop-portal/portals";
  XDG_STATE_HOME = "$HOME/.local/state";
}

You might want to omit or lib.mkForce these.)

Please let me know if there are any omissions or errors.

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/why-does-nixos-not-set-xdg-config-home-by-default/45296/6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants