79

The XDG specification talks about the XDG_CONFIG_HOME variable, but does not specify where it should be defined. Should we define it in /etc/X11/Xsession, or is it the window manager's config file that needs to define this?

I tried declaring it in /etc/environment as

XDG_CONFIG_HOME="$HOME/.config"

but that didn't work, as it seems that $HOME is not defined when /etc/environment is parsed.

The only documentation I could find online was for Gentoo, where it was declared in /etc/env.d/90xsession

I'm using Ubuntu. What would be the general solution for Debian based distros?

NOLFXceptMe
  • 1,082
  • 2
  • 9
  • 12

6 Answers6

102

You don't need to define it anywhere, unless you want to change the default.

XDG Base Directory Specification clearly says:

If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used.

So it is redundant to define it to the default value. All compliant applications will already use $HOME/.config

But, if you do want to change the default in a Debian/Ubuntu system, the best place is:

  • For a system-wide change, affecting all users: /etc/profile
  • For your user only: ~/.profile
MestreLion
  • 2,467
  • 4
  • 27
  • 21
  • 6
    This answer is perfectly fine, theoretically, but there is plenty software around, which is not XDG Base Directory Specification compliant and a quattuordecillion of bugs stemming from this ignorance. – ManuelSchneid3r Jul 30 '15 at 11:44
  • 7
    @ManuelSchneid3r Very true, but for such software setting `XDG_CONFIG_HOME` will make little difference anyway, if any. – MestreLion Aug 02 '15 at 09:19
  • 7
    There may be software that blindly uses `XDG_CONFIG_HOME` without following the spec, assuming that it's a standard Linux or even Unix feature rather than part of a third-party specification. – Eagle-Eye Dec 03 '16 at 21:54
  • @Eagle-Eye are you saying that we *do* have to define `XDG_CONFIG_HOME` etc therefore? – mcnesium Dec 06 '16 at 10:10
  • 3
    @mcnesium I'm saying it probably can't hurt. Though if possible, it would be better to fix the application itself and send the fix upstream. – Eagle-Eye Dec 06 '16 at 19:03
  • 3
    FWIW, byobu uses `XDG_CONFIG_HOME` but does not fallback to `$HOME/.config`. Think of programs that adopt `XDG_CONFIG_HOME` but want to stay backward-compatible. – Torsten Bronger May 29 '20 at 06:57
  • 2
    @TorstenBronger: "backward-compatible" with _what_? There was no standard before XDG for home directories, `~/.appname` is just a (poor) convention. If byobu is falling back to `~/.appname` when `XDG_CONFIG_HOME` is not set, then it's **terribly** _misusing_ the XDG standard and its variables, and should be fixed. – MestreLion Jun 06 '20 at 17:24
  • 1
    @TorstenBronger: If a software wants to cater to both the XDG standard and the old convention, it could use a solution I created for legacy software: **if** there's already an `~/.appname` dir, then use it; otherwise use `$XDG_CONFIG_HOME` (falling back to `$HOME/.config`, obviously). It's the sanest solution IMHO. In Bash it's a one-liner: `DATADIR=$HOME/.$APPNAME; if ! [[ -d "$DATADIR" ]]; then DATADIR=${XDG_CONFIG_HOME:-$HOME/.config}/$APPNAME; fi` – MestreLion Jun 06 '20 at 17:32
  • 1
    I think this is in the eye of the beholder. I find byobu’s behaviour easy to understand. And this standard is for users rather than for developers after all. – Torsten Bronger Jun 07 '20 at 10:08
  • 1
    It is for users indeed, and it's not easy to understand why byobu requires users the effort of setting an env var when other apps do it automatically. There are much better ways to handle backward-compatibility. – MestreLion Mar 18 '21 at 16:49
  • 1
    @TorstenBronger “this standard is for users rather than for developers after all” — Right, so why are you defending a buggy program that makes correct configuration harder for users? (That said, this bug appears to be fixed, though [rather badly](https://github.com/dustinkirkland/byobu/blob/bfb7a763d0ea458b310962a4fd7538420f613b6b/usr/lib/byobu/include/dirs.in#L33-L38).) – Konrad Rudolph Nov 03 '21 at 13:30
  • @KonradRudolph, Eww, badly indeed!!! More than 10 lines of nonsensical `if`s, misusing the spec, when this could've been so simple. Yeah, if you code it like this, XDG seems awkward and complex. – MestreLion Nov 04 '21 at 05:25
45

In Arch Linux, this is defined by /etc/profile, using a /etc/profile.d script.

For Debian/Ubuntu, if there's a /etc/profile.d – create a similar script inside; if such a directory does not exist – edit /etc/profile itsef.

export XDG_CONFIG_HOME="$HOME/.config"

The /etc/environment file is parsed by pam_env, which treats it as simple name=value assignments. However, it also has /etc/security/pam_env.conf, which supports variable expansion and can be used for this purpose.

Eagle-Eye
  • 204
  • 1
  • 9
u1686_grawity
  • 426,297
  • 64
  • 894
  • 966
11

Elaborating on the points in the other answers regarding setting variables to the fallback values:

If one is fine with the fallback values stated in the specification, setting environment variables to duplicate the fallbacks (ie: setting $XDG_CONFIG_HOME=$HOME/.config) is not pointless or dumb. Not every program will follow the spec correctly, and having the variable set can make copying and pasting much easier.

For example, NVIDIA uses XDG_CACHE_HOME if set, otherwise improperly falls back to ~/.nv instead of ~/.cache. And you can easily wait years for something like that to be fixed.

Also, this page is a great spot to grab a bunch of environment variables to force certain programs to use your defined directories. Copying and pasting 20 of those and then setting tweaking the path is more work than having to set the XDG variables.

And to add something specific to the original question: this page has information about where to define variables.

Glorfindel
  • 4,089
  • 8
  • 24
  • 37
MuddyArch
  • 111
  • 1
  • 2
  • 1
    seems like a fine partial answer to me. I usually lead with "partial:answer:to add to what has already been said in other answers" – ctrl-alt-delor Jan 29 '21 at 17:08
10

I've found that it works best to set environment variables via PAM. For modern Linux distos, this means /etc/environment or $HOME/.pam_environment (see man pam_env). You can also set them in /etc/security/pam_env.conf using a special syntax. Here is how I set my XDG variables in /etc/security/pam_env.conf.

XDG_CACHE_HOME  DEFAULT=@{HOME}/.xdg/cache
XDG_CONFIG_HOME DEFAULT=@{HOME}/.xdg/config
XDG_DATA_HOME   DEFAULT=@{HOME}/.xdg/data
XDG_STATE_HOME  DEFAULT=@{HOME}/.xdg/state

Previously I would set these variables in /etc/profile.d/custom.sh. However, some applications start before that file is read. Switching to the PAM method solved the issue for multiple applications that behaved this way.

carlwgeorge
  • 339
  • 2
  • 9
  • 8
    Note: this does not follow the defaults in specified in the [XDG Base Directory Specification](https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html) – Tom Hale Sep 26 '16 at 15:18
  • 6
    @TomHale Of course not, the whole point of setting the variables is to override the defaults. If you are happy with the defaults, then you don't need to set these variables at all. – carlwgeorge Sep 28 '16 at 00:22
  • 1
    Ubuntu 14.04 doesn't set the XDG directory variables by default - just because there is a specification doesn't mean that one's distro follows it. – Tom Hale Sep 28 '16 at 02:37
  • 1
    @TomHale That doesn't matter because the XDG specification provides defaults for when the variables are not set, therefore it is *not* necessary to set the XDG variables. – Pauan Nov 14 '16 at 12:42
  • 4
    It does matter if I want to `export LESSHISTFILE="$XDG_CACHE_HOME"/less/history` where `less` is not cognisant of the spec and the defaults are not yet set by my distro. – Tom Hale Nov 14 '16 at 12:52
  • 6
    @TomHale the spec doesn't define what the _operating system_ should set the variables to; it defines variables, that, if defined and non-empty, the _application_ should use. And if the variable isn't defined or is empty, the _application_ should use the default path referenced in the spec. So your short example isn't spec-compliant, since it doesn't first check that `XDG_CACHE_HOME` is defined and non-empty. It should instead be: `export LESSHISTFILE="${XDG_CACHE_HOME:-$HOME/.cache}"/less/history` – villapx Dec 04 '18 at 22:33
  • For me, on RedHat the use of `@{HOME}` yielded an empty string so that the path was `/.local` etc. ${HOME} didn't work either, but was interpreted literally. So am a bit confused about this. – Jacob Lee Jul 02 '21 at 00:11
  • 1
    Arch wiki [claims](https://wiki.archlinux.org/title/Environment_variables#Per_user) reading user `~/.pam_environment` is [deprecated](https://github.com/linux-pam/linux-pam/commit/ecd526743a27157c5210b0ce9867c43a2fa27784) and maybe removed at some point. – Real Nov 30 '21 at 17:10
2

For Zsh users, define it in your .zshenv ~/.zprofile file

export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
smac89
  • 338
  • 4
  • 11
0

For Zsh, I prefer to use global zshenv directly. By specifying this default value to it - $HOME/.config, which it should know .... - using the bash substitution parameter ":="

cat >> /etc/zsh/zshenv <<- "gnark"
export ZDOTDIR="${XDG_CONFIG_HOME:=$HOME/.config}/zsh"
gnark