blueprint icon indicating copy to clipboard operation
blueprint copied to clipboard

Add standalone home-manager support

Open adam-gaia opened this issue 1 year ago • 1 comments

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 homeManagerConfiguration calls

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_

adam-gaia avatar Aug 30 '24 23:08 adam-gaia

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...

srounce avatar Sep 21 '24 13:09 srounce

Closing this for now as #54 has been merged.

phaer avatar Jan 27 '25 12:01 phaer