at 16.09-beta 6.0 kB view raw
1# This module defines a global environment configuration and 2# a common configuration for all shells. 3 4{ config, lib, utils, pkgs, ... }: 5 6with lib; 7 8let 9 10 cfg = config.environment; 11 12 exportedEnvVars = 13 let 14 absoluteVariables = 15 mapAttrs (n: toList) cfg.variables; 16 17 suffixedVariables = 18 flip mapAttrs cfg.profileRelativeEnvVars (envVar: listSuffixes: 19 concatMap (profile: map (suffix: "${profile}${suffix}") listSuffixes) cfg.profiles 20 ); 21 22 allVariables = 23 zipAttrsWith (n: concatLists) [ absoluteVariables suffixedVariables ]; 24 25 exportVariables = 26 mapAttrsToList (n: v: ''export ${n}="${concatStringsSep ":" v}"'') allVariables; 27 in 28 concatStringsSep "\n" exportVariables; 29in 30 31{ 32 33 options = { 34 35 environment.variables = mkOption { 36 default = {}; 37 description = '' 38 A set of environment variables used in the global environment. 39 These variables will be set on shell initialisation. 40 The value of each variable can be either a string or a list of 41 strings. The latter is concatenated, interspersed with colon 42 characters. 43 ''; 44 type = types.attrsOf (types.loeOf types.str); 45 apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v); 46 }; 47 48 environment.profiles = mkOption { 49 default = []; 50 description = '' 51 A list of profiles used to setup the global environment. 52 ''; 53 type = types.listOf types.str; 54 }; 55 56 environment.profileRelativeEnvVars = mkOption { 57 type = types.attrsOf (types.listOf types.str); 58 example = { PATH = [ "/bin" "/sbin" ]; MANPATH = [ "/man" "/share/man" ]; }; 59 description = '' 60 Attribute set of environment variable. Each attribute maps to a list 61 of relative paths. Each relative path is appended to the each profile 62 of <option>environment.profiles</option> to form the content of the 63 corresponding environment variable. 64 ''; 65 }; 66 67 # !!! isn't there a better way? 68 environment.extraInit = mkOption { 69 default = ""; 70 description = '' 71 Shell script code called during global environment initialisation 72 after all variables and profileVariables have been set. 73 This code is asumed to be shell-independent, which means you should 74 stick to pure sh without sh word split. 75 ''; 76 type = types.lines; 77 }; 78 79 environment.shellInit = mkOption { 80 default = ""; 81 description = '' 82 Shell script code called during shell initialisation. 83 This code is asumed to be shell-independent, which means you should 84 stick to pure sh without sh word split. 85 ''; 86 type = types.lines; 87 }; 88 89 environment.loginShellInit = mkOption { 90 default = ""; 91 description = '' 92 Shell script code called during login shell initialisation. 93 This code is asumed to be shell-independent, which means you should 94 stick to pure sh without sh word split. 95 ''; 96 type = types.lines; 97 }; 98 99 environment.interactiveShellInit = mkOption { 100 default = ""; 101 description = '' 102 Shell script code called during interactive shell initialisation. 103 This code is asumed to be shell-independent, which means you should 104 stick to pure sh without sh word split. 105 ''; 106 type = types.lines; 107 }; 108 109 environment.shellAliases = mkOption { 110 default = {}; 111 example = { ll = "ls -l"; }; 112 description = '' 113 An attribute set that maps aliases (the top level attribute names in 114 this option) to command strings or directly to build outputs. The 115 aliases are added to all users' shells. 116 ''; 117 type = types.attrs; # types.attrsOf types.stringOrPath; 118 }; 119 120 environment.binsh = mkOption { 121 default = "${config.system.build.binsh}/bin/sh"; 122 defaultText = "\${config.system.build.binsh}/bin/sh"; 123 example = literalExample '' 124 "''${pkgs.dash}/bin/dash" 125 ''; 126 type = types.path; 127 visible = false; 128 description = '' 129 The shell executable that is linked system-wide to 130 <literal>/bin/sh</literal>. Please note that NixOS assumes all 131 over the place that shell to be Bash, so override the default 132 setting only if you know exactly what you're doing. 133 ''; 134 }; 135 136 environment.shells = mkOption { 137 default = []; 138 example = literalExample "[ pkgs.bashInteractive pkgs.zsh ]"; 139 description = '' 140 A list of permissible login shells for user accounts. 141 No need to mention <literal>/bin/sh</literal> 142 here, it is placed into this list implicitly. 143 ''; 144 type = types.listOf (types.either types.shellPackage types.path); 145 }; 146 147 }; 148 149 config = { 150 151 system.build.binsh = pkgs.bashInteractive; 152 153 # Set session variables in the shell as well. This is usually 154 # unnecessary, but it allows changes to session variables to take 155 # effect without restarting the session (e.g. by opening a new 156 # terminal instead of logging out of X11). 157 environment.variables = config.environment.sessionVariables; 158 159 environment.etc."shells".text = 160 '' 161 ${concatStringsSep "\n" (map utils.toShellPath cfg.shells)} 162 /bin/sh 163 ''; 164 165 system.build.setEnvironment = pkgs.writeText "set-environment" 166 '' 167 ${exportedEnvVars} 168 169 ${cfg.extraInit} 170 171 # The setuid wrappers override other bin directories. 172 export PATH="${config.security.wrapperDir}:$PATH" 173 174 # ~/bin if it exists overrides other bin directories. 175 export PATH="$HOME/bin:$PATH" 176 ''; 177 178 system.activationScripts.binsh = stringAfter [ "stdio" ] 179 '' 180 # Create the required /bin/sh symlink; otherwise lots of things 181 # (notably the system() function) won't work. 182 mkdir -m 0755 -p /bin 183 ln -sfn "${cfg.binsh}" /bin/.sh.tmp 184 mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh 185 ''; 186 187 }; 188 189}