Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for generic users without hostname in home-manager configs #74

Open
jzbor opened this issue Feb 11, 2025 · 14 comments
Open

Support for generic users without hostname in home-manager configs #74

jzbor opened this issue Feb 11, 2025 · 14 comments
Labels
enhancement New feature or request

Comments

@jzbor
Copy link

jzbor commented Feb 11, 2025

Is your feature request related to a problem? Please describe.

I currently have one home-manager config that I use for most my machines, which looks like this:

    homeConfigurations.jzbor = home-manager.lib.homeManagerConfiguration (...);

It automatically applies to all users named "jzbor", regardless of the hostname of the machine.
As far as I can tell this does not seem to be supported by blueprint, although it seems to me as a pretty basic and wide-spread use case. The currently used folder structure of blueprint does not seem to allow for this kind of behavior. Of course one could make it work with symlinks and stuff, but I don't think that is a satisfying solution.

Describe the solution you'd like

It would me nice to have a generic folder for home-manager configurations that does not abstract further, e.g. home/*, where * may be jzbor as well as jzbor@t420.

Of course this would be a breaking change so maybe something like hosts/any/users/* would also do.

Describe alternatives you've considered
One could create a symlink or import for every machine.

Additional context
I think #70 is slightly related. There are use-cases for home-manager on non-NixOS machines and there are reasons for keeping a NixOS config separate from a home-manager config even if they are eventually deployed to the same machine. Flakes and home-manager do not enforce such restrictions themselves and I think it is in the spirit of modularity to not do so here.

For context: I am still trying to figure out how to port my NixOS and home-configuration to blueprint, so I am not an active user yet, but very much would like to be if it works out.

@jzbor jzbor added the enhancement New feature or request label Feb 11, 2025
@JumpIn-Git
Copy link

JumpIn-Git commented Feb 11, 2025

you can also make a home-manager module containing the user you want (modules/home/jzbor.nix), and import it on all your host's users/jzbor.nix

@jzbor
Copy link
Author

jzbor commented Feb 12, 2025

you can also make a home-manager module containing the user you want (modules/home/jzbor.nix), and import it on all your host's users/jzbor.nix

Yes, but this still only works for machines managed through the same flake.

In the meantime I have resorted to a simple workaround mapping legacyPackages.homeConfigurations."jzbor" to inputs.self.legacyPackages.${system}.homeConfigurations."jzbor@any": https://github.com/jzbor/nixos-config/blob/be04309e1ac4fa946398a60c4babf77ff6edaf6a/misc/default.nix#L13 .

@phaer
Copy link
Member

phaer commented Feb 12, 2025

you can also make a home-manager module containing the user you want (modules/home/jzbor.nix), and import it on all your host's users/jzbor.nix

Yes, but this still only works for machines managed through the same flake.

Are you sure? You should be able to import homeModules from another flake just as well.

@jzbor
Copy link
Author

jzbor commented Feb 12, 2025

Are you sure? You should be able to import homeModules from another flake just as well.

Yes, but I have for example a Debian machine, which I still use home-manager on. It would be nice if I could also just use the jzbor profile, without having to create a new stub in hosts/<machine>/users/<username>/home-configuration.nix.

@clo4
Copy link
Contributor

clo4 commented Feb 17, 2025

This is all just my opinion - not a maintainer, just someone that likes the project and worked on the home manager stuff.

Personally I think of home configurations as always being tied to a particular machine. A "computer user" fundamentally doesn't exist independently from the computer on which it resides. If you don't have any customisations for a particular device, then it's a matter of when, not if, that will need to change. This structure sets you up for success with practically zero refactoring.

There are use-cases for home-manager on non-NixOS machines and there are reasons for keeping a NixOS config separate from a home-manager config even if they are eventually deployed to the same machine. Flakes and home-manager do not enforce such restrictions themselves and I think it is in the spirit of modularity to not do so here.

Allowing this use-case was actually something I had in mind from the start! That's why it's easy to disable the integration between the two of them like was discussed in that issue (the valuable feedback from that issue was that easy != obvious).

IMO it would be a bit of an antipattern to allow people to take the "easy" path that is 100% going to have to be refactored later on, where the single benefit is that you don't explicitly declare the hostname too.

Having said all that, if the use-case is strong enough then I'm not staunchly opposed to this.

For context: I am still trying to figure out how to port my NixOS and home-configuration to blueprint, so I am not an active user yet, but very much would like to be if it works out.

You've got a pretty large config! Any feedback on it after using it for ~1 week? 🙂

@jzbor
Copy link
Author

jzbor commented Feb 17, 2025

Personally I think of home configurations as always being tied to a particular machine. A "computer user" fundamentally doesn't exist independently from the computer on which it resides. If you don't have any customisations for a particular device, then it's a matter of when, not if, that will need to change. This structure sets you up for success with practically zero refactoring.

While I think that this is a valid mental model of machines/homes, I do use them quite differently. All my NixOS systems are single-user (as I imagine are most desktop NixOS systems). All these systems have different hardware and therefore different NixOS configurations. My home-manager config however always stays the same. One of the benefits of Nix is that I can change something in my config on one computer and it automatically shows up on all others. No need to debug or check why one machine has a program, while another doesn't. I do have some machine-specific additional packages occasionally, but they are mostly either proprietary (e.g. Steam) or project bound/only installed for a short time period, in which case I install them either via nix profile or via nix develop. I don't want to pollute my home-config or system config with proprietary packages anyway, so this is the best way to do that.

So in my mind machine configs (as in NixOS configs) are different for every machine, while I want my home-config to be consistently synced up between all machines. After all at the end it is always the same user (me) using that home.

Having said all that, if the use-case is strong enough then I'm not staunchly opposed to this.

For context: I am still trying to figure out how to port my NixOS and home-configuration to blueprint, so I am not an active user yet, but very much would like to be if it works out.

You've got a pretty large config! Any feedback on it after using it for ~1 week? 🙂

Migration was relatively smooth, as my layout was already pretty similar. I have been using the jzbor@any workaround now for a week as well:
https://github.com/jzbor/nixos-config/blob/773c6f52fc789fbbe3f9a50299aaa6ae4a730600/misc/default.nix#L13

It works quite well, thanks to Nix small overrides like these are not a big issue. That being said, I would still be in favor of mainlining something like this to blueprint, as I still don't think it is that odd of a use case.

I have created a /misc directory with all additional outputs that are not supported by blueprint yet, which I think is a pretty nice pattern:
https://github.com/jzbor/nixos-config/blob/773c6f52fc789fbbe3f9a50299aaa6ae4a730600/misc/default.nix#L13

It might also be a great fit for blueprint as it allows the user to extend blueprint even by unsupported outputs, without polluting the rest of the flake.

@phaer
Copy link
Member

phaer commented Feb 17, 2025

While I think that this is a valid mental model of machines/homes, I do use them quite differently. All my NixOS systems are single-user (as I imagine are most desktop NixOS systems). All these systems have different hardware and therefore different NixOS configurations.

Agreed, I didn't care enough to argue for it in the original PR.

Of course this would be a breaking change so maybe something like hosts/any/users/* would also do.

I don't think a breaking change would be out of the question if it leaves us with a better design for more use-cases (and stays simple enough in terms of implementation as well as upgrade path).

On the other hand, I think when having enough non-nixos/nix-darwin hosts managed by home-manager that hosts/any/users/* brings a tangible benefit over hosts/<machine>/users/<username>/home-configuration.nix, it should be feasible to customize a bit.

@jzbor
Copy link
Author

jzbor commented Feb 17, 2025

On the other hand, I think when having enough non-nixos/nix-darwin hosts managed by home-manager that hosts/any/users/* brings a tangible benefit over hosts/<machine>/users/<username>/home-configuration.nix, it should be feasible to customize a bit.

I am not quite sure, what you mean with the last bit. In my mind there are three possible designs:

  1. /hosts/any/users/<username> gets mapped to homeConfigurations.<username>, which would not be a breaking change (unless someone named their machine "any") and would keep the current scheme.
  2. /users/<home>, where <home> might be either of <user>@<machine> or <user>, which would be a breaking change, but would map more directly onto the home-manager side of things.
  3. Keeping things as they are and maybe suggesting a workaround in the docs (maybe in combination with something like Subdirectory for "miscellaneous" outputs #76 )

@clo4
Copy link
Contributor

clo4 commented Feb 17, 2025

I think something like /users/<username>/home-configuration.nix makes the most sense since a 'users' folder is already common for storing non-host-specific user data (auth keys, secrets, etc).

I've been using this path to store my shared home user config, and have just been importing that directly in my host-specific configs. Maybe we make this the best of both worlds: a way to define users without a host, and an "official" way to share user configuration? (modules are publicly exposed, but your user config likely isn't intended for other flakes to consume)

For my example, something like:

# /users/robert/home-configuration.nix
{ pkgs, ... }:
{
  home.packages = [ pkgs.curl ];
  # ...
}

# /hosts/server/users/robert/home-configuration.nix
{ users, ... }:
{
  imports = [ users.robert ];
  # ...
}

To recap: host-specific stuff is still co-located with the rest of the host's config, and there's now a correct place to define shared, non-specific configuration.

Thoughts?

@clo4
Copy link
Contributor

clo4 commented Feb 17, 2025

I've created a branch to test this out: https://github.com/clo4/blueprint/tree/generic-users

github:clo4/blueprint/generic-users

@jzbor if you want to give this a shot, please let me know what you think!

@JumpIn-Git
Copy link

JumpIn-Git commented Feb 18, 2025

idk how i just though of this, but just do this with your outputs:

  outputs = {
    inputs,
    self,
    cf,
    blueprint,
  }:
    blueprint {inherit inputs;}
    // 
    (inputs.cf.lib.flakeForDefaultSystems (system: 
      {
        legacyPackages.homeConfigurations."jzbor" = inputs.self.legacyPackages.${system}.homeConfigurations."jzbor@any";
      }
    ))

(i dont know if you even need to put brackets around inputs.cf.lib.flakeForDefaultSystems, test yourself)

@JumpIn-Git
Copy link

JumpIn-Git commented Feb 18, 2025

I think something like /users/<username>/home-configuration.nix makes the most sense since a 'users' folder is already common for storing non-host-specific user data (auth keys, secrets, etc).

I've been using this path to store my shared home user config, and have just been importing that directly in my host-specific configs. Maybe we make this the best of both worlds: a way to define users without a host, and an "official" way to share user configuration? (modules are publicly exposed, but your user config likely isn't intended for other flakes to consume)

For my example, something like:

/users/robert/home-configuration.nix

{ pkgs, ... }:
{
home.packages = [ pkgs.curl ];

...

}

/hosts/server/users/robert/home-configuration.nix

{ users, ... }:
{
imports = [ users.robert ];

...

}
To recap: host-specific stuff is still co-located with the rest of the host's config, and there's now a correct place to define shared, non-specific configuration.

Thoughts?

this would also fix my issue of using standalone home-manager on nixos! amazing idea imo

@jzbor
Copy link
Author

jzbor commented Feb 18, 2025

@JumpIn-Git I think this is pretty much the workaround I am using right now, which I have commented on extensively yesterday.

@clo4 Thanks alot, I will take a look at it!

@jzbor
Copy link
Author

jzbor commented Feb 18, 2025

@jzbor if you want to give this a shot, please let me know what you think!

Hi, I just tested it in jzbor/nixos-config/generic-users. It works as expected. /users/jzbor is available without a hostname, while /hosts/pinenote/users/jzbor is still exported as jzbor@pinenote. Seems great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants