First let me describe my current NixOS installation, in my configuration.nix
I set the NIX_PATH like this:
nix.nixPath = [
"nixpkgs=/path/to/my/nixpkgs"
"nixpkgs-overlays=/path/to/my/overlays"
];
because I don’t use channels, and I want to try my own nixpkgs modifications before opening a PR.
I want to achieve something similar with home-manager
, but I’m a bit confused because reading the project documentation seems like there are only two options to install it:
- using channels: I’d like to avoid channels since I don’t use the
nix-channel
command anymore
- Install it as NixOS module: In that case, I’ll need to run
sudo nixos-rebuild switch
to update my user config, while I’d prefer to use the home-manager
command
There is also a home-manager
package on nixpkgs, but that is not mentioned in the documentation, what is its purpose?
For now, I came with this solution:
nix.nixPath = [
"nixpkgs=/path/to/my/nixpkgs"
"nixpkgs-overlays=/path/to/my/overlays"
"home-manager=/path/to/my/home-manager"
];
users.users.myuser.packages = [
(pkgs.writeScriptBin "home-manager" ''
#!${pkgs.bash}/bin/bash
export HOME_MANAGER_CONFIG=/path/to/my/dotfiles/home.nix
exec ${pkgs.home-manager}/bin/home-manager "$@"
'')
];
};
I’m also wrapping the home-manager
executable to modify the default home-manager config path. The problem here is that I think that I’m not using my local home-manager checkout, but the once provided by nixpkgs.
One last question, looks like home-manager is doing 2 different things, managing your dotfiles and installing some programs (like with nix-env -i
). Is it ok if I install git
with environment.systemPackages
and then use home-manager
to only manage my .gitconfig
file? Or is it recommended to not mix systemPackages
and home-manager
?
1 Like
Indeed. What you could do is set pam.sessionVariables.HOME_MANAGER_CONFIG
in your home-manager configuration. There is a bit of a bootstrap problem though.
Same with the nix.nixPath
, that only gets set after the nixos configuration has been switched and after a fresh user session has been created.
Another option is to put that wrapper script into the repository that contains all your nix configuration. This would force you to go to that folder to do the switch but it solves the bootstrap problem.
One last question, looks like home-manager is doing 2 different things, managing your dotfiles and installing some programs (like with nix-env -i
). Is it ok if I install git
with environment.systemPackages
and then use home-manager
to only manage my .gitconfig
file? Or is it recommended to not mix systemPackages
and home-manager
?
In general, if a program is enabled in home-manager, home-manager tends to also install it in the user profile. If git
is also installed on the system level it’s not a problem as it will be shadowed by the one provided by home-manager (because of the ordering in the PATH).
thanks for your answer, I liked the wrapper idea, and end with this solution:
let
home-manager = { home-manager-path, config-path }:
(pkgs.callPackage (/. + home-manager-path + "/home-manager") { path = "${home-manager-path}"; }).overrideAttrs (old: {
nativeBuildInputs = [ pkgs.makeWrapper ];
buildCommand = ''
${old.buildCommand}
wrapProgram $out/bin/home-manager --set HOME_MANAGER_CONFIG "${config-path}"
'';
});
in rec
{
# ...
users.users.${mainUser} = {
# ...
packages = [
(home-manager {
home-manager-path = "/local/checkout/home-manager";
config-path = "/local/dotfiles/home.nix";
})
];
};
}
It seems to work as expected, using my local home-manager
version.
I notice that setting home-manager
on NIX_PATH
is useless, because it will be overridden by home-manager
script:
home-manager/home-manager at 6c7a0313673687368a33197e58bc28f4290ec244 · nix-community/home-manager · GitHub
I have one last question, why are you using pam.sessionVariables
and not home.sessionVariables
or systemd.user.sessionVariables
? I’m not sure which one to use
Mostly cargo-culting from previous configs. Looking at the home-manager modules it seems like home.sessionVariables
is the one being used now. Probably the pam-one is only usable on Linux whereas home.sessionVariables seems to be more generic.
1 Like
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.
3 Likes