Add standalone home-manager support
Adds support for standalone home-manager configurations.
These configurations are discovered from homes/<username>/(default.nix|home.nix), similarly to how systems are discovered from hosts/<hostname>/(default.nix|configuration.nix|darwin-configuration.nix)
- home.nix: standalone home-manager configuration
- default.nix: an "escape hatch" giving the user complete control over
homeManagerConfigurationcalls
This issue was my attempt to add support in the way described by #35, however I wasn't able to do it exactly as I wanted. Home manager configs need system set to pass pkgs as an argument to HM modules. Instead of adding an option to specify the system of a particular home-manager profile, I used the existing eachSystem function to build profiles for each system specified by the user's systems flake input.
The home-manager CLI expects the flake outputs homeConfigurations.<name> not homeConfigurations.<system>.<name>. To get around this, I merged the nested attrsets so that the output becomes homeConfigurations."<name>@<system>". An example command to build the profile would be home-manager build --flake .#"agaia@x86_64-linux".
I don't love this solution TBH, but I wasn't sure of a good way for the user to specify. It crossed my mind to add a nested folder specifying the system (<repo>/homes/<system>/<name>), but I didn't like that either.
If this HM issue ever gets taken up, it could add some clarity on what to do. https://github.com/nix-community/home-manager/issues/2161_
I have a (kinda ghetto) alternative version I've been using in my own config with a similar expected directory layout to this PR (s/homes/users/). As home-manager cli expects the output path to be .#packages.<system>.homeConfigurations.<name> I decided to just generate an identical homeConfigurations set for every system:
homeConfigurations =
usersPath:
let
usersPathStr = toString usersPath;
userDirs = builtins.attrNames (
lib.filterAttrs (_: type: type == "directory") (builtins.readDir usersPathStr)
);
in
{
packages = lib.genAttrs (import inputs.systems) (system: {
homeConfigurations = lib.genAttrs userDirs (
name:
inputs.home-manager.lib.homeManagerConfiguration {
pkgs = import inputs.nixpkgs {
inherit system;
config.allowUnfree = true;
};
modules = [
"${usersPathStr}/${name}/home.nix"
];
extraSpecialArgs = {
inherit inputs system;
flake = inputs.self;
perSystem = lib.mapAttrs (
_: flake: flake.legacyPackages.${system} or { } // flake.packages.${system} or { }
) inputs;
};
}
);
});
};
and then in my flake.nix I have
outputs =
inputs:
let
lib = inputs.nixpkgs.lib;
slib = import ./lib { inherit inputs; };
in
lib.recursiveUpdate (inputs.blueprint {
inherit inputs;
nixpkgs.config = {
allowUnfree = true;
};
}) (slib.homeConfigurations ./users);
This results in the following:
└───packages
├───x86_64-linux
│ └───homeConfigurations
│ ├───s-desktop
│ └───s-server
# etc...
Closing this for now as #54 has been merged.