If you want to rigorously separate system configuration from user configuration - for example to make your user environment portable to machines which you don’t control - you have to install home-manager
in the user environment. It is not required to do this with nix-env
or using nix-channel
. You can also instantiate a nix-shell
with the same version of home-manager
that will handle your environment.
Let’s say your files live in ~/.config
and the entry point to your configuration is ~/.config/home.nix
. Then we can define a version of home-manager
in sources.nix
:
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
{
home-manager = let
src = builtins.fetchGit {
name = "home-manager";
url = https://github.com/rycee/home-manager;
ref = "release-20.03";
};
# `path` is required for `home-manager` to find its own sources
in callPackage "${src}/home-manager" { path = "${src}"; };
}
Then you can instantiate your configuration in nix-shell
by importing that definition:
$ nix-shell -E \
"with import <nixpkgs> {}; mkShell { buildInputs = [ (callPackage ./sources.nix {}).home-manager ]; }" \
--run "home-manager -f ~/.config/home.nix switch"
Of course your home.nix
includes the same home-manager
in the environment:
{ pkgs, ... }:
with pkgs;
let
home-manager = writeShellScriptBin "home-manager" ''
# `toString` is required to impurely track your configuration instead of copying it to `/nix/store`
exec ${(callPackage ../home-sources.nix {}).home-manager}/bin/home-manager -f ${toString ./home.nix} $@
'';
in
{
home.packages = [ home-manager ];
}
That way you can update home-manager
in sources.nix
and just run home-manager switch
to have it available.
This simplified version uses the system’s nixpkgs
, but you could just as well specify one just for that user environment. Don’t forget that home-manager
’s release number should match that of your nixpkgs
, otherwise you may get weird errors due to incompatible package definitions. On my machines I have the nix-shell
invocation as part of an installation script, and also parameterize home-manager
over different machine-specific configurations.