From 2bdaf4ae98fad26ded1b0d2a0219484b2252bf64 Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Tue, 19 Dec 2017 15:43:40 +0100 Subject: [PATCH] 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..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. (cherry picked from commit ef168979bf88310459464e5fe3fbcf2d3cbe49b5) --- modules/home-environment.nix | 36 ++++++++++++++++++++++++++---- modules/misc/news.nix | 18 +++++++++++++++ modules/misc/submodule-support.nix | 13 +++++++++++ nixos/default.nix | 24 +++++++++++++++----- 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/modules/home-environment.nix b/modules/home-environment.nix index c98cb9ea..6e8c7cf9 100644 --- a/modules/home-environment.nix +++ b/modules/home-environment.nix @@ -269,7 +269,11 @@ in home.username = mkDefault (builtins.getEnv "USER"); 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 = let @@ -307,9 +311,33 @@ in home.activation.writeBoundary = dag.entryAnywhere ""; # 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..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 = let diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 9f6bdb01..679fadd3 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -966,6 +966,24 @@ in 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..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'. + ''; + } ]; }; } diff --git a/modules/misc/submodule-support.nix b/modules/misc/submodule-support.nix index cffdcb9e..d6138c7c 100644 --- a/modules/misc/submodule-support.nix +++ b/modules/misc/submodule-support.nix @@ -15,5 +15,18 @@ with lib; in, for example, NixOS or nix-darwin. ''; }; + + externalPackageInstall = mkOption { + type = types.bool; + default = false; + internal = true; + description = '' + Whether the packages of are + installed separately from the Home Manager activation script. + In NixOS, for example, this may be accomplished by installing + the packages through + . + ''; + }; }; } diff --git a/nixos/default.nix b/nixos/default.nix index 1e1131f9..5dec943b 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -11,6 +11,7 @@ let config = { submoduleSupport.enable = true; + submoduleSupport.externalPackageInstall = cfg.useUserPackages; home.username = config.users.users.${name}.name; home.homeDirectory = config.users.users.${name}.home; }; @@ -20,16 +21,29 @@ in { options = { - home-manager.users = mkOption { - type = types.attrsOf hmModule; - default = {}; - description = '' - Per-user Home Manager configuration. + home-manager = { + useUserPackages = mkEnableOption '' + installation of user packages through the + option. ''; + + users = mkOption { + type = types.attrsOf hmModule; + default = {}; + description = '' + Per-user Home Manager configuration. + ''; + }; }; }; config = mkIf (cfg.users != {}) { + users.users = mkIf cfg.useUserPackages ( + mapAttrs (username: usercfg: { + packages = usercfg.home.packages; + }) cfg.users + ); + systemd.services = mapAttrs' (username: usercfg: nameValuePair ("home-manager-${utils.escapeSystemdPath username}") { description = "Home Manager environment for ${username}";