nixos module: support NixOS user packages install

When using the NixOS module we cannot guarantee that the Nix store
will be writable during startup. Installing the user packages through
`nix-env -i` will fail in these cases.

This commit adds a NixOS option `home-manager.useUserPackages` that,
when enabled, installs user packages through the NixOS

    users.users.<name?>.packages

option.

Note, when submodule support and external package install is enabled
then the installed packages are not available in `~/.nix-profile`. We
therefore set `home.profileDirectory` directly to the HM profile
packages.
This commit is contained in:
Robert Helgesson 2017-12-19 15:43:40 +01:00
parent 2093cf425f
commit ef168979bf
No known key found for this signature in database
GPG key ID: 36BDAA14C2797E89
4 changed files with 82 additions and 9 deletions

View file

@ -269,7 +269,11 @@ in
home.username = mkDefault (builtins.getEnv "USER"); home.username = mkDefault (builtins.getEnv "USER");
home.homeDirectory = mkDefault (builtins.getEnv "HOME"); home.homeDirectory = mkDefault (builtins.getEnv "HOME");
home.profileDirectory = cfg.homeDirectory + "/.nix-profile"; home.profileDirectory =
if config.submoduleSupport.enable
&& config.submoduleSupport.externalPackageInstall
then config.home.path
else cfg.homeDirectory + "/.nix-profile";
home.sessionVariables = home.sessionVariables =
let let
@ -307,9 +311,33 @@ in
home.activation.writeBoundary = dag.entryAnywhere ""; home.activation.writeBoundary = dag.entryAnywhere "";
# Install packages to the user environment. # Install packages to the user environment.
home.activation.installPackages = dag.entryAfter ["writeBoundary"] '' #
$DRY_RUN_CMD nix-env -i ${cfg.path} # Note, sometimes our target may not allow modification of the Nix
''; # store and then we cannot rely on `nix-env -i`. This is the case,
# for example, if we are running as a NixOS module and building a
# virtual machine. Then we must instead rely on an external
# mechanism for installing packages, which in NixOS is provided by
# the `users.users.<name?>.packages` option. The activation
# command is still needed since some modules need to run their
# activation commands after the packages are guaranteed to be
# installed.
#
# In case the user has moved from a user-install of Home Manager
# to a submodule managed one we attempt to uninstall the
# `home-manager-path` package if it is installed.
home.activation.installPackages = dag.entryAfter ["writeBoundary"] (
if config.submoduleSupport.externalPackageInstall
then
''
if nix-env -q | grep '^home-manager-path$'; then
$DRY_RUN_CMD nix-env -e home-manager-path
fi
''
else
''
$DRY_RUN_CMD nix-env -i ${cfg.path}
''
);
home.activationPackage = home.activationPackage =
let let

View file

@ -966,6 +966,24 @@ in
as an Emacs daemon. as an Emacs daemon.
''; '';
} }
{
time = "2019-02-16T20:33:56+00:00";
condition = hostPlatform.isLinux;
message = ''
When using Home Manager as a NixOS submodule it is now
possible to install packages using the NixOS
users.users.<name?>.packages
option. This is enabled by adding
home-manager.useUserPackages = true;
to your NixOS system configuration. This mode of operation
is necessary if you want to use 'nixos-rebuild build-vm'.
'';
}
]; ];
}; };
} }

View file

@ -15,5 +15,18 @@ with lib;
in, for example, NixOS or nix-darwin. in, for example, NixOS or nix-darwin.
''; '';
}; };
externalPackageInstall = mkOption {
type = types.bool;
default = false;
internal = true;
description = ''
Whether the packages of <option>home.packages</option> are
installed separately from the Home Manager activation script.
In NixOS, for example, this may be accomplished by installing
the packages through
<option>users.users.&lt;name?&gt;.packages</option>.
'';
};
}; };
} }

View file

@ -11,6 +11,7 @@ let
config = { config = {
submoduleSupport.enable = true; submoduleSupport.enable = true;
submoduleSupport.externalPackageInstall = cfg.useUserPackages;
home.username = config.users.users.${name}.name; home.username = config.users.users.${name}.name;
home.homeDirectory = config.users.users.${name}.home; home.homeDirectory = config.users.users.${name}.home;
}; };
@ -20,16 +21,29 @@ in
{ {
options = { options = {
home-manager.users = mkOption { home-manager = {
type = types.attrsOf hmModule; useUserPackages = mkEnableOption ''
default = {}; installation of user packages through the
description = '' <option>users.users.&lt;name?&gt;.packages</option> option.
Per-user Home Manager configuration.
''; '';
users = mkOption {
type = types.attrsOf hmModule;
default = {};
description = ''
Per-user Home Manager configuration.
'';
};
}; };
}; };
config = mkIf (cfg.users != {}) { config = mkIf (cfg.users != {}) {
users.users = mkIf cfg.useUserPackages (
mapAttrs (username: usercfg: {
packages = usercfg.home.packages;
}) cfg.users
);
systemd.services = mapAttrs' (username: usercfg: systemd.services = mapAttrs' (username: usercfg:
nameValuePair ("home-manager-${utils.escapeSystemdPath username}") { nameValuePair ("home-manager-${utils.escapeSystemdPath username}") {
description = "Home Manager environment for ${username}"; description = "Home Manager environment for ${username}";