diff --git a/README.md b/README.md
index f83af3366..7c7d4b123 100644
--- a/README.md
+++ b/README.md
@@ -89,6 +89,24 @@ Currently the easiest way to install Home Manager is as follows:
Home Manager should now be active and available in your user
environment.
+5. If you do not plan on having Home Manager manage your shell
+ configuration then you must source the
+
+ ```
+ "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
+ ```
+
+ file in your shell configuration. Unfortunately, we currently only
+ support POSIX.2-like shells such as [Bash][] or [Z shell][].
+
+ For example, if you use Bash then add
+
+ ```bash
+ . "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
+ ```
+
+ to your `~/.profile` file.
+
Note, because the `HM_PATH` variable above points to the live Home
Manager repository you will automatically get updates whenever you
build a new generation. If you dislike automatic updates then perform
@@ -240,8 +258,10 @@ in your system configuration and
in your Home Manager configuration.
+[Bash]: https://www.gnu.org/software/bash/
[Nix]: https://nixos.org/nix/
[NixOS]: https://nixos.org/
[Nixpkgs]: https://nixos.org/nixpkgs/
[nixAllowedUsers]: https://nixos.org/nix/manual/#conf-allowed-users
[nixosAllowedUsers]: https://nixos.org/nixos/manual/options.html#opt-nix.allowedUsers
+[Z shell]: http://zsh.sourceforge.net/
diff --git a/modules/home-environment.nix b/modules/home-environment.nix
index f29364159..197e9dc57 100644
--- a/modules/home-environment.nix
+++ b/modules/home-environment.nix
@@ -127,12 +127,40 @@ in
example = { EDITOR = "emacs"; GS_OPTIONS = "-sPAPERSIZE=a4"; };
description = ''
Environment variables to always set at login.
+
+ The values may refer to other environment variables using
+ POSIX.2 style variable references. For example, a variable
+ parameter may be referenced as
+ $parameter
or ''${parameter}
. A
+ default value foo may be given as per
+ ''${parameter:-foo}
and, similarly, an alternate
+ value bar can be given as per
+ ''${parameter:+bar}
.
+
+ Note, these variables may be set in any order so no session
+ variable may have a runtime dependency on another session
+ variable. In particular code like
+
+ home.sessionVariables = {
+ FOO = "Hello";
+ BAR = "$FOO World!";
+ };
+
+ may not work as expected. If you need to reference another
+ session variable, then do so inside Nix instead. The above
+ example then becomes
+
+ home.sessionVariables = {
+ FOO = "Hello";
+ BAR = "''${config.home.sessionVariables.FOO} World!";
+ };
+
'';
};
home.sessionVariableSetter = mkOption {
- default = "bash";
- type = types.enum [ "pam" "bash" "zsh" ];
+ default = null;
+ type = types.nullOr (types.enum [ "pam" "bash" "zsh" ]);
example = "pam";
description = ''
Identifies the module that should set the session variables.
@@ -143,6 +171,9 @@ in
If "pam" is set then PAM must be used to set the system
environment. Also mind that typical environment variables
might not be set by the time PAM starts up.
+
+ This option is DEPRECATED, the shell modules are now
+ automatically setting the session variables when enabled.
'';
};
@@ -239,6 +270,23 @@ in
//
(maybeSet "LC_TIME" cfg.language.time);
+ home.packages = [
+ # Provide a file holding all session variables.
+ (
+ pkgs.writeTextFile {
+ name = "hm-session-vars.sh";
+ destination = "/etc/profile.d/hm-session-vars.sh";
+ text = ''
+ # Only source this once.
+ if [ -n "$__HM_SESS_VARS_SOURCED" ]; then return; fi
+ export __HM_SESS_VARS_SOURCED=1
+
+ ${config.lib.shell.exportAll cfg.sessionVariables}
+ '';
+ }
+ )
+ ];
+
# A dummy entry acting as a boundary between the activation
# script's "check" and the "write" phases.
home.activation.writeBoundary = dag.entryAnywhere "";
diff --git a/modules/lib/default.nix b/modules/lib/default.nix
index 5c273f15d..8291be0b2 100644
--- a/modules/lib/default.nix
+++ b/modules/lib/default.nix
@@ -15,4 +15,6 @@
entryAfter = d.dagEntryAfter;
entryBefore = d.dagEntryBefore;
};
+
+ shell = import ./shell.nix { inherit lib; };
}
diff --git a/modules/lib/shell.nix b/modules/lib/shell.nix
new file mode 100644
index 000000000..f1443c546
--- /dev/null
+++ b/modules/lib/shell.nix
@@ -0,0 +1,11 @@
+{ lib }:
+
+rec {
+ # Produces a Bourne shell like variable export statement.
+ export = n: v: "export ${n}=\"${toString v}\"";
+
+ # Given an attribute set containing shell variable names and their
+ # assignment, this function produces a string containing an export
+ # statement for each set entry.
+ exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars);
+}
diff --git a/modules/misc/news.nix b/modules/misc/news.nix
index 8ca9b7aae..5c11803ed 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -478,6 +478,60 @@ in
necessary.
'';
}
+
+ {
+ time = "2018-01-08T20:39:56+00:00";
+ condition = config.home.sessionVariableSetter != null;
+ message =
+ let
+ opts = {
+ bash = ''
+ Instead the 'programs.bash' module will, when enabled,
+ automatically set session variables. You can safely
+ remove the 'home.sessionVariableSetter' option from your
+ configuration.
+ '';
+
+ zsh = ''
+ Instead the 'programs.zsh' module will, when enabled,
+ automatically set session variables. You can safely
+ remove the 'home.sessionVariableSetter' option from your
+ configuration.
+ '';
+
+ pam = ''
+ Unfortunately setting general session variables using
+ PAM will not be directly supported after this date. The
+ primary reason for this change is its limited support
+ for variable expansion.
+
+ To continue setting session variables from the Home
+ Manager configuration you must either use the
+ 'programs.bash' or 'programs.zsh' modules or manually
+ source the session variable file
+
+ $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
+
+ within your shell configuration, see the README file for
+ more information. This file requires a Bourne-like shell
+ such as Bash or Z shell but hopefully other shells
+ will be supported in the future.
+
+ If you specifically need to set a session variable using
+ PAM then the new option 'pam.sessionVariables' can be
+ used. It works much the same as 'home.sessionVariables'
+ but its attribute values must be valid within the PAM
+ environment file.
+ '';
+ };
+ in
+ ''
+ The 'home.sessionVariableSetter' option is now deprecated
+ and will be removed on February 8, 2018.
+
+ ${opts.${config.home.sessionVariableSetter}}
+ '';
+ }
];
};
}
diff --git a/modules/misc/pam.nix b/modules/misc/pam.nix
index 3bd0f2925..dfeaf2f33 100644
--- a/modules/misc/pam.nix
+++ b/modules/misc/pam.nix
@@ -6,17 +6,35 @@ let
homeCfg = config.home;
+ vars =
+ optionalAttrs (homeCfg.sessionVariableSetter == "pam") homeCfg.sessionVariables
+ // config.pam.sessionVariables;
+
in
{
meta.maintainers = [ maintainers.rycee ];
- options = {};
+ options = {
+ pam.sessionVariables = mkOption {
+ default = {};
+ type = types.attrs;
+ example = { EDITOR = "vim"; };
+ description = ''
+ Environment variables that will be set for the PAM session.
+ The variable values must be as described in
+
+ pam_env.conf
+ 5
+ .
+ '';
+ };
+ };
- config = mkIf (homeCfg.sessionVariableSetter == "pam") {
+ config = mkIf (vars != {}) {
home.file.".pam_environment".text =
concatStringsSep "\n" (
- mapAttrsToList (n: v: "${n} OVERRIDE=${v}") homeCfg.sessionVariables
+ mapAttrsToList (n: v: "${n} OVERRIDE=${toString v}") vars
) + "\n";
};
}
diff --git a/modules/programs/bash.nix b/modules/programs/bash.nix
index 90ab5dd75..b5ac9417b 100644
--- a/modules/programs/bash.nix
+++ b/modules/programs/bash.nix
@@ -131,31 +131,26 @@ in
map (v: "shopt -s ${v}") cfg.shellOptions
);
- export = n: v: "export ${n}=\"${toString v}\"";
- setIfNonEmpty = n: v: optionalString (v != "") "${n}=${toString v}";
+ sessionVarsStr = config.lib.shell.exportAll cfg.sessionVariables;
- histControlStr = concatStringsSep ":" cfg.historyControl;
- histIgnoreStr = concatStringsSep ":" cfg.historyIgnore;
-
- # If Bash is the session variable setter then this is the
- # attribute set of global session variables, otherwise it is an
- # empty set.
- globalEnvVars =
- optionalAttrs
- (config.home.sessionVariableSetter == "bash")
- config.home.sessionVariables;
-
- envVarsStr = concatStringsSep "\n" (
- mapAttrsToList export (cfg.sessionVariables // globalEnvVars)
- );
+ historyControlStr =
+ concatStringsSep "\n" (mapAttrsToList (n: v: "${n}=${v}") (
+ {
+ HISTSIZE = toString cfg.historySize;
+ HISTFILESIZE = toString cfg.historyFileSize;
+ }
+ // optionalAttrs (cfg.historyControl != []) {
+ HISTCONTROL = concatStringsSep ":" cfg.historyControl;
+ }
+ // optionalAttrs (cfg.historyIgnore != []) {
+ HISTIGNORE = concatStringsSep ":" cfg.historyIgnore;
+ }
+ ));
in mkIf cfg.enable {
programs.bash.bashrcExtra = ''
# Commands that should be applied only for interactive shells.
if [[ -n $PS1 ]]; then
- HISTSIZE=${toString cfg.historySize}
- HISTFILESIZE=${toString cfg.historyFileSize}
- ${setIfNonEmpty "HISTCONTROL" histControlStr}
- ${setIfNonEmpty "HISTIGNORE" histIgnoreStr}
+ ${historyControlStr}
${shoptsStr}
@@ -181,7 +176,11 @@ in
home.file.".profile".text = ''
# -*- mode: sh -*-
- ${envVarsStr}
+ ${optionalString (config.home.sessionVariableSetter != "pam") ''
+ . "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
+ ''}
+
+ ${sessionVarsStr}
${cfg.profileExtra}
'';
diff --git a/modules/programs/zsh.nix b/modules/programs/zsh.nix
index a088b332a..4c97a921d 100644
--- a/modules/programs/zsh.nix
+++ b/modules/programs/zsh.nix
@@ -11,17 +11,7 @@ let
pluginsDir = if cfg.dotDir != null then
relToDotDir "plugins" else ".zsh/plugins";
- export = n: v: "export ${n}=\"${toString v}\"";
-
- toEnvVarsStr = vars: concatStringsSep "\n" (
- mapAttrsToList export vars
- );
-
- envVars = cfg.sessionVariables // (
- if config.home.sessionVariableSetter == "zsh" then config.home.sessionVariables else {}
- );
-
- envVarsStr = toEnvVarsStr envVars;
+ envVarsStr = config.lib.shell.exportAll cfg.sessionVariables;
aliasesStr = concatStringsSep "\n" (
mapAttrsToList (k: v: "alias ${k}='${v}'") cfg.shellAliases
@@ -255,6 +245,9 @@ in
home.file."${relToDotDir ".zshenv"}".text = ''
typeset -U fpath
+ ${optionalString (config.home.sessionVariableSetter != "pam") ''
+ . "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"
+ ''}
${envVarsStr}
'';
diff --git a/modules/xsession.nix b/modules/xsession.nix
index 9f06e76be..40e522029 100644
--- a/modules/xsession.nix
+++ b/modules/xsession.nix
@@ -82,6 +82,9 @@ in
};
home.file.".xprofile".text = ''
+ ${optionalString (config.home.sessionVariableSetter != "pam")
+ ''. "$HOME/.nix-profile/etc/profile.d/hm-session-vars.sh"''}
+
if [[ -e "$HOME/.profile" ]]; then
. "$HOME/.profile"
fi