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

Switch to environment.d for setting envvars #32

Closed
ayekat opened this issue Nov 5, 2020 · 10 comments
Closed

Switch to environment.d for setting envvars #32

ayekat opened this issue Nov 5, 2020 · 10 comments

Comments

@ayekat
Copy link
Owner

ayekat commented Nov 5, 2020

With PAM developers having switched to setting user_readenv to 0 by default recently, and now with them voicing their intent to remove ~/.pam_environment entirely, it's a good moment to seriously start thinking about moving variable declaration to environment.d.

The downsides are:

  • environment.d reads from $XDG_CONFIG_HOME/environment.d, so there is a bit of a bootstrapping issue here: with pam_env disappearing, one can no longer define $XDG_CONFIG_HOME before environment.d runs (so it will either default to the specification-defined default (~/.config), or whatever the local sysadmin decides to set system-wide). We'll need a not-too-painful way of adapting to the individual cases; probably by symlinking ~/system-specific-xdg_config_home/environment.d to ~/.local/etc/environment.d as part of the initial dotfiles setup.
  • environment.d only applies to the systemd user daemon, but not the user session. So we will need a way to import variables into the login session as well. Either by evaling the output of systemctl show-environment, or by reading the environment.d files directly (given that the show-environment output isn't POSIX conform, so we can't put that in etc/sh/profile.d).

It's less than ideal, but as far as I can see, it's the only thing that is currently left for setting environment variables.

@roosemberth
Copy link

roosemberth commented Nov 5, 2020

How about writing a PAM module to be added to the required services session management?

It could be argued that session brokering is a service of the system administrator and up to them to allow users to configure the session.

The original argument about security stands, I don't think it should reimplement pam_userenv, but merely provide a way of setting fixed envvars (iirc you could have ACE using .pam_environment).

@t8m
Copy link

t8m commented Nov 5, 2020

It could be a module to set just the XDG_CONFIG_HOME environment variable. That would be probably somewhat acceptable. Not sure if that module has to be part of the Linux PAM.

@roosemberth
Copy link

Or a list of envvars defined by the sysadmin e.g. XDG_CONFIG_HOME, XDG_DATA_DIRS, XDG_DATA_HOME, ...

@ayekat
Copy link
Owner Author

ayekat commented Nov 5, 2020

Hi!

Thank you very much for commenting!

How about writing a PAM module to be added to the required services session management?

Writing a new PAM module would only work for systems where I have administrative rights. I cannot expect every other system administrator to include and enable some fiddled PAM module by a random opinionated user on the Web 😅

With my dotfiles, I generally avoid any approach that requires system-wide modifications, as I would need to rely on the local system administrator to have taken specific steps beyond what is already provided by default. Admittedly, I haven't applied this consistently (RedHat-based systems have already disabled user_readenv before upstream PAM, and zsh isn't really guaranteed to be present at all), but if I make any major shift here, I try to move towards more compatibility.

It could be argued that session brokering is a service of the system administrator and up to them to allow users to configure the session.

I agree with that, but unfortunately, the way the XDG basedir spec is defined (grumble, grumble) this has implications on where application files end up within a user's home directory. And my stance there is that users should generally be allowed to decide for themselves how they want to organise their personal files.

It could be a module to set just the XDG_CONFIG_HOME environment variable. That would be probably somewhat acceptable. Not sure if that module has to be part of the Linux PAM.

That would be a compromise that would solve this particular problem.

But I also agree with your comment in the referenced PAM issue that it isn't really PAM's job to set user environment variables. It just happened to be a feature I was glad existed and I could use, but I do see the security implications of misconfigured PAM setups as well (and I think even only XDG_CONFIG_HOME could have undesired consequences for any subsequently loaded PAM modules).

I'm painfully reminded of https://xkcd.com/1172/ right now.

Or a list of envvars defined by the sysadmin e.g. XDG_CONFIG_HOME, XDG_DATA_DIRS, XDG_DATA_HOME, ...

Unless the upstream defaults include at least XDG_CONFIG_HOME, I would again run into the issue of having to rely on the local system administrator.


Overall, I was rather planning to see if I could make environment.d additionally also consider a file/directory like ~/.environment{,.d}, and try to open a pull request at systemd for this. And yes, I do see the irony of trying to make the XDG basedir spec working by having something ignore it 🙂

@roosemberth
Copy link

It could be argued that session brokering is a service of the system
administrator and up to them to allow users to configure the session.

I agree with that, but unfortunately, the way the XDG basedir spec is defined
(grumble, grumble) this has implications on where application files end up
within a user's home directory. And my stance there is that users should
generally be allowed to decide for themselves how they want to organise their
personal files.

I think we're ignoring the fact that user sessions don't necessarily need to be
interactive or even lead to a shell. For instance chfn is a service opening a
PAM session to change the user information, and so are polkit and most display
managers.

These applications start under a user session long before the user for whom
they were invoked becomes aware, I think this a feature of PAM.

A solution using the existing PAM stack would require configuration by the
system administrator, it's just that most of the stuff we use were put
there by the distribution maintainers on their behalf.

I don't think that solution belongs in systemd, but in consolekit / logind,
however systemd is already trespassing to workaround chicken and egg. Part of
the reason for this is that systemd is slowly becoming PAM (thorugh polkit), but
with less power than the allmighty PAM (which is good).

How about exploring other systemd subsystems to piggy back on?

@ayekat
Copy link
Owner Author

ayekat commented Nov 6, 2020

I don't think that solution belongs in systemd, but in consolekit / logind […]

But isn't logind only for login sessions? Please correct me if I'm wrong, I'm basing my assumption only on what I've read in the systemd-logind manpage.

The goal is to have my environment variables be respected by as many processes as possible, not just interactive sessions (otherwise I could just stick to ~/.profile) :-)

But I fully agree with you on this:

A solution using the existing PAM stack would require configuration by the
system administrator, it's just that most of the stuff we use were put
there by the distribution maintainers on their behalf.

So far I have indeed overlooked that for most (relevant) PAM applications, I have been lucky that pam_env.so user_readenv=1 was already set (either by upstream or by the distro maintainers), but there may just as well be applications where that is not the case, and I'm at the whims of the local sysadmin or distribution maintainer already anyway.

How about exploring other systemd subsystems to piggy back on?

To be honest, I am now genuinely lost as to what component should ideally handle this. The way I see it, anything that launches a process under my user would have to respect that, and that doesn't sound particularly realistic.

So I assume I will have to strive for a "good enough" solution, and based on my current knowledge, I am still under the impression that (both by its name and its functionality) environment.d does this job just fine.

--edit: But I'm open for suggestions, if you see any specific components that are better suited for this.

@ayekat
Copy link
Owner Author

ayekat commented Apr 16, 2021

Moved (large parts of) ~/.pam_environment to an environment.d config snippet in 81bc3dd.

I ran into a second boostrapping issue: XDG_CONFIG_HOME only works for systemd-environment-d-generator; ZSH on the other hand completely ignores the XDG basedir spec, so we need to set ZDOTDIR instead.

The result is that we now set XDG_CONFIG_HOME and ZDOTDIR in ~/.pam_environment. On systems where that no longer works, we'll have to create symlinks in the home directory. That is extremely ugly, but it'll do for now.

@ayekat ayekat closed this as completed Apr 16, 2021
@ayekat ayekat added the Fixed label Apr 16, 2021
@adrelanos
Copy link

I don't know much about this repository but I've been looking for a drop-in folder /etc/environment.d that works similar to /etc/environment as one would intuitively expect on and off for probably 10 years already. During my recent attempt (where I will keep updating my notes), I might have finally found it. At least for systemd enabled system which you are apparently also using.

How about...

/usr/lib/systemd/system.conf.d/30_name.conf

[Manager]
DefaultEnvironment=TESTONE=A
DefaultEnvironment=TESTTWO=B

Does it work for you? Works great for me in all places that I tested so far (terminal emulator, virtual console).

@ayekat
Copy link
Owner Author

ayekat commented Sep 28, 2022

Hi @adrelanos, thanks for your input and interest in this!

But do I understand you correctly that you want to set environment variables that apply to the entire system?

My goal is to have a user-controlled knob for setting environment variables. Configuration files outside of my $HOME (like /etc/environment, /etc/environment.d or any system-wide systemd configuration) are not an option.


If you don't mind some feedback on your approach, though: Files in /usr are usually not meant to be modified or created by a local system admin. But fortunately, systemd allows configuring its components via corresponding files in /etc. I haven't tested your (or this) method, but I feel like /etc/systemd/system.conf.d/30_name.conf might be a better/cleaner place.

--edit: Ah, but I see that further down in that linked discussion, you're describing how that file would be installed by an OS package, in which case /usr/lib/systemd/system.conf.d would be fine. I apologise, a minor slightly-sleep-deprived-brain hiccup of mine.

@adrelanos
Copy link

But do I understand you correctly that you want to set environment variables that apply to the entire system?

In some cases, yes.

But indeed. Your feature request,

makes a lot sense. Having some environment applied only to PAM sessions and not each and every (systemd) daemon would be cleaner.

In the specific use case why this came up again we were looking for a solution was how to set ZDOTDIR for a virtual console. The same question as someone else asked on reddit.

My goal is to have a user-controlled knob for setting environment variables. Configuration files outside of my $HOME (like /etc/environment, /etc/environment.d or any system-wide systemd configuration) are not an option.

I can see the issue. Having ZDOTDIR set for daemons (lets say nginx) seems imperfect.

Where do you need it? Xorg? Wayland? Virtual console? I suppose so. In that case, would a systemd drop-in for getty with Environment= or EnvironmentFile=? That should cover virtual consoles. But also not a very clean solution. It wouldn't automatically apply everywhere where PAM is involved.

--edit: Ah, but I see that further down in that linked discussion, you're describing how that file would be installed by an OS package, in which case /usr/lib/systemd/system.conf.d would be fine.

Indeed.

Thank you for your reply!

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

4 participants