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