vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / config / shells-environment.nix
blob9289eced109f38dc33881e1ed35158e02bc767b2
1 # This module defines a global environment configuration and
2 # a common configuration for all shells.
3 { config, lib, utils, pkgs, ... }:
4 let
6   cfg = config.environment;
8   exportedEnvVars =
9     let
10       absoluteVariables =
11         lib.mapAttrs (n: lib.toList) cfg.variables;
13       suffixedVariables =
14         lib.flip lib.mapAttrs cfg.profileRelativeEnvVars (envVar: listSuffixes:
15           lib.concatMap (profile: map (suffix: "${profile}${suffix}") listSuffixes) cfg.profiles
16         );
18       allVariables =
19         lib.zipAttrsWith (n: lib.concatLists) [ absoluteVariables suffixedVariables ];
21       exportVariables =
22         lib.mapAttrsToList (n: v: ''export ${n}="${lib.concatStringsSep ":" v}"'') allVariables;
23     in
24       lib.concatStringsSep "\n" exportVariables;
29   options = {
31     environment.variables = lib.mkOption {
32       default = {};
33       example = { EDITOR = "nvim"; VISUAL = "nvim"; };
34       description = ''
35         A set of environment variables used in the global environment.
36         These variables will be set on shell initialisation (e.g. in /etc/profile).
37         The value of each variable can be either a string or a list of
38         strings.  The latter is concatenated, interspersed with colon
39         characters.
40       '';
41       type = with lib.types; attrsOf (oneOf [ (listOf (oneOf [ int str path ])) int str path ]);
42       apply = let
43         toStr = v: if lib.isPath v then "${v}" else toString v;
44       in lib.mapAttrs (n: v: if lib.isList v then lib.concatMapStringsSep ":" toStr v else toStr v);
45     };
47     environment.profiles = lib.mkOption {
48       default = [];
49       description = ''
50         A list of profiles used to setup the global environment.
51       '';
52       type = lib.types.listOf lib.types.str;
53     };
55     environment.profileRelativeEnvVars = lib.mkOption {
56       type = lib.types.attrsOf (lib.types.listOf lib.types.str);
57       example = { PATH = [ "/bin" ]; MANPATH = [ "/man" "/share/man" ]; };
58       description = ''
59         Attribute set of environment variable.  Each attribute maps to a list
60         of relative paths.  Each relative path is appended to the each profile
61         of {option}`environment.profiles` to form the content of the
62         corresponding environment variable.
63       '';
64     };
66     # !!! isn't there a better way?
67     environment.extraInit = lib.mkOption {
68       default = "";
69       description = ''
70         Shell script code called during global environment initialisation
71         after all variables and profileVariables have been set.
72         This code is assumed to be shell-independent, which means you should
73         stick to pure sh without sh word split.
74       '';
75       type = lib.types.lines;
76     };
78     environment.shellInit = lib.mkOption {
79       default = "";
80       description = ''
81         Shell script code called during shell initialisation.
82         This code is assumed to be shell-independent, which means you should
83         stick to pure sh without sh word split.
84       '';
85       type = lib.types.lines;
86     };
88     environment.loginShellInit = lib.mkOption {
89       default = "";
90       description = ''
91         Shell script code called during login shell initialisation.
92         This code is assumed to be shell-independent, which means you should
93         stick to pure sh without sh word split.
94       '';
95       type = lib.types.lines;
96     };
98     environment.interactiveShellInit = lib.mkOption {
99       default = "";
100       description = ''
101         Shell script code called during interactive shell initialisation.
102         This code is assumed to be shell-independent, which means you should
103         stick to pure sh without sh word split.
104       '';
105       type = lib.types.lines;
106     };
108     environment.shellAliases = lib.mkOption {
109       example = { l = null; ll = "ls -l"; };
110       description = ''
111         An attribute set that maps aliases (the top level attribute names in
112         this option) to command strings or directly to build outputs. The
113         aliases are added to all users' shells.
114         Aliases mapped to `null` are ignored.
115       '';
116       type = with lib.types; attrsOf (nullOr (either str path));
117     };
119     environment.homeBinInPath = lib.mkOption {
120       description = ''
121         Include ~/bin/ in $PATH.
122       '';
123       default = false;
124       type = lib.types.bool;
125     };
127     environment.localBinInPath = lib.mkOption {
128       description = ''
129         Add ~/.local/bin/ to $PATH
130       '';
131       default = false;
132       type = lib.types.bool;
133     };
135     environment.binsh = lib.mkOption {
136       default = "${config.system.build.binsh}/bin/sh";
137       defaultText = lib.literalExpression ''"''${config.system.build.binsh}/bin/sh"'';
138       example = lib.literalExpression ''"''${pkgs.dash}/bin/dash"'';
139       type = lib.types.path;
140       visible = false;
141       description = ''
142         The shell executable that is linked system-wide to
143         `/bin/sh`. Please note that NixOS assumes all
144         over the place that shell to be Bash, so override the default
145         setting only if you know exactly what you're doing.
146       '';
147     };
149     environment.shells = lib.mkOption {
150       default = [];
151       example = lib.literalExpression "[ pkgs.bashInteractive pkgs.zsh ]";
152       description = ''
153         A list of permissible login shells for user accounts.
154         No need to mention `/bin/sh`
155         here, it is placed into this list implicitly.
156       '';
157       type = lib.types.listOf (lib.types.either lib.types.shellPackage lib.types.path);
158     };
160   };
162   config = {
164     system.build.binsh = pkgs.bashInteractive;
166     # Set session variables in the shell as well. This is usually
167     # unnecessary, but it allows changes to session variables to take
168     # effect without restarting the session (e.g. by opening a new
169     # terminal instead of logging out of X11).
170     environment.variables = config.environment.sessionVariables;
172     environment.profileRelativeEnvVars = config.environment.profileRelativeSessionVariables;
174     environment.shellAliases = lib.mapAttrs (name: lib.mkDefault) {
175       ls = "ls --color=tty";
176       ll = "ls -l";
177       l  = "ls -alh";
178     };
180     environment.etc.shells.text =
181       ''
182         ${lib.concatStringsSep "\n" (map utils.toShellPath cfg.shells)}
183         /bin/sh
184       '';
186     # For resetting environment with `. /etc/set-environment` when needed
187     # and discoverability (see motivation of #30418).
188     environment.etc.set-environment.source = config.system.build.setEnvironment;
190     system.build.setEnvironment = pkgs.writeText "set-environment"
191       ''
192         # DO NOT EDIT -- this file has been generated automatically.
194         # Prevent this file from being sourced by child shells.
195         export __NIXOS_SET_ENVIRONMENT_DONE=1
197         ${exportedEnvVars}
199         ${cfg.extraInit}
201         ${lib.optionalString cfg.homeBinInPath ''
202           # ~/bin if it exists overrides other bin directories.
203           export PATH="$HOME/bin:$PATH"
204         ''}
206         ${lib.optionalString cfg.localBinInPath ''
207           export PATH="$HOME/.local/bin:$PATH"
208         ''}
209       '';
211     system.activationScripts.binsh = lib.stringAfter [ "stdio" ]
212       ''
213         # Create the required /bin/sh symlink; otherwise lots of things
214         # (notably the system() function) won't work.
215         mkdir -p /bin
216         chmod 0755 /bin
217         ln -sfn "${cfg.binsh}" /bin/.sh.tmp
218         mv /bin/.sh.tmp /bin/sh # atomically replace /bin/sh
219       '';
221   };