This fixes user environment setup for sessions which doesn't successfully go through a shell init. Note we don't go through `sessionVariables` as we want the wrappers to have highest priority. It would also cause wrapperDir to occur twice when in shell sessions, as shells use `sessionVariables` too while prepending wrapperDir in a custom snippet. In particular logging in and out of gnome-shell could result in a broken path without this fix.
		
			
				
	
	
		
			107 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
# This module defines a system-wide environment that will be
 | 
						|
# initialised by pam_env (that is, not only in shells).
 | 
						|
{ config, lib, pkgs, ... }:
 | 
						|
 | 
						|
with lib;
 | 
						|
 | 
						|
let
 | 
						|
 | 
						|
  cfg = config.environment;
 | 
						|
 | 
						|
in
 | 
						|
 | 
						|
{
 | 
						|
 | 
						|
  options = {
 | 
						|
 | 
						|
    environment.sessionVariables = mkOption {
 | 
						|
      default = {};
 | 
						|
      description = ''
 | 
						|
        A set of environment variables used in the global environment.
 | 
						|
        These variables will be set by PAM early in the login process.
 | 
						|
 | 
						|
        The value of each session variable can be either a string or a
 | 
						|
        list of strings. The latter is concatenated, interspersed with
 | 
						|
        colon characters.
 | 
						|
 | 
						|
        Note, due to limitations in the PAM format values may not
 | 
						|
        contain the <literal>"</literal> character.
 | 
						|
 | 
						|
        Also, these variables are merged into
 | 
						|
        <xref linkend="opt-environment.variables"/> and it is
 | 
						|
        therefore not possible to use PAM style variables such as
 | 
						|
        <code>@{HOME}</code>.
 | 
						|
      '';
 | 
						|
      type = with types; attrsOf (either str (listOf str));
 | 
						|
      apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v);
 | 
						|
    };
 | 
						|
 | 
						|
    environment.profileRelativeSessionVariables = mkOption {
 | 
						|
      type = types.attrsOf (types.listOf types.str);
 | 
						|
      example = { PATH = [ "/bin" ]; MANPATH = [ "/man" "/share/man" ]; };
 | 
						|
      description = ''
 | 
						|
        Attribute set of environment variable used in the global
 | 
						|
        environment. These variables will be set by PAM early in the
 | 
						|
        login process.
 | 
						|
 | 
						|
        Variable substitution is available as described in
 | 
						|
        <citerefentry>
 | 
						|
          <refentrytitle>pam_env.conf</refentrytitle>
 | 
						|
          <manvolnum>5</manvolnum>
 | 
						|
        </citerefentry>.
 | 
						|
 | 
						|
        Each attribute maps to a list of relative paths. Each relative
 | 
						|
        path is appended to the each profile of
 | 
						|
        <option>environment.profiles</option> to form the content of
 | 
						|
        the corresponding environment variable.
 | 
						|
 | 
						|
        Also, these variables are merged into
 | 
						|
        <xref linkend="opt-environment.profileRelativeEnvVars"/> and it is
 | 
						|
        therefore not possible to use PAM style variables such as
 | 
						|
        <code>@{HOME}</code>.
 | 
						|
      '';
 | 
						|
    };
 | 
						|
 | 
						|
  };
 | 
						|
 | 
						|
  config = {
 | 
						|
 | 
						|
    system.build.pamEnvironment =
 | 
						|
      let
 | 
						|
        suffixedVariables =
 | 
						|
          flip mapAttrs cfg.profileRelativeSessionVariables (envVar: suffixes:
 | 
						|
            flip concatMap cfg.profiles (profile:
 | 
						|
              map (suffix: "${profile}${suffix}") suffixes
 | 
						|
            )
 | 
						|
          );
 | 
						|
 | 
						|
        # We're trying to use the same syntax for PAM variables and env variables.
 | 
						|
        # That means we need to map the env variables that people might use to their
 | 
						|
        # equivalent PAM variable.
 | 
						|
        replaceEnvVars = replaceStrings ["$HOME" "$USER"] ["@{HOME}" "@{PAM_USER}"];
 | 
						|
 | 
						|
        pamVariable = n: v:
 | 
						|
          ''${n}   DEFAULT="${concatStringsSep ":" (map replaceEnvVars (toList v))}"'';
 | 
						|
 | 
						|
        pamVariables =
 | 
						|
          concatStringsSep "\n"
 | 
						|
          (mapAttrsToList pamVariable
 | 
						|
          (zipAttrsWith (n: concatLists)
 | 
						|
            [
 | 
						|
              # Make sure security wrappers are prioritized without polluting
 | 
						|
              # shell environments with an extra entry. Sessions which depend on
 | 
						|
              # pam for its environment will otherwise have eg. broken sudo. In
 | 
						|
              # particular Gnome Shell sometimes fails to source a proper
 | 
						|
              # environment from a shell.
 | 
						|
              { PATH = [ config.security.wrapperDir ]; }
 | 
						|
 | 
						|
              (mapAttrs (n: toList) cfg.sessionVariables)
 | 
						|
              suffixedVariables
 | 
						|
            ]));
 | 
						|
      in
 | 
						|
        pkgs.writeText "pam-environment" "${pamVariables}\n";
 | 
						|
 | 
						|
  };
 | 
						|
 | 
						|
}
 |